2019-06-26 21:08:36 +08:00
|
|
|
//==- SemanticHighlightingTests.cpp - SemanticHighlighting tests-*- C++ -* -==//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Annotations.h"
|
2019-06-27 23:13:03 +08:00
|
|
|
#include "ClangdServer.h"
|
2019-07-04 15:53:12 +08:00
|
|
|
#include "Protocol.h"
|
2019-06-26 21:08:36 +08:00
|
|
|
#include "SemanticHighlighting.h"
|
2019-09-09 16:47:05 +08:00
|
|
|
#include "SourceCode.h"
|
2019-06-27 23:13:03 +08:00
|
|
|
#include "TestFS.h"
|
2019-06-26 21:08:36 +08:00
|
|
|
#include "TestTU.h"
|
2019-09-09 16:47:05 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
2019-06-26 21:08:36 +08:00
|
|
|
#include "gmock/gmock.h"
|
2019-09-09 16:47:05 +08:00
|
|
|
#include <algorithm>
|
2019-06-26 21:08:36 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
2019-08-26 16:38:45 +08:00
|
|
|
MATCHER_P(LineNumber, L, "") { return arg.Line == L; }
|
|
|
|
MATCHER(EmptyHighlightings, "") { return arg.Tokens.empty(); }
|
|
|
|
|
2019-06-26 21:08:36 +08:00
|
|
|
std::vector<HighlightingToken>
|
|
|
|
makeHighlightingTokens(llvm::ArrayRef<Range> Ranges, HighlightingKind Kind) {
|
|
|
|
std::vector<HighlightingToken> Tokens(Ranges.size());
|
|
|
|
for (int I = 0, End = Ranges.size(); I < End; ++I) {
|
|
|
|
Tokens[I].R = Ranges[I];
|
|
|
|
Tokens[I].Kind = Kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Tokens;
|
|
|
|
}
|
|
|
|
|
2019-08-01 16:08:44 +08:00
|
|
|
std::vector<HighlightingToken> getExpectedTokens(Annotations &Test) {
|
2019-06-26 21:08:36 +08:00
|
|
|
static const std::map<HighlightingKind, std::string> KindToString{
|
|
|
|
{HighlightingKind::Variable, "Variable"},
|
2019-08-30 11:37:24 +08:00
|
|
|
{HighlightingKind::LocalVariable, "LocalVariable"},
|
2019-08-19 15:51:39 +08:00
|
|
|
{HighlightingKind::Parameter, "Parameter"},
|
2019-07-10 16:41:25 +08:00
|
|
|
{HighlightingKind::Function, "Function"},
|
|
|
|
{HighlightingKind::Class, "Class"},
|
2019-07-11 17:29:16 +08:00
|
|
|
{HighlightingKind::Enum, "Enum"},
|
2019-07-15 15:41:12 +08:00
|
|
|
{HighlightingKind::Namespace, "Namespace"},
|
2019-07-15 16:12:21 +08:00
|
|
|
{HighlightingKind::EnumConstant, "EnumConstant"},
|
|
|
|
{HighlightingKind::Field, "Field"},
|
2019-08-30 11:37:24 +08:00
|
|
|
{HighlightingKind::StaticField, "StaticField"},
|
2019-07-18 17:56:38 +08:00
|
|
|
{HighlightingKind::Method, "Method"},
|
2019-08-30 11:37:24 +08:00
|
|
|
{HighlightingKind::StaticMethod, "StaticMethod"},
|
2019-10-15 02:26:13 +08:00
|
|
|
{HighlightingKind::Typedef, "Typedef"},
|
|
|
|
{HighlightingKind::DependentType, "DependentType"},
|
|
|
|
{HighlightingKind::DependentName, "DependentName"},
|
2019-08-08 21:10:30 +08:00
|
|
|
{HighlightingKind::TemplateParameter, "TemplateParameter"},
|
2020-01-22 02:21:08 +08:00
|
|
|
{HighlightingKind::Concept, "Concept"},
|
2019-08-30 23:47:27 +08:00
|
|
|
{HighlightingKind::Primitive, "Primitive"},
|
|
|
|
{HighlightingKind::Macro, "Macro"}};
|
2019-06-26 21:08:36 +08:00
|
|
|
std::vector<HighlightingToken> ExpectedTokens;
|
|
|
|
for (const auto &KindString : KindToString) {
|
2019-07-10 16:41:25 +08:00
|
|
|
std::vector<HighlightingToken> Toks = makeHighlightingTokens(
|
|
|
|
Test.ranges(KindString.second), KindString.first);
|
2019-06-26 21:08:36 +08:00
|
|
|
ExpectedTokens.insert(ExpectedTokens.end(), Toks.begin(), Toks.end());
|
|
|
|
}
|
2019-08-01 16:08:44 +08:00
|
|
|
llvm::sort(ExpectedTokens);
|
|
|
|
return ExpectedTokens;
|
|
|
|
}
|
|
|
|
|
2019-09-09 16:47:05 +08:00
|
|
|
/// Annotates the input code with provided semantic highlightings. Results look
|
|
|
|
/// something like:
|
|
|
|
/// class $Class[[X]] {
|
|
|
|
/// $Primitive[[int]] $Field[[a]] = 0;
|
|
|
|
/// };
|
|
|
|
std::string annotate(llvm::StringRef Input,
|
|
|
|
llvm::ArrayRef<HighlightingToken> Tokens) {
|
|
|
|
assert(std::is_sorted(
|
|
|
|
Tokens.begin(), Tokens.end(),
|
|
|
|
[](const HighlightingToken &L, const HighlightingToken &R) {
|
|
|
|
return L.R.start < R.R.start;
|
|
|
|
}));
|
|
|
|
|
|
|
|
std::string Result;
|
|
|
|
unsigned NextChar = 0;
|
|
|
|
for (auto &T : Tokens) {
|
|
|
|
unsigned StartOffset = llvm::cantFail(positionToOffset(Input, T.R.start));
|
|
|
|
unsigned EndOffset = llvm::cantFail(positionToOffset(Input, T.R.end));
|
|
|
|
assert(StartOffset <= EndOffset);
|
|
|
|
assert(NextChar <= StartOffset);
|
|
|
|
|
|
|
|
Result += Input.substr(NextChar, StartOffset - NextChar);
|
|
|
|
Result += llvm::formatv("${0}[[{1}]]", T.Kind,
|
|
|
|
Input.substr(StartOffset, EndOffset - StartOffset));
|
|
|
|
NextChar = EndOffset;
|
|
|
|
}
|
|
|
|
Result += Input.substr(NextChar);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2019-08-12 21:01:11 +08:00
|
|
|
void checkHighlightings(llvm::StringRef Code,
|
|
|
|
std::vector<std::pair</*FileName*/ llvm::StringRef,
|
|
|
|
/*FileContent*/ llvm::StringRef>>
|
|
|
|
AdditionalFiles = {}) {
|
2019-08-01 16:08:44 +08:00
|
|
|
Annotations Test(Code);
|
2019-10-13 21:15:27 +08:00
|
|
|
TestTU TU;
|
|
|
|
TU.Code = Test.code();
|
|
|
|
|
|
|
|
// FIXME: Auto-completion in a template requires disabling delayed template
|
|
|
|
// parsing.
|
|
|
|
TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
|
2020-01-22 02:21:08 +08:00
|
|
|
TU.ExtraArgs.push_back("-std=c++2a");
|
2019-10-13 21:15:27 +08:00
|
|
|
|
2019-08-12 21:01:11 +08:00
|
|
|
for (auto File : AdditionalFiles)
|
|
|
|
TU.AdditionalFiles.insert({File.first, File.second});
|
|
|
|
auto AST = TU.build();
|
2019-09-09 16:47:05 +08:00
|
|
|
|
|
|
|
EXPECT_EQ(Code, annotate(Test.code(), getSemanticHighlightings(AST)));
|
2019-08-01 16:08:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Any annotations in OldCode and NewCode are converted into their corresponding
|
|
|
|
// HighlightingToken. The tokens are diffed against each other. Any lines where
|
|
|
|
// the tokens should diff must be marked with a ^ somewhere on that line in
|
|
|
|
// NewCode. If there are diffs that aren't marked with ^ the test fails. The
|
|
|
|
// test also fails if there are lines marked with ^ that don't differ.
|
|
|
|
void checkDiffedHighlights(llvm::StringRef OldCode, llvm::StringRef NewCode) {
|
|
|
|
Annotations OldTest(OldCode);
|
|
|
|
Annotations NewTest(NewCode);
|
|
|
|
std::vector<HighlightingToken> OldTokens = getExpectedTokens(OldTest);
|
|
|
|
std::vector<HighlightingToken> NewTokens = getExpectedTokens(NewTest);
|
|
|
|
|
|
|
|
llvm::DenseMap<int, std::vector<HighlightingToken>> ExpectedLines;
|
|
|
|
for (const Position &Point : NewTest.points()) {
|
|
|
|
ExpectedLines[Point.line]; // Default initialize to an empty line. Tokens
|
|
|
|
// are inserted on these lines later.
|
|
|
|
}
|
|
|
|
std::vector<LineHighlightings> ExpectedLinePairHighlighting;
|
|
|
|
for (const HighlightingToken &Token : NewTokens) {
|
|
|
|
auto It = ExpectedLines.find(Token.R.start.line);
|
|
|
|
if (It != ExpectedLines.end())
|
|
|
|
It->second.push_back(Token);
|
|
|
|
}
|
|
|
|
for (auto &LineTokens : ExpectedLines)
|
|
|
|
ExpectedLinePairHighlighting.push_back(
|
2019-09-25 06:17:55 +08:00
|
|
|
{LineTokens.first, LineTokens.second, /*IsInactive = */ false});
|
2019-06-26 21:08:36 +08:00
|
|
|
|
2019-08-01 16:08:44 +08:00
|
|
|
std::vector<LineHighlightings> ActualDiffed =
|
2019-08-26 16:38:45 +08:00
|
|
|
diffHighlightings(NewTokens, OldTokens);
|
2019-08-01 16:08:44 +08:00
|
|
|
EXPECT_THAT(ActualDiffed,
|
2019-08-26 16:38:45 +08:00
|
|
|
testing::UnorderedElementsAreArray(ExpectedLinePairHighlighting))
|
|
|
|
<< OldCode;
|
2019-06-26 21:08:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SemanticHighlighting, GetsCorrectTokens) {
|
|
|
|
const char *TestCases[] = {
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-07-10 16:41:25 +08:00
|
|
|
struct $Class[[AS]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
double $Field[[SomeMember]];
|
2019-07-05 21:06:03 +08:00
|
|
|
};
|
|
|
|
struct {
|
|
|
|
} $Variable[[S]];
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]](int $Parameter[[A]], $Class[[AS]] $Parameter[[As]]) {
|
2019-08-28 03:39:11 +08:00
|
|
|
$Primitive[[auto]] $LocalVariable[[VeryLongVariableName]] = 12312;
|
|
|
|
$Class[[AS]] $LocalVariable[[AA]];
|
|
|
|
$Primitive[[auto]] $LocalVariable[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]];
|
2019-10-28 18:31:06 +08:00
|
|
|
auto $LocalVariable[[FN]] = [ $LocalVariable[[AA]]](int $Parameter[[A]]) -> void {};
|
2019-08-28 03:39:11 +08:00
|
|
|
$LocalVariable[[FN]](12312);
|
2019-07-05 21:06:03 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]](int);
|
|
|
|
void $Function[[Gah]]();
|
|
|
|
void $Function[[foo]]() {
|
2019-08-28 03:39:11 +08:00
|
|
|
auto $LocalVariable[[Bou]] = $Function[[Gah]];
|
2019-07-05 21:06:03 +08:00
|
|
|
}
|
2019-07-10 16:41:25 +08:00
|
|
|
struct $Class[[A]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[abc]]();
|
2019-07-10 16:41:25 +08:00
|
|
|
};
|
2019-07-05 21:06:03 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-07-11 17:29:16 +08:00
|
|
|
namespace $Namespace[[abc]] {
|
2019-07-18 17:56:38 +08:00
|
|
|
template<typename $TemplateParameter[[T]]>
|
2019-07-10 16:41:25 +08:00
|
|
|
struct $Class[[A]] {
|
2019-07-18 17:56:38 +08:00
|
|
|
$TemplateParameter[[T]] $Field[[t]];
|
2019-07-10 16:41:25 +08:00
|
|
|
};
|
|
|
|
}
|
2019-07-18 17:56:38 +08:00
|
|
|
template<typename $TemplateParameter[[T]]>
|
|
|
|
struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
|
2019-10-15 02:26:13 +08:00
|
|
|
typename $TemplateParameter[[T]]::$DependentType[[A]]* $Field[[D]];
|
2019-07-10 16:41:25 +08:00
|
|
|
};
|
2019-10-28 18:31:06 +08:00
|
|
|
$Namespace[[abc]]::$Class[[A]]<int> $Variable[[AA]];
|
|
|
|
typedef $Namespace[[abc]]::$Class[[A]]<int> $Class[[AAA]];
|
2019-07-10 16:41:25 +08:00
|
|
|
struct $Class[[B]] {
|
|
|
|
$Class[[B]]();
|
|
|
|
~$Class[[B]]();
|
2019-10-28 18:31:06 +08:00
|
|
|
void operator<<($Class[[B]]);
|
2019-07-15 16:12:21 +08:00
|
|
|
$Class[[AAA]] $Field[[AA]];
|
2019-07-10 16:41:25 +08:00
|
|
|
};
|
|
|
|
$Class[[B]]::$Class[[B]]() {}
|
|
|
|
$Class[[B]]::~$Class[[B]]() {}
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[f]] () {
|
2019-08-28 03:39:11 +08:00
|
|
|
$Class[[B]] $LocalVariable[[BB]] = $Class[[B]]();
|
|
|
|
$LocalVariable[[BB]].~$Class[[B]]();
|
2019-07-10 16:41:25 +08:00
|
|
|
$Class[[B]]();
|
|
|
|
}
|
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-07-15 15:41:12 +08:00
|
|
|
enum class $Enum[[E]] {
|
|
|
|
$EnumConstant[[A]],
|
|
|
|
$EnumConstant[[B]],
|
|
|
|
};
|
|
|
|
enum $Enum[[EE]] {
|
|
|
|
$EnumConstant[[Hi]],
|
|
|
|
};
|
2019-07-10 16:41:25 +08:00
|
|
|
struct $Class[[A]] {
|
2019-07-15 16:12:21 +08:00
|
|
|
$Enum[[E]] $Field[[EEE]];
|
|
|
|
$Enum[[EE]] $Field[[EEEE]];
|
2019-07-05 21:06:03 +08:00
|
|
|
};
|
2019-10-28 18:31:06 +08:00
|
|
|
int $Variable[[I]] = $EnumConstant[[Hi]];
|
2019-07-15 15:41:12 +08:00
|
|
|
$Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]];
|
2019-07-11 17:29:16 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-07-11 17:29:16 +08:00
|
|
|
namespace $Namespace[[abc]] {
|
|
|
|
namespace {}
|
|
|
|
namespace $Namespace[[bcd]] {
|
|
|
|
struct $Class[[A]] {};
|
|
|
|
namespace $Namespace[[cde]] {
|
|
|
|
struct $Class[[A]] {
|
|
|
|
enum class $Enum[[B]] {
|
2019-07-15 15:41:12 +08:00
|
|
|
$EnumConstant[[Hi]],
|
2019-07-11 17:29:16 +08:00
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
using namespace $Namespace[[abc]]::$Namespace[[bcd]];
|
|
|
|
namespace $Namespace[[vwz]] =
|
|
|
|
$Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]];
|
|
|
|
$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[AA]];
|
|
|
|
$Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable[[AAA]] =
|
2019-07-15 15:41:12 +08:00
|
|
|
$Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::$EnumConstant[[Hi]];
|
2019-07-11 17:29:16 +08:00
|
|
|
::$Namespace[[vwz]]::$Class[[A]] $Variable[[B]];
|
|
|
|
::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[BB]];
|
2019-07-15 16:12:21 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-07-15 16:12:21 +08:00
|
|
|
struct $Class[[D]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
double $Field[[C]];
|
2019-07-15 16:12:21 +08:00
|
|
|
};
|
|
|
|
struct $Class[[A]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
double $Field[[B]];
|
2019-07-15 16:12:21 +08:00
|
|
|
$Class[[D]] $Field[[E]];
|
2019-10-28 18:31:06 +08:00
|
|
|
static double $StaticField[[S]];
|
|
|
|
static void $StaticMethod[[bar]]() {}
|
|
|
|
void $Method[[foo]]() {
|
2019-07-15 16:12:21 +08:00
|
|
|
$Field[[B]] = 123;
|
|
|
|
this->$Field[[B]] = 156;
|
|
|
|
this->$Method[[foo]]();
|
|
|
|
$Method[[foo]]();
|
2019-08-30 11:37:24 +08:00
|
|
|
$StaticMethod[[bar]]();
|
|
|
|
$StaticField[[S]] = 90.1;
|
2019-07-15 16:12:21 +08:00
|
|
|
}
|
|
|
|
};
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]]() {
|
2019-08-28 03:39:11 +08:00
|
|
|
$Class[[A]] $LocalVariable[[AA]];
|
|
|
|
$LocalVariable[[AA]].$Field[[B]] += 2;
|
|
|
|
$LocalVariable[[AA]].$Method[[foo]]();
|
|
|
|
$LocalVariable[[AA]].$Field[[E]].$Field[[C]];
|
2019-08-30 11:37:24 +08:00
|
|
|
$Class[[A]]::$StaticField[[S]] = 90;
|
2019-07-15 16:12:21 +08:00
|
|
|
}
|
2019-07-15 23:08:27 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-07-15 23:08:27 +08:00
|
|
|
struct $Class[[AA]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
int $Field[[A]];
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
Summary:
The historic behavior of TestTU is to gather diagnostics and otherwise ignore
them. So if a test has a syntax error, and doesn't assert diagnostics, it
silently misbehaves.
This can be annoying when developing tests, as evidenced by various tests
gaining "assert no diagnostics" where that's not really the point of the test.
This patch aims to make that default behavior. For the first error
(not warning), TestTU will call ADD_FAILURE().
This can be suppressed with a comment containing "error-ok". For now that will
suppress any errors in the TU. We can make this stricter later -verify style.
(-verify itself is hard to reuse because of DiagnosticConsumer interfaces...)
A magic-comment was chosen over a TestTU option because of table-driven tests.
In addition to the behavior change, this patch:
- adds //error-ok where we're knowingly testing invalid code
(e.g. for diagnostics, crash-resilience, or token-level tests)
- fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;)
- removes a bunch of now-redundant instances of "assert no diagnostics"
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73199
2020-01-22 23:38:41 +08:00
|
|
|
};
|
2019-10-28 18:31:06 +08:00
|
|
|
int $Variable[[B]];
|
2019-07-15 23:08:27 +08:00
|
|
|
$Class[[AA]] $Variable[[A]]{$Variable[[B]]};
|
2019-07-16 21:23:12 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-07-16 21:23:12 +08:00
|
|
|
namespace $Namespace[[a]] {
|
|
|
|
struct $Class[[A]] {};
|
2019-10-28 18:31:06 +08:00
|
|
|
typedef char $Primitive[[C]];
|
2019-07-16 21:23:12 +08:00
|
|
|
}
|
|
|
|
typedef $Namespace[[a]]::$Class[[A]] $Class[[B]];
|
|
|
|
using $Class[[BB]] = $Namespace[[a]]::$Class[[A]];
|
|
|
|
enum class $Enum[[E]] {};
|
|
|
|
typedef $Enum[[E]] $Enum[[C]];
|
|
|
|
typedef $Enum[[C]] $Enum[[CC]];
|
|
|
|
using $Enum[[CD]] = $Enum[[CC]];
|
|
|
|
$Enum[[CC]] $Function[[f]]($Class[[B]]);
|
|
|
|
$Enum[[CD]] $Function[[f]]($Class[[BB]]);
|
2019-08-08 21:10:30 +08:00
|
|
|
typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]];
|
2019-10-28 18:31:06 +08:00
|
|
|
typedef float $Primitive[[F]];
|
2019-07-18 17:56:38 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-10-28 18:31:06 +08:00
|
|
|
template<typename $TemplateParameter[[T]], typename = void>
|
2019-07-18 17:56:38 +08:00
|
|
|
class $Class[[A]] {
|
|
|
|
$TemplateParameter[[T]] $Field[[AA]];
|
|
|
|
$TemplateParameter[[T]] $Method[[foo]]();
|
|
|
|
};
|
|
|
|
template<class $TemplateParameter[[TT]]>
|
|
|
|
class $Class[[B]] {
|
|
|
|
$Class[[A]]<$TemplateParameter[[TT]]> $Field[[AA]];
|
|
|
|
};
|
|
|
|
template<class $TemplateParameter[[TT]], class $TemplateParameter[[GG]]>
|
|
|
|
class $Class[[BB]] {};
|
|
|
|
template<class $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
class $Class[[BB]]<$TemplateParameter[[T]], int> {};
|
2019-07-18 17:56:38 +08:00
|
|
|
template<class $TemplateParameter[[T]]>
|
|
|
|
class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {};
|
|
|
|
|
|
|
|
template<template<class> class $TemplateParameter[[T]], class $TemplateParameter[[C]]>
|
|
|
|
$TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function[[f]]();
|
|
|
|
|
|
|
|
template<typename>
|
|
|
|
class $Class[[Foo]] {};
|
|
|
|
|
|
|
|
template<typename $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]]($TemplateParameter[[T]] ...);
|
2019-08-08 15:21:06 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-08-08 15:21:06 +08:00
|
|
|
template <class $TemplateParameter[[T]]>
|
|
|
|
struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;};
|
2019-10-28 18:31:06 +08:00
|
|
|
extern template struct $Class[[Tmpl]]<float>;
|
|
|
|
template struct $Class[[Tmpl]]<double>;
|
2019-08-08 20:43:55 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
// This test is to guard against highlightings disappearing when using
|
|
|
|
// conversion operators as their behaviour in the clang AST differ from
|
|
|
|
// other CXXMethodDecls.
|
|
|
|
R"cpp(
|
2019-08-08 20:43:55 +08:00
|
|
|
class $Class[[Foo]] {};
|
|
|
|
struct $Class[[Bar]] {
|
|
|
|
explicit operator $Class[[Foo]]*() const;
|
2019-10-28 18:31:06 +08:00
|
|
|
explicit operator int() const;
|
2019-08-08 20:43:55 +08:00
|
|
|
operator $Class[[Foo]]();
|
|
|
|
};
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[f]]() {
|
2019-08-28 03:39:11 +08:00
|
|
|
$Class[[Bar]] $LocalVariable[[B]];
|
|
|
|
$Class[[Foo]] $LocalVariable[[F]] = $LocalVariable[[B]];
|
|
|
|
$Class[[Foo]] *$LocalVariable[[FP]] = ($Class[[Foo]]*)$LocalVariable[[B]];
|
2019-10-28 18:31:06 +08:00
|
|
|
int $LocalVariable[[I]] = (int)$LocalVariable[[B]];
|
2019-08-08 20:43:55 +08:00
|
|
|
}
|
2019-08-09 15:30:28 +08:00
|
|
|
)cpp"
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-08-09 15:30:28 +08:00
|
|
|
struct $Class[[B]] {};
|
|
|
|
struct $Class[[A]] {
|
|
|
|
$Class[[B]] $Field[[BB]];
|
2019-08-19 15:51:39 +08:00
|
|
|
$Class[[A]] &operator=($Class[[A]] &&$Parameter[[O]]);
|
2019-08-09 15:30:28 +08:00
|
|
|
};
|
|
|
|
|
2019-08-19 15:51:39 +08:00
|
|
|
$Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter[[O]]) = default;
|
2019-08-09 20:19:10 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-08-09 20:19:10 +08:00
|
|
|
enum $Enum[[En]] {
|
|
|
|
$EnumConstant[[EC]],
|
|
|
|
};
|
|
|
|
class $Class[[Foo]] {};
|
|
|
|
class $Class[[Bar]] {
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
Summary:
The historic behavior of TestTU is to gather diagnostics and otherwise ignore
them. So if a test has a syntax error, and doesn't assert diagnostics, it
silently misbehaves.
This can be annoying when developing tests, as evidenced by various tests
gaining "assert no diagnostics" where that's not really the point of the test.
This patch aims to make that default behavior. For the first error
(not warning), TestTU will call ADD_FAILURE().
This can be suppressed with a comment containing "error-ok". For now that will
suppress any errors in the TU. We can make this stricter later -verify style.
(-verify itself is hard to reuse because of DiagnosticConsumer interfaces...)
A magic-comment was chosen over a TestTU option because of table-driven tests.
In addition to the behavior change, this patch:
- adds //error-ok where we're knowingly testing invalid code
(e.g. for diagnostics, crash-resilience, or token-level tests)
- fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;)
- removes a bunch of now-redundant instances of "assert no diagnostics"
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73199
2020-01-22 23:38:41 +08:00
|
|
|
public:
|
2019-08-09 20:19:10 +08:00
|
|
|
$Class[[Foo]] $Field[[Fo]];
|
|
|
|
$Enum[[En]] $Field[[E]];
|
2019-10-28 18:31:06 +08:00
|
|
|
int $Field[[I]];
|
2019-08-19 15:51:39 +08:00
|
|
|
$Class[[Bar]] ($Class[[Foo]] $Parameter[[F]],
|
|
|
|
$Enum[[En]] $Parameter[[E]])
|
|
|
|
: $Field[[Fo]] ($Parameter[[F]]), $Field[[E]] ($Parameter[[E]]),
|
2019-08-09 20:19:10 +08:00
|
|
|
$Field[[I]] (123) {}
|
|
|
|
};
|
|
|
|
class $Class[[Bar2]] : public $Class[[Bar]] {
|
|
|
|
$Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) {}
|
|
|
|
};
|
2019-08-12 15:45:12 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-08-12 15:45:12 +08:00
|
|
|
enum $Enum[[E]] {
|
|
|
|
$EnumConstant[[E]],
|
|
|
|
};
|
|
|
|
class $Class[[Foo]] {};
|
|
|
|
$Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]];
|
|
|
|
$Class[[auto]] $Variable[[AF]] = $Class[[Foo]]();
|
|
|
|
$Class[[decltype]](auto) $Variable[[AF2]] = $Class[[Foo]]();
|
|
|
|
$Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]];
|
|
|
|
$Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]];
|
|
|
|
$Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
|
|
|
|
$Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
|
2019-10-28 18:31:06 +08:00
|
|
|
auto $Variable[[Fun]] = []()->void{};
|
2019-08-16 17:30:21 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-08-16 17:30:21 +08:00
|
|
|
class $Class[[G]] {};
|
|
|
|
template<$Class[[G]] *$TemplateParameter[[U]]>
|
|
|
|
class $Class[[GP]] {};
|
|
|
|
template<$Class[[G]] &$TemplateParameter[[U]]>
|
|
|
|
class $Class[[GR]] {};
|
2019-10-28 18:31:06 +08:00
|
|
|
template<int *$TemplateParameter[[U]]>
|
2019-08-16 17:30:21 +08:00
|
|
|
class $Class[[IP]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[f]]() {
|
2019-08-16 17:30:21 +08:00
|
|
|
*$TemplateParameter[[U]] += 5;
|
|
|
|
}
|
|
|
|
};
|
2019-10-28 18:31:06 +08:00
|
|
|
template<unsigned $TemplateParameter[[U]] = 2>
|
2019-08-16 17:30:21 +08:00
|
|
|
class $Class[[Foo]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[f]]() {
|
|
|
|
for(int $LocalVariable[[I]] = 0;
|
2019-08-28 03:39:11 +08:00
|
|
|
$LocalVariable[[I]] < $TemplateParameter[[U]];) {}
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
$Class[[G]] $Variable[[L]];
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[f]]() {
|
2019-08-28 03:39:11 +08:00
|
|
|
$Class[[Foo]]<123> $LocalVariable[[F]];
|
|
|
|
$Class[[GP]]<&$Variable[[L]]> $LocalVariable[[LL]];
|
|
|
|
$Class[[GR]]<$Variable[[L]]> $LocalVariable[[LLL]];
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-12-07 04:43:02 +08:00
|
|
|
template<typename $TemplateParameter[[T]],
|
|
|
|
void ($TemplateParameter[[T]]::*$TemplateParameter[[method]])(int)>
|
2019-08-16 17:30:21 +08:00
|
|
|
struct $Class[[G]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[foo]](
|
2019-08-19 15:51:39 +08:00
|
|
|
$TemplateParameter[[T]] *$Parameter[[O]]) {
|
|
|
|
($Parameter[[O]]->*$TemplateParameter[[method]])(10);
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
struct $Class[[F]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[f]](int);
|
2019-08-16 17:30:21 +08:00
|
|
|
};
|
2019-10-28 18:31:06 +08:00
|
|
|
template<void (*$TemplateParameter[[Func]])()>
|
2019-08-16 17:30:21 +08:00
|
|
|
struct $Class[[A]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[f]]() {
|
2019-08-16 17:30:21 +08:00
|
|
|
(*$TemplateParameter[[Func]])();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]]() {
|
2019-08-28 03:39:11 +08:00
|
|
|
$Class[[F]] $LocalVariable[[FF]];
|
|
|
|
$Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $LocalVariable[[GG]];
|
|
|
|
$LocalVariable[[GG]].$Method[[foo]](&$LocalVariable[[FF]]);
|
|
|
|
$Class[[A]]<$Function[[foo]]> $LocalVariable[[AA]];
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
Summary:
The historic behavior of TestTU is to gather diagnostics and otherwise ignore
them. So if a test has a syntax error, and doesn't assert diagnostics, it
silently misbehaves.
This can be annoying when developing tests, as evidenced by various tests
gaining "assert no diagnostics" where that's not really the point of the test.
This patch aims to make that default behavior. For the first error
(not warning), TestTU will call ADD_FAILURE().
This can be suppressed with a comment containing "error-ok". For now that will
suppress any errors in the TU. We can make this stricter later -verify style.
(-verify itself is hard to reuse because of DiagnosticConsumer interfaces...)
A magic-comment was chosen over a TestTU option because of table-driven tests.
In addition to the behavior change, this patch:
- adds //error-ok where we're knowingly testing invalid code
(e.g. for diagnostics, crash-resilience, or token-level tests)
- fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;)
- removes a bunch of now-redundant instances of "assert no diagnostics"
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73199
2020-01-22 23:38:41 +08:00
|
|
|
}
|
2019-08-20 00:27:49 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
// Tokens that share a source range but have conflicting Kinds are not
|
|
|
|
// highlighted.
|
|
|
|
R"cpp(
|
2019-09-24 19:14:06 +08:00
|
|
|
#define $Macro[[DEF_MULTIPLE]](X) namespace X { class X { int X; }; }
|
|
|
|
#define $Macro[[DEF_CLASS]](T) class T {};
|
2019-09-10 18:10:36 +08:00
|
|
|
// Preamble ends.
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[DEF_MULTIPLE]](XYZ);
|
|
|
|
$Macro[[DEF_MULTIPLE]](XYZW);
|
|
|
|
$Macro[[DEF_CLASS]]($Class[[A]])
|
2019-09-10 18:10:36 +08:00
|
|
|
#define $Macro[[MACRO_CONCAT]](X, V, T) T foo##X = V
|
|
|
|
#define $Macro[[DEF_VAR]](X, V) int X = V
|
|
|
|
#define $Macro[[DEF_VAR_T]](T, X, V) T X = V
|
|
|
|
#define $Macro[[DEF_VAR_REV]](V, X) DEF_VAR(X, V)
|
|
|
|
#define $Macro[[CPY]](X) X
|
|
|
|
#define $Macro[[DEF_VAR_TYPE]](X, Y) X Y
|
|
|
|
#define $Macro[[SOME_NAME]] variable
|
|
|
|
#define $Macro[[SOME_NAME_SET]] variable2 = 123
|
|
|
|
#define $Macro[[INC_VAR]](X) X += 2
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]]() {
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[DEF_VAR]]($LocalVariable[[X]], 123);
|
|
|
|
$Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
|
2019-10-28 18:31:06 +08:00
|
|
|
int $Macro[[CPY]]( $LocalVariable[[XX]] );
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]);
|
2019-10-28 18:31:06 +08:00
|
|
|
double $Macro[[SOME_NAME]];
|
|
|
|
int $Macro[[SOME_NAME_SET]];
|
2019-08-28 03:39:11 +08:00
|
|
|
$LocalVariable[[variable]] = 20.1;
|
2019-10-28 18:31:06 +08:00
|
|
|
$Macro[[MACRO_CONCAT]](var, 2, float);
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]](
|
|
|
|
$Macro[[CPY]]($LocalVariable[[Nested]])),
|
|
|
|
$Macro[[CPY]]($Class[[A]]()));
|
|
|
|
$Macro[[INC_VAR]]($LocalVariable[[variable]]);
|
2019-08-20 00:27:49 +08:00
|
|
|
}
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Macro[[SOME_NAME]]();
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
Summary:
The historic behavior of TestTU is to gather diagnostics and otherwise ignore
them. So if a test has a syntax error, and doesn't assert diagnostics, it
silently misbehaves.
This can be annoying when developing tests, as evidenced by various tests
gaining "assert no diagnostics" where that's not really the point of the test.
This patch aims to make that default behavior. For the first error
(not warning), TestTU will call ADD_FAILURE().
This can be suppressed with a comment containing "error-ok". For now that will
suppress any errors in the TU. We can make this stricter later -verify style.
(-verify itself is hard to reuse because of DiagnosticConsumer interfaces...)
A magic-comment was chosen over a TestTU option because of table-driven tests.
In addition to the behavior change, this patch:
- adds //error-ok where we're knowingly testing invalid code
(e.g. for diagnostics, crash-resilience, or token-level tests)
- fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;)
- removes a bunch of now-redundant instances of "assert no diagnostics"
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73199
2020-01-22 23:38:41 +08:00
|
|
|
$Macro[[DEF_VAR]]($Variable[[MMMMM]], 567);
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[DEF_VAR_REV]](756, $Variable[[AB]]);
|
2019-08-20 00:27:49 +08:00
|
|
|
|
2019-09-10 18:10:36 +08:00
|
|
|
#define $Macro[[CALL_FN]](F) F();
|
|
|
|
#define $Macro[[DEF_FN]](F) void F ()
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[DEF_FN]]($Function[[g]]) {
|
|
|
|
$Macro[[CALL_FN]]($Function[[foo]]);
|
2019-08-20 00:27:49 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2019-09-24 19:14:06 +08:00
|
|
|
#define $Macro[[fail]](expr) expr
|
|
|
|
#define $Macro[[assert]](COND) if (!(COND)) { fail("assertion failed" #COND); }
|
2019-09-10 18:10:36 +08:00
|
|
|
// Preamble ends.
|
2019-10-28 18:31:06 +08:00
|
|
|
int $Variable[[x]];
|
|
|
|
int $Variable[[y]];
|
|
|
|
int $Function[[f]]();
|
|
|
|
void $Function[[foo]]() {
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[assert]]($Variable[[x]] != $Variable[[y]]);
|
|
|
|
$Macro[[assert]]($Variable[[x]] != $Function[[f]]());
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
2019-10-07 18:10:31 +08:00
|
|
|
)cpp",
|
|
|
|
// highlighting all macro references
|
|
|
|
R"cpp(
|
|
|
|
#ifndef $Macro[[name]]
|
|
|
|
#define $Macro[[name]]
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define $Macro[[test]]
|
|
|
|
#undef $Macro[[test]]
|
2019-09-25 06:17:55 +08:00
|
|
|
$InactiveCode[[]] #ifdef $Macro[[test]]
|
|
|
|
$InactiveCode[[]] #endif
|
2019-10-07 18:10:31 +08:00
|
|
|
|
2019-09-25 06:17:55 +08:00
|
|
|
$InactiveCode[[]] #if defined($Macro[[test]])
|
|
|
|
$InactiveCode[[]] #endif
|
2019-08-30 22:07:05 +08:00
|
|
|
)cpp",
|
[clangd] Highlight typedefs to template parameters as template parameters
Summary:
Template parameters were handled outside `addType`, this led to lack of highlightings for typedefs
to template types.
This was never desirable, we want to highlight our typedefs as their underlying type.
Note that typedefs to more complicated types, like pointers and references are still not highlighted.
Original patch by Johan Vikström.
Reviewers: hokein, jvikstrom
Reviewed By: hokein
Subscribers: nridge, javed.absar, kristof.beyls, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66516
llvm-svn: 371379
2019-09-09 17:37:17 +08:00
|
|
|
R"cpp(
|
2019-08-30 22:07:05 +08:00
|
|
|
struct $Class[[S]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
float $Field[[Value]];
|
2019-08-30 22:07:05 +08:00
|
|
|
$Class[[S]] *$Field[[Next]];
|
|
|
|
};
|
|
|
|
$Class[[S]] $Variable[[Global]][2] = {$Class[[S]](), $Class[[S]]()};
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[f]]($Class[[S]] $Parameter[[P]]) {
|
|
|
|
int $LocalVariable[[A]][2] = {1,2};
|
2019-08-30 22:07:05 +08:00
|
|
|
auto [$Variable[[B1]], $Variable[[B2]]] = $LocalVariable[[A]];
|
|
|
|
auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]];
|
|
|
|
$Class[[auto]] [$Variable[[P1]], $Variable[[P2]]] = $Parameter[[P]];
|
|
|
|
// Highlights references to BindingDecls.
|
|
|
|
$Variable[[B1]]++;
|
|
|
|
}
|
[clangd] Highlight typedefs to template parameters as template parameters
Summary:
Template parameters were handled outside `addType`, this led to lack of highlightings for typedefs
to template types.
This was never desirable, we want to highlight our typedefs as their underlying type.
Note that typedefs to more complicated types, like pointers and references are still not highlighted.
Original patch by Johan Vikström.
Reviewers: hokein, jvikstrom
Reviewed By: hokein
Subscribers: nridge, javed.absar, kristof.beyls, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66516
llvm-svn: 371379
2019-09-09 17:37:17 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
template<class $TemplateParameter[[T]]>
|
|
|
|
class $Class[[A]] {
|
|
|
|
using $TemplateParameter[[TemplateParam1]] = $TemplateParameter[[T]];
|
|
|
|
typedef $TemplateParameter[[T]] $TemplateParameter[[TemplateParam2]];
|
2019-10-28 18:31:06 +08:00
|
|
|
using $Primitive[[IntType]] = int;
|
[clangd] Highlight typedefs to template parameters as template parameters
Summary:
Template parameters were handled outside `addType`, this led to lack of highlightings for typedefs
to template types.
This was never desirable, we want to highlight our typedefs as their underlying type.
Note that typedefs to more complicated types, like pointers and references are still not highlighted.
Original patch by Johan Vikström.
Reviewers: hokein, jvikstrom
Reviewed By: hokein
Subscribers: nridge, javed.absar, kristof.beyls, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66516
llvm-svn: 371379
2019-09-09 17:37:17 +08:00
|
|
|
|
2019-09-09 22:33:10 +08:00
|
|
|
using $Typedef[[Pointer]] = $TemplateParameter[[T]] *;
|
|
|
|
using $Typedef[[LVReference]] = $TemplateParameter[[T]] &;
|
|
|
|
using $Typedef[[RVReference]] = $TemplateParameter[[T]]&&;
|
|
|
|
using $Typedef[[Array]] = $TemplateParameter[[T]]*[3];
|
2020-01-21 18:50:57 +08:00
|
|
|
using $Typedef[[MemberPointer]] = int ($Class[[A]]::*)(int);
|
2019-09-09 22:33:10 +08:00
|
|
|
|
|
|
|
// Use various previously defined typedefs in a function type.
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[func]](
|
2019-09-09 22:33:10 +08:00
|
|
|
$Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]],
|
|
|
|
$Typedef[[Array]], $Typedef[[MemberPointer]]);
|
[clangd] Highlight typedefs to template parameters as template parameters
Summary:
Template parameters were handled outside `addType`, this led to lack of highlightings for typedefs
to template types.
This was never desirable, we want to highlight our typedefs as their underlying type.
Note that typedefs to more complicated types, like pointers and references are still not highlighted.
Original patch by Johan Vikström.
Reviewers: hokein, jvikstrom
Reviewed By: hokein
Subscribers: nridge, javed.absar, kristof.beyls, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66516
llvm-svn: 371379
2019-09-09 17:37:17 +08:00
|
|
|
};
|
2019-10-15 02:26:13 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <class $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[phase1]]($TemplateParameter[[T]]);
|
2019-10-15 02:26:13 +08:00
|
|
|
template <class $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
|
2019-10-15 02:26:13 +08:00
|
|
|
$Function[[phase1]]($Parameter[[P]]);
|
|
|
|
$DependentName[[phase2]]($Parameter[[P]]);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
class $Class[[A]] {
|
|
|
|
template <class $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[bar]]($TemplateParameter[[T]]);
|
2019-10-15 02:26:13 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class $TemplateParameter[[U]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]]($TemplateParameter[[U]] $Parameter[[P]]) {
|
2019-10-15 02:26:13 +08:00
|
|
|
$Class[[A]]().$Method[[bar]]($Parameter[[P]]);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct $Class[[A]] {
|
|
|
|
template <class $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
static void $StaticMethod[[foo]]($TemplateParameter[[T]]);
|
2019-10-15 02:26:13 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class $TemplateParameter[[T]]>
|
|
|
|
struct $Class[[B]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Method[[bar]]() {
|
2019-10-15 02:26:13 +08:00
|
|
|
$Class[[A]]::$StaticMethod[[foo]]($TemplateParameter[[T]]());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <class $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]](typename $TemplateParameter[[T]]::$DependentType[[Type]]
|
2019-10-15 02:26:13 +08:00
|
|
|
= $TemplateParameter[[T]]::$DependentName[[val]]);
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <class $TemplateParameter[[T]]>
|
2019-10-28 18:31:06 +08:00
|
|
|
void $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
|
2019-10-15 02:26:13 +08:00
|
|
|
$Parameter[[P]].$DependentName[[Field]];
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <class $TemplateParameter[[T]]>
|
|
|
|
class $Class[[A]] {
|
2019-10-28 18:31:06 +08:00
|
|
|
int $Method[[foo]]() {
|
2019-10-15 02:26:13 +08:00
|
|
|
return $TemplateParameter[[T]]::$DependentName[[Field]];
|
|
|
|
}
|
|
|
|
};
|
2019-10-28 20:42:20 +08:00
|
|
|
)cpp",
|
|
|
|
// Highlighting the using decl as the underlying using shadow decl.
|
|
|
|
R"cpp(
|
|
|
|
void $Function[[foo]]();
|
|
|
|
using ::$Function[[foo]];
|
[clangd] Implement semantic highlightings via findExplicitReferences
Summary:
To keep the logic of finding locations of interesting AST nodes in one
place.
The advantage is better coverage of various AST nodes, both now and in
the future: as new nodes get added to `findExplicitReferences`, semantic
highlighting will automatically pick them up.
The drawback of this change is that we have to traverse declarations
inside our file twice in order to highlight dependent names, 'auto'
and 'decltype'. Hopefully, this should not affect the actual latency
too much, most time should be spent in building the AST and not
traversing it.
Reviewers: hokein
Reviewed By: hokein
Subscribers: nridge, merge_guards_bot, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69673
2019-11-06 02:06:12 +08:00
|
|
|
)cpp",
|
|
|
|
// Highlighting of template template arguments.
|
|
|
|
R"cpp(
|
|
|
|
template <template <class> class $TemplateParameter[[TT]],
|
|
|
|
template <class> class ...$TemplateParameter[[TTs]]>
|
|
|
|
struct $Class[[Foo]] {
|
|
|
|
$Class[[Foo]]<$TemplateParameter[[TT]], $TemplateParameter[[TTs]]...>
|
|
|
|
*$Field[[t]];
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
Summary:
The historic behavior of TestTU is to gather diagnostics and otherwise ignore
them. So if a test has a syntax error, and doesn't assert diagnostics, it
silently misbehaves.
This can be annoying when developing tests, as evidenced by various tests
gaining "assert no diagnostics" where that's not really the point of the test.
This patch aims to make that default behavior. For the first error
(not warning), TestTU will call ADD_FAILURE().
This can be suppressed with a comment containing "error-ok". For now that will
suppress any errors in the TU. We can make this stricter later -verify style.
(-verify itself is hard to reuse because of DiagnosticConsumer interfaces...)
A magic-comment was chosen over a TestTU option because of table-driven tests.
In addition to the behavior change, this patch:
- adds //error-ok where we're knowingly testing invalid code
(e.g. for diagnostics, crash-resilience, or token-level tests)
- fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;)
- removes a bunch of now-redundant instances of "assert no diagnostics"
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73199
2020-01-22 23:38:41 +08:00
|
|
|
};
|
2019-09-25 06:17:55 +08:00
|
|
|
)cpp",
|
|
|
|
// Inactive code highlighting
|
|
|
|
R"cpp(
|
|
|
|
// Code in the preamble.
|
|
|
|
// Inactive lines get an empty InactiveCode token at the beginning.
|
|
|
|
$InactiveCode[[]] #ifdef $Macro[[test]]
|
|
|
|
$InactiveCode[[]] #endif
|
|
|
|
|
|
|
|
// A declaration to cause the preamble to end.
|
|
|
|
int $Variable[[EndPreamble]];
|
|
|
|
|
|
|
|
// Code after the preamble.
|
|
|
|
// Code inside inactive blocks does not get regular highlightings
|
|
|
|
// because it's not part of the AST.
|
|
|
|
$InactiveCode[[]] #ifdef $Macro[[test]]
|
|
|
|
$InactiveCode[[]] int Inactive2;
|
|
|
|
$InactiveCode[[]] #endif
|
|
|
|
|
|
|
|
#ifndef $Macro[[test]]
|
|
|
|
int $Variable[[Active1]];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
$InactiveCode[[]] #ifdef $Macro[[test]]
|
|
|
|
$InactiveCode[[]] int Inactive3;
|
|
|
|
$InactiveCode[[]] #else
|
|
|
|
int $Variable[[Active2]];
|
|
|
|
#endif
|
2019-12-06 03:27:23 +08:00
|
|
|
)cpp",
|
|
|
|
// Argument to 'sizeof...'
|
|
|
|
R"cpp(
|
|
|
|
template <typename... $TemplateParameter[[Elements]]>
|
|
|
|
struct $Class[[TupleSize]] {
|
2019-12-06 03:28:56 +08:00
|
|
|
static const int $StaticField[[size]] =
|
|
|
|
sizeof...($TemplateParameter[[Elements]]);
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
// More dependent types
|
|
|
|
R"cpp(
|
|
|
|
template <typename $TemplateParameter[[T]]>
|
|
|
|
struct $Class[[Waldo]] {
|
|
|
|
using $Typedef[[Location1]] = typename $TemplateParameter[[T]]
|
|
|
|
::$DependentType[[Resolver]]::$DependentType[[Location]];
|
|
|
|
using $Typedef[[Location2]] = typename $TemplateParameter[[T]]
|
|
|
|
::template $DependentType[[Resolver]]<$TemplateParameter[[T]]>
|
|
|
|
::$DependentType[[Location]];
|
|
|
|
using $Typedef[[Location3]] = typename $TemplateParameter[[T]]
|
|
|
|
::$DependentType[[Resolver]]
|
|
|
|
::template $DependentType[[Location]]<$TemplateParameter[[T]]>;
|
|
|
|
static const int $StaticField[[Value]] = $TemplateParameter[[T]]
|
|
|
|
::$DependentType[[Resolver]]::$DependentName[[Value]];
|
2019-12-06 03:27:23 +08:00
|
|
|
};
|
2020-01-22 02:21:08 +08:00
|
|
|
)cpp",
|
|
|
|
// Concepts
|
|
|
|
R"cpp(
|
|
|
|
template <typename $TemplateParameter[[T]]>
|
|
|
|
concept $Concept[[Fooable]] =
|
|
|
|
requires($TemplateParameter[[T]] $Parameter[[F]]) {
|
|
|
|
$Parameter[[F]].$DependentName[[foo]]();
|
|
|
|
};
|
|
|
|
template <typename $TemplateParameter[[T]]>
|
|
|
|
requires $Concept[[Fooable]]<$TemplateParameter[[T]]>
|
|
|
|
void $Function[[bar]]($TemplateParameter[[T]] $Parameter[[F]]) {
|
|
|
|
$Parameter[[F]].$DependentName[[foo]]();
|
|
|
|
}
|
2019-07-05 21:06:03 +08:00
|
|
|
)cpp"};
|
2019-06-26 21:08:36 +08:00
|
|
|
for (const auto &TestCase : TestCases) {
|
|
|
|
checkHighlightings(TestCase);
|
|
|
|
}
|
2019-08-12 21:01:11 +08:00
|
|
|
|
|
|
|
checkHighlightings(R"cpp(
|
|
|
|
class $Class[[A]] {
|
|
|
|
#include "imp.h"
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
{{"imp.h", R"cpp(
|
|
|
|
int someMethod();
|
|
|
|
void otherMethod();
|
|
|
|
)cpp"}});
|
2019-08-20 00:27:49 +08:00
|
|
|
|
|
|
|
// A separate test for macros in headers.
|
|
|
|
checkHighlightings(R"cpp(
|
|
|
|
#include "imp.h"
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[DEFINE_Y]]
|
|
|
|
$Macro[[DXYZ_Y]](A);
|
2019-08-20 00:27:49 +08:00
|
|
|
)cpp",
|
|
|
|
{{"imp.h", R"cpp(
|
|
|
|
#define DXYZ(X) class X {};
|
|
|
|
#define DXYZ_Y(Y) DXYZ(x##Y)
|
|
|
|
#define DEFINE(X) int X;
|
|
|
|
#define DEFINE_Y DEFINE(Y)
|
|
|
|
)cpp"}});
|
2019-06-26 21:08:36 +08:00
|
|
|
}
|
|
|
|
|
2019-07-04 15:53:12 +08:00
|
|
|
TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
|
2019-06-27 23:13:03 +08:00
|
|
|
class HighlightingsCounterDiagConsumer : public DiagnosticsConsumer {
|
|
|
|
public:
|
|
|
|
std::atomic<int> Count = {0};
|
|
|
|
|
|
|
|
void onDiagnosticsReady(PathRef, std::vector<Diag>) override {}
|
2019-08-26 16:38:45 +08:00
|
|
|
void onHighlightingsReady(
|
|
|
|
PathRef File, std::vector<HighlightingToken> Highlightings) override {
|
2019-06-27 23:13:03 +08:00
|
|
|
++Count;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
auto FooCpp = testPath("foo.cpp");
|
|
|
|
MockFSProvider FS;
|
|
|
|
FS.Files[FooCpp] = "";
|
|
|
|
|
|
|
|
MockCompilationDatabase MCD;
|
|
|
|
HighlightingsCounterDiagConsumer DiagConsumer;
|
|
|
|
ClangdServer Server(MCD, FS, DiagConsumer, ClangdServer::optsForTest());
|
|
|
|
Server.addDocument(FooCpp, "int a;");
|
|
|
|
ASSERT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for server";
|
|
|
|
ASSERT_EQ(DiagConsumer.Count, 1);
|
|
|
|
}
|
|
|
|
|
2019-07-04 15:53:12 +08:00
|
|
|
TEST(SemanticHighlighting, toSemanticHighlightingInformation) {
|
|
|
|
auto CreatePosition = [](int Line, int Character) -> Position {
|
|
|
|
Position Pos;
|
|
|
|
Pos.line = Line;
|
|
|
|
Pos.character = Character;
|
|
|
|
return Pos;
|
|
|
|
};
|
|
|
|
|
2019-08-01 16:08:44 +08:00
|
|
|
std::vector<LineHighlightings> Tokens{
|
|
|
|
{3,
|
|
|
|
{{HighlightingKind::Variable,
|
|
|
|
Range{CreatePosition(3, 8), CreatePosition(3, 12)}},
|
|
|
|
{HighlightingKind::Function,
|
2019-09-25 06:17:55 +08:00
|
|
|
Range{CreatePosition(3, 4), CreatePosition(3, 7)}}},
|
|
|
|
/* IsInactive = */ false},
|
2019-08-01 16:08:44 +08:00
|
|
|
{1,
|
|
|
|
{{HighlightingKind::Variable,
|
2019-09-25 06:17:55 +08:00
|
|
|
Range{CreatePosition(1, 1), CreatePosition(1, 5)}}},
|
|
|
|
/* IsInactive = */ true}};
|
2019-07-04 15:53:12 +08:00
|
|
|
std::vector<SemanticHighlightingInformation> ActualResults =
|
|
|
|
toSemanticHighlightingInformation(Tokens);
|
|
|
|
std::vector<SemanticHighlightingInformation> ExpectedResults = {
|
2019-08-28 03:39:11 +08:00
|
|
|
{3, "AAAACAAEAAAAAAAEAAMAAw=="}, {1, "AAAAAQAEAAA="}};
|
2019-07-04 15:53:12 +08:00
|
|
|
EXPECT_EQ(ActualResults, ExpectedResults);
|
|
|
|
}
|
|
|
|
|
2019-08-01 16:08:44 +08:00
|
|
|
TEST(SemanticHighlighting, HighlightingDiffer) {
|
|
|
|
struct {
|
|
|
|
llvm::StringRef OldCode;
|
|
|
|
llvm::StringRef NewCode;
|
|
|
|
} TestCases[]{{
|
|
|
|
R"(
|
|
|
|
$Variable[[A]]
|
|
|
|
$Class[[B]]
|
|
|
|
$Function[[C]]
|
|
|
|
)",
|
|
|
|
R"(
|
|
|
|
$Variable[[A]]
|
|
|
|
$Class[[D]]
|
|
|
|
$Function[[C]]
|
|
|
|
)"},
|
|
|
|
{
|
|
|
|
R"(
|
|
|
|
$Class[[C]]
|
|
|
|
$Field[[F]]
|
|
|
|
$Variable[[V]]
|
|
|
|
$Class[[C]] $Variable[[V]] $Field[[F]]
|
|
|
|
)",
|
|
|
|
R"(
|
|
|
|
$Class[[C]]
|
|
|
|
$Field[[F]]
|
|
|
|
^$Function[[F]]
|
|
|
|
$Class[[C]] $Variable[[V]] $Field[[F]]
|
|
|
|
)"},
|
|
|
|
{
|
|
|
|
R"(
|
|
|
|
|
|
|
|
$Class[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
)",
|
|
|
|
R"(
|
|
|
|
|
|
|
|
^
|
|
|
|
^$Class[[A]]
|
|
|
|
^$Variable[[A]]
|
|
|
|
)"},
|
|
|
|
{
|
|
|
|
R"(
|
|
|
|
$Class[[C]]
|
|
|
|
$Field[[F]]
|
|
|
|
$Variable[[V]]
|
|
|
|
$Class[[C]] $Variable[[V]] $Field[[F]]
|
|
|
|
)",
|
|
|
|
R"(
|
|
|
|
$Class[[C]]
|
|
|
|
^
|
|
|
|
^
|
|
|
|
$Class[[C]] $Variable[[V]] $Field[[F]]
|
|
|
|
)"},
|
|
|
|
{
|
|
|
|
R"(
|
|
|
|
$Class[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
)",
|
|
|
|
R"(
|
|
|
|
$Class[[A]]
|
|
|
|
^$Variable[[AA]]
|
|
|
|
$Variable[[A]]
|
|
|
|
)"},
|
|
|
|
{
|
|
|
|
R"(
|
|
|
|
$Class[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
)",
|
|
|
|
R"(
|
|
|
|
$Class[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
^$Class[[A]]
|
|
|
|
^$Variable[[A]]
|
|
|
|
)"},
|
|
|
|
{
|
|
|
|
R"(
|
|
|
|
$Variable[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
)",
|
|
|
|
R"(
|
|
|
|
^$Class[[A]]
|
|
|
|
^$Class[[A]]
|
|
|
|
^$Class[[A]]
|
|
|
|
)"}};
|
|
|
|
|
|
|
|
for (const auto &Test : TestCases)
|
|
|
|
checkDiffedHighlights(Test.OldCode, Test.NewCode);
|
|
|
|
}
|
|
|
|
|
2019-08-26 16:38:45 +08:00
|
|
|
TEST(SemanticHighlighting, DiffBeyondTheEndOfFile) {
|
|
|
|
llvm::StringRef OldCode =
|
|
|
|
R"(
|
|
|
|
$Class[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
$Class[[A]]
|
|
|
|
$Variable[[A]]
|
|
|
|
)";
|
|
|
|
llvm::StringRef NewCode =
|
|
|
|
R"(
|
|
|
|
$Class[[A]] // line 1
|
|
|
|
$Variable[[A]] // line 2
|
|
|
|
)";
|
|
|
|
|
|
|
|
Annotations OldTest(OldCode);
|
|
|
|
Annotations NewTest(NewCode);
|
|
|
|
std::vector<HighlightingToken> OldTokens = getExpectedTokens(OldTest);
|
|
|
|
std::vector<HighlightingToken> NewTokens = getExpectedTokens(NewTest);
|
|
|
|
|
|
|
|
auto ActualDiff = diffHighlightings(NewTokens, OldTokens);
|
|
|
|
EXPECT_THAT(ActualDiff,
|
|
|
|
testing::UnorderedElementsAre(
|
|
|
|
testing::AllOf(LineNumber(3), EmptyHighlightings()),
|
|
|
|
testing::AllOf(LineNumber(4), EmptyHighlightings())));
|
|
|
|
}
|
|
|
|
|
2019-06-26 21:08:36 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
2019-10-13 21:15:27 +08:00
|
|
|
} // namespace clang
|