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-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-26 21:08:36 +08:00
|
|
|
#include "TestTU.h"
|
2019-09-09 16:47:05 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2019-09-09 16:47:05 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
2021-01-27 16:47:17 +08:00
|
|
|
#include "llvm/Support/raw_ostream.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 {
|
|
|
|
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
using testing::IsEmpty;
|
|
|
|
using testing::SizeIs;
|
|
|
|
|
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;
|
|
|
|
}));
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
std::string Buf;
|
|
|
|
llvm::raw_string_ostream OS(Buf);
|
2019-09-09 16:47:05 +08:00
|
|
|
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);
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
OS << Input.substr(NextChar, StartOffset - NextChar);
|
|
|
|
OS << '$' << T.Kind;
|
|
|
|
for (unsigned I = 0;
|
|
|
|
I <= static_cast<uint32_t>(HighlightingModifier::LastModifier); ++I) {
|
|
|
|
if (T.Modifiers & (1 << I))
|
|
|
|
OS << '_' << static_cast<HighlightingModifier>(I);
|
|
|
|
}
|
|
|
|
OS << "[[" << Input.substr(StartOffset, EndOffset - StartOffset) << "]]";
|
2019-09-09 16:47:05 +08:00
|
|
|
NextChar = EndOffset;
|
|
|
|
}
|
2021-01-27 16:47:17 +08:00
|
|
|
OS << Input.substr(NextChar);
|
|
|
|
return std::move(OS.str());
|
2019-09-09 16:47:05 +08:00
|
|
|
}
|
|
|
|
|
2019-08-12 21:01:11 +08:00
|
|
|
void checkHighlightings(llvm::StringRef Code,
|
|
|
|
std::vector<std::pair</*FileName*/ llvm::StringRef,
|
|
|
|
/*FileContent*/ llvm::StringRef>>
|
2021-01-30 06:18:34 +08:00
|
|
|
AdditionalFiles = {},
|
2021-04-30 01:03:10 +08:00
|
|
|
uint32_t ModifierMask = -1,
|
|
|
|
std::vector<std::string> AdditionalArgs = {}) {
|
2019-08-01 16:08:44 +08:00
|
|
|
Annotations Test(Code);
|
2019-10-13 21:15:27 +08:00
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.Code = std::string(Test.code());
|
2019-10-13 21:15:27 +08:00
|
|
|
|
2020-06-03 20:53:59 +08:00
|
|
|
TU.ExtraArgs.push_back("-std=c++20");
|
2021-02-28 05:08:07 +08:00
|
|
|
TU.ExtraArgs.push_back("-xobjective-c++");
|
2021-04-30 01:03:10 +08:00
|
|
|
TU.ExtraArgs.insert(std::end(TU.ExtraArgs), std::begin(AdditionalArgs),
|
|
|
|
std::end(AdditionalArgs));
|
2019-10-13 21:15:27 +08:00
|
|
|
|
2019-08-12 21:01:11 +08:00
|
|
|
for (auto File : AdditionalFiles)
|
2020-01-29 06:30:02 +08:00
|
|
|
TU.AdditionalFiles.insert({File.first, std::string(File.second)});
|
2019-08-12 21:01:11 +08:00
|
|
|
auto AST = TU.build();
|
2021-01-30 06:18:34 +08:00
|
|
|
auto Actual = getSemanticHighlightings(AST);
|
|
|
|
for (auto &Token : Actual)
|
|
|
|
Token.Modifiers &= ModifierMask;
|
2019-09-09 16:47:05 +08:00
|
|
|
|
2021-01-30 06:18:34 +08:00
|
|
|
EXPECT_EQ(Code, annotate(Test.code(), Actual));
|
2019-08-01 16:08:44 +08:00
|
|
|
}
|
|
|
|
|
2021-01-30 06:18:34 +08:00
|
|
|
constexpr static uint32_t ScopeModifierMask =
|
|
|
|
1 << unsigned(HighlightingModifier::FunctionScope) |
|
|
|
|
1 << unsigned(HighlightingModifier::ClassScope) |
|
|
|
|
1 << unsigned(HighlightingModifier::FileScope) |
|
|
|
|
1 << unsigned(HighlightingModifier::GlobalScope);
|
|
|
|
|
2019-06-26 21:08:36 +08:00
|
|
|
TEST(SemanticHighlighting, GetsCorrectTokens) {
|
|
|
|
const char *TestCases[] = {
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[AS]] {
|
|
|
|
double $Field_decl[[SomeMember]];
|
2019-07-05 21:06:03 +08:00
|
|
|
};
|
|
|
|
struct {
|
2021-01-27 16:47:17 +08:00
|
|
|
} $Variable_decl[[S]];
|
|
|
|
void $Function_decl[[foo]](int $Parameter_decl[[A]], $Class[[AS]] $Parameter_decl[[As]]) {
|
2021-04-30 01:03:10 +08:00
|
|
|
$Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_decl[[VeryLongVariableName]] = 12312;
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[AS]] $LocalVariable_decl[[AA]];
|
2021-04-30 01:03:10 +08:00
|
|
|
$Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_decl[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]];
|
2021-01-27 16:47:17 +08:00
|
|
|
auto $LocalVariable_decl[[FN]] = [ $LocalVariable[[AA]]](int $Parameter_decl[[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(
|
2021-01-27 16:47:17 +08:00
|
|
|
void $Function_decl[[foo]](int);
|
|
|
|
void $Function_decl[[Gah]]();
|
|
|
|
void $Function_decl[[foo]]() {
|
|
|
|
auto $LocalVariable_decl[[Bou]] = $Function[[Gah]];
|
2019-07-05 21:06:03 +08:00
|
|
|
}
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
void $Method_decl[[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(
|
2021-01-27 16:47:17 +08:00
|
|
|
namespace $Namespace_decl[[abc]] {
|
|
|
|
template<typename $TemplateParameter_decl[[T]]>
|
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
$TemplateParameter[[T]] $Field_decl[[t]];
|
2019-07-10 16:41:25 +08:00
|
|
|
};
|
|
|
|
}
|
2021-01-27 16:47:17 +08:00
|
|
|
template<typename $TemplateParameter_decl[[T]]>
|
|
|
|
struct $Class_decl[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
|
2021-01-30 08:12:36 +08:00
|
|
|
typename $TemplateParameter[[T]]::$Type_dependentName[[A]]* $Field_decl[[D]];
|
2021-01-27 16:47:17 +08:00
|
|
|
};
|
|
|
|
$Namespace[[abc]]::$Class[[A]]<int> $Variable_decl[[AA]];
|
|
|
|
typedef $Namespace[[abc]]::$Class[[A]]<int> $Class_decl[[AAA]];
|
|
|
|
struct $Class_decl[[B]] {
|
|
|
|
$Class_decl[[B]]();
|
|
|
|
~$Class[[B]](); // FIXME: inconsistent with constructor
|
2019-10-28 18:31:06 +08:00
|
|
|
void operator<<($Class[[B]]);
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[AAA]] $Field_decl[[AA]];
|
2019-07-10 16:41:25 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[B]]::$Class_decl[[B]]() {}
|
|
|
|
$Class[[B]]::~$Class[[B]]() {} // FIXME: inconsistent with constructor
|
|
|
|
void $Function_decl[[f]] () {
|
|
|
|
$Class[[B]] $LocalVariable_decl[[BB]] = $Class[[B]]();
|
2019-08-28 03:39:11 +08:00
|
|
|
$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(
|
2021-01-27 16:47:17 +08:00
|
|
|
enum class $Enum_decl[[E]] {
|
|
|
|
$EnumConstant_decl_readonly[[A]],
|
|
|
|
$EnumConstant_decl_readonly[[B]],
|
2019-07-15 15:41:12 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
enum $Enum_decl[[EE]] {
|
|
|
|
$EnumConstant_decl_readonly[[Hi]],
|
2019-07-15 15:41:12 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
$Enum[[E]] $Field_decl[[EEE]];
|
|
|
|
$Enum[[EE]] $Field_decl[[EEEE]];
|
2019-07-05 21:06:03 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
int $Variable_decl[[I]] = $EnumConstant_readonly[[Hi]];
|
|
|
|
$Enum[[E]] $Variable_decl[[L]] = $Enum[[E]]::$EnumConstant_readonly[[B]];
|
2019-07-11 17:29:16 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
namespace $Namespace_decl[[abc]] {
|
2019-07-11 17:29:16 +08:00
|
|
|
namespace {}
|
2021-01-27 16:47:17 +08:00
|
|
|
namespace $Namespace_decl[[bcd]] {
|
|
|
|
struct $Class_decl[[A]] {};
|
|
|
|
namespace $Namespace_decl[[cde]] {
|
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
enum class $Enum_decl[[B]] {
|
|
|
|
$EnumConstant_decl_readonly[[Hi]],
|
2019-07-11 17:29:16 +08:00
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
using namespace $Namespace[[abc]]::$Namespace[[bcd]];
|
2021-01-27 16:47:17 +08:00
|
|
|
namespace $Namespace_decl[[vwz]] =
|
2019-07-11 17:29:16 +08:00
|
|
|
$Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]];
|
2021-01-27 16:47:17 +08:00
|
|
|
$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable_decl[[AA]];
|
|
|
|
$Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable_decl[[AAA]] =
|
|
|
|
$Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::$EnumConstant_readonly[[Hi]];
|
|
|
|
::$Namespace[[vwz]]::$Class[[A]] $Variable_decl[[B]];
|
|
|
|
::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable_decl[[BB]];
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct $Class_decl[[D]] {
|
|
|
|
double $Field_decl[[C]];
|
|
|
|
};
|
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
double $Field_decl[[B]];
|
|
|
|
$Class[[D]] $Field_decl[[E]];
|
|
|
|
static double $StaticField_decl_static[[S]];
|
|
|
|
static void $StaticMethod_decl_static[[bar]]() {}
|
|
|
|
void $Method_decl[[foo]]() {
|
2019-07-15 16:12:21 +08:00
|
|
|
$Field[[B]] = 123;
|
|
|
|
this->$Field[[B]] = 156;
|
|
|
|
this->$Method[[foo]]();
|
|
|
|
$Method[[foo]]();
|
2021-01-27 16:47:17 +08:00
|
|
|
$StaticMethod_static[[bar]]();
|
|
|
|
$StaticField_static[[S]] = 90.1;
|
2019-07-15 16:12:21 +08:00
|
|
|
}
|
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
void $Function_decl[[foo]]() {
|
|
|
|
$Class[[A]] $LocalVariable_decl[[AA]];
|
2019-08-28 03:39:11 +08:00
|
|
|
$LocalVariable[[AA]].$Field[[B]] += 2;
|
|
|
|
$LocalVariable[[AA]].$Method[[foo]]();
|
|
|
|
$LocalVariable[[AA]].$Field[[E]].$Field[[C]];
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[A]]::$StaticField_static[[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(
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[AA]] {
|
|
|
|
int $Field_decl[[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
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
int $Variable_decl[[B]];
|
|
|
|
$Class[[AA]] $Variable_decl[[A]]{$Variable[[B]]};
|
2019-07-16 21:23:12 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
namespace $Namespace_decl[[a]] {
|
|
|
|
struct $Class_decl[[A]] {};
|
|
|
|
typedef char $Primitive_decl[[C]];
|
2019-07-16 21:23:12 +08:00
|
|
|
}
|
2021-01-27 16:47:17 +08:00
|
|
|
typedef $Namespace[[a]]::$Class[[A]] $Class_decl[[B]];
|
|
|
|
using $Class_decl[[BB]] = $Namespace[[a]]::$Class[[A]];
|
|
|
|
enum class $Enum_decl[[E]] {};
|
|
|
|
typedef $Enum[[E]] $Enum_decl[[C]];
|
|
|
|
typedef $Enum[[C]] $Enum_decl[[CC]];
|
|
|
|
using $Enum_decl[[CD]] = $Enum[[CC]];
|
|
|
|
$Enum[[CC]] $Function_decl[[f]]($Class[[B]]);
|
|
|
|
$Enum[[CD]] $Function_decl[[f]]($Class[[BB]]);
|
|
|
|
typedef $Namespace[[a]]::$Primitive[[C]] $Primitive_decl[[PC]];
|
|
|
|
typedef float $Primitive_decl[[F]];
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
template<typename $TemplateParameter_decl[[T]], typename = void>
|
|
|
|
class $Class_decl[[A]] {
|
|
|
|
$TemplateParameter[[T]] $Field_decl[[AA]];
|
|
|
|
$TemplateParameter[[T]] $Method_decl[[foo]]();
|
|
|
|
};
|
|
|
|
template<class $TemplateParameter_decl[[TT]]>
|
|
|
|
class $Class_decl[[B]] {
|
|
|
|
$Class[[A]]<$TemplateParameter[[TT]]> $Field_decl[[AA]];
|
|
|
|
};
|
|
|
|
template<class $TemplateParameter_decl[[TT]], class $TemplateParameter_decl[[GG]]>
|
|
|
|
class $Class_decl[[BB]] {};
|
|
|
|
template<class $TemplateParameter_decl[[T]]>
|
|
|
|
class $Class_decl[[BB]]<$TemplateParameter[[T]], int> {};
|
|
|
|
template<class $TemplateParameter_decl[[T]]>
|
|
|
|
class $Class_decl[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {};
|
|
|
|
|
|
|
|
template<template<class> class $TemplateParameter_decl[[T]], class $TemplateParameter_decl[[C]]>
|
|
|
|
$TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function_decl[[f]]();
|
2019-07-18 17:56:38 +08:00
|
|
|
|
|
|
|
template<typename>
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[Foo]] {};
|
2019-07-18 17:56:38 +08:00
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
template<typename $TemplateParameter_decl[[T]]>
|
|
|
|
void $Function_decl[[foo]]($TemplateParameter[[T]] ...);
|
2019-08-08 15:21:06 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
struct $Class_decl[[Tmpl]] {$TemplateParameter[[T]] $Field_decl[[x]] = 0;};
|
2021-01-30 08:12:36 +08:00
|
|
|
extern template struct $Class_decl[[Tmpl]]<float>;
|
|
|
|
template struct $Class_decl[[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(
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[Foo]] {};
|
|
|
|
struct $Class_decl[[Bar]] {
|
2019-08-08 20:43:55 +08:00
|
|
|
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]]();
|
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
void $Function_decl[[f]]() {
|
|
|
|
$Class[[Bar]] $LocalVariable_decl[[B]];
|
|
|
|
$Class[[Foo]] $LocalVariable_decl[[F]] = $LocalVariable[[B]];
|
|
|
|
$Class[[Foo]] *$LocalVariable_decl[[FP]] = ($Class[[Foo]]*)$LocalVariable[[B]];
|
|
|
|
int $LocalVariable_decl[[I]] = (int)$LocalVariable[[B]];
|
2019-08-08 20:43:55 +08:00
|
|
|
}
|
2020-08-15 02:27:30 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[B]] {};
|
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
$Class[[B]] $Field_decl[[BB]];
|
|
|
|
$Class[[A]] &operator=($Class[[A]] &&$Parameter_decl[[O]]);
|
2019-08-09 15:30:28 +08:00
|
|
|
};
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter_decl[[O]]) = default;
|
2019-08-09 20:19:10 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
enum $Enum_decl[[En]] {
|
|
|
|
$EnumConstant_decl_readonly[[EC]],
|
2019-08-09 20:19:10 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[Foo]] {};
|
|
|
|
class $Class_decl[[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:
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[Foo]] $Field_decl[[Fo]];
|
|
|
|
$Enum[[En]] $Field_decl[[E]];
|
|
|
|
int $Field_decl[[I]];
|
|
|
|
$Class_decl[[Bar]] ($Class[[Foo]] $Parameter_decl[[F]],
|
|
|
|
$Enum[[En]] $Parameter_decl[[E]])
|
2019-08-19 15:51:39 +08:00
|
|
|
: $Field[[Fo]] ($Parameter[[F]]), $Field[[E]] ($Parameter[[E]]),
|
2019-08-09 20:19:10 +08:00
|
|
|
$Field[[I]] (123) {}
|
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[Bar2]] : public $Class[[Bar]] {
|
|
|
|
$Class_decl[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant_readonly[[EC]]) {}
|
2019-08-09 20:19:10 +08:00
|
|
|
};
|
2019-08-12 15:45:12 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
enum $Enum_decl[[E]] {
|
|
|
|
$EnumConstant_decl_readonly[[E]],
|
2019-08-12 15:45:12 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[Foo]] {};
|
|
|
|
$Enum_deduced[[auto]] $Variable_decl[[AE]] = $Enum[[E]]::$EnumConstant_readonly[[E]];
|
|
|
|
$Class_deduced[[auto]] $Variable_decl[[AF]] = $Class[[Foo]]();
|
|
|
|
$Class_deduced[[decltype]](auto) $Variable_decl[[AF2]] = $Class[[Foo]]();
|
|
|
|
$Class_deduced[[auto]] *$Variable_decl[[AFP]] = &$Variable[[AF]];
|
|
|
|
$Enum_deduced[[auto]] &$Variable_decl[[AER]] = $Variable[[AE]];
|
2021-04-30 01:03:10 +08:00
|
|
|
$Primitive_deduced_defaultLibrary[[auto]] $Variable_decl[[Form]] = 10.2 + 2 * 4;
|
|
|
|
$Primitive_deduced_defaultLibrary[[decltype]]($Variable[[Form]]) $Variable_decl[[F]] = 10;
|
2021-01-27 16:47:17 +08:00
|
|
|
auto $Variable_decl[[Fun]] = []()->void{};
|
2019-08-16 17:30:21 +08:00
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[G]] {};
|
|
|
|
template<$Class[[G]] *$TemplateParameter_decl_readonly[[U]]>
|
|
|
|
class $Class_decl[[GP]] {};
|
|
|
|
template<$Class[[G]] &$TemplateParameter_decl_readonly[[U]]>
|
|
|
|
class $Class_decl[[GR]] {};
|
|
|
|
template<int *$TemplateParameter_decl_readonly[[U]]>
|
|
|
|
class $Class_decl[[IP]] {
|
|
|
|
void $Method_decl[[f]]() {
|
|
|
|
*$TemplateParameter_readonly[[U]] += 5;
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
template<unsigned $TemplateParameter_decl_readonly[[U]] = 2>
|
|
|
|
class $Class_decl[[Foo]] {
|
|
|
|
void $Method_decl[[f]]() {
|
|
|
|
for(int $LocalVariable_decl[[I]] = 0;
|
|
|
|
$LocalVariable[[I]] < $TemplateParameter_readonly[[U]];) {}
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[G]] $Variable_decl[[L]];
|
|
|
|
void $Function_decl[[f]]() {
|
|
|
|
$Class[[Foo]]<123> $LocalVariable_decl[[F]];
|
|
|
|
$Class[[GP]]<&$Variable[[L]]> $LocalVariable_decl[[LL]];
|
|
|
|
$Class[[GR]]<$Variable[[L]]> $LocalVariable_decl[[LLL]];
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template<typename $TemplateParameter_decl[[T]],
|
|
|
|
void ($TemplateParameter[[T]]::*$TemplateParameter_decl_readonly[[method]])(int)>
|
|
|
|
struct $Class_decl[[G]] {
|
|
|
|
void $Method_decl[[foo]](
|
|
|
|
$TemplateParameter[[T]] *$Parameter_decl[[O]]) {
|
|
|
|
($Parameter[[O]]->*$TemplateParameter_readonly[[method]])(10);
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[F]] {
|
|
|
|
void $Method_decl[[f]](int);
|
2019-08-16 17:30:21 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
template<void (*$TemplateParameter_decl_readonly[[Func]])()>
|
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
void $Method_decl[[f]]() {
|
|
|
|
(*$TemplateParameter_readonly[[Func]])();
|
2019-08-16 17:30:21 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
void $Function_decl[[foo]]() {
|
|
|
|
$Class[[F]] $LocalVariable_decl[[FF]];
|
|
|
|
$Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $LocalVariable_decl[[GG]];
|
2019-08-28 03:39:11 +08:00
|
|
|
$LocalVariable[[GG]].$Method[[foo]](&$LocalVariable[[FF]]);
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[A]]<$Function[[foo]]> $LocalVariable_decl[[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(
|
2021-01-27 16:47:17 +08:00
|
|
|
#define $Macro_decl[[DEF_MULTIPLE]](X) namespace X { class X { int X; }; }
|
|
|
|
#define $Macro_decl[[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);
|
2021-01-27 16:47:17 +08:00
|
|
|
$Macro[[DEF_CLASS]]($Class_decl[[A]])
|
|
|
|
#define $Macro_decl[[MACRO_CONCAT]](X, V, T) T foo##X = V
|
|
|
|
#define $Macro_decl[[DEF_VAR]](X, V) int X = V
|
|
|
|
#define $Macro_decl[[DEF_VAR_T]](T, X, V) T X = V
|
|
|
|
#define $Macro_decl[[DEF_VAR_REV]](V, X) DEF_VAR(X, V)
|
|
|
|
#define $Macro_decl[[CPY]](X) X
|
|
|
|
#define $Macro_decl[[DEF_VAR_TYPE]](X, Y) X Y
|
|
|
|
#define $Macro_decl[[SOME_NAME]] variable
|
|
|
|
#define $Macro_decl[[SOME_NAME_SET]] variable2 = 123
|
|
|
|
#define $Macro_decl[[INC_VAR]](X) X += 2
|
|
|
|
void $Function_decl[[foo]]() {
|
|
|
|
$Macro[[DEF_VAR]]($LocalVariable_decl[[X]], 123);
|
|
|
|
$Macro[[DEF_VAR_REV]](908, $LocalVariable_decl[[XY]]);
|
|
|
|
int $Macro[[CPY]]( $LocalVariable_decl[[XX]] );
|
|
|
|
$Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable_decl[[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]](
|
2021-01-27 16:47:17 +08:00
|
|
|
$Macro[[CPY]]($LocalVariable_decl[[Nested]])),
|
2019-08-30 23:47:27 +08:00
|
|
|
$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]]();
|
2021-01-27 16:47:17 +08:00
|
|
|
$Macro[[DEF_VAR]]($Variable_decl[[MMMMM]], 567);
|
|
|
|
$Macro[[DEF_VAR_REV]](756, $Variable_decl[[AB]]);
|
2019-08-20 00:27:49 +08:00
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
#define $Macro_decl[[CALL_FN]](F) F();
|
|
|
|
#define $Macro_decl[[DEF_FN]](F) void F ()
|
|
|
|
$Macro[[DEF_FN]]($Function_decl[[g]]) {
|
2019-08-30 23:47:27 +08:00
|
|
|
$Macro[[CALL_FN]]($Function[[foo]]);
|
2019-08-20 00:27:49 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
2019-08-28 03:39:11 +08:00
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
#define $Macro_decl[[fail]](expr) expr
|
|
|
|
#define $Macro_decl[[assert]](COND) if (!(COND)) { fail("assertion failed" #COND); }
|
2019-09-10 18:10:36 +08:00
|
|
|
// Preamble ends.
|
2021-01-27 16:47:17 +08:00
|
|
|
int $Variable_decl[[x]];
|
|
|
|
int $Variable_decl[[y]];
|
|
|
|
int $Function_decl[[f]]();
|
|
|
|
void $Function_decl[[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]]
|
2021-01-27 16:47:17 +08:00
|
|
|
#define $Macro_decl[[name]]
|
2019-10-07 18:10:31 +08:00
|
|
|
#endif
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
#define $Macro_decl[[test]]
|
2019-10-07 18:10:31 +08:00
|
|
|
#undef $Macro[[test]]
|
2020-08-26 16:50:31 +08:00
|
|
|
$InactiveCode[[#ifdef test]]
|
|
|
|
$InactiveCode[[#endif]]
|
2019-10-07 18:10:31 +08:00
|
|
|
|
2020-08-26 16:50:31 +08:00
|
|
|
$InactiveCode[[#if defined(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(
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[S]] {
|
|
|
|
float $Field_decl[[Value]];
|
|
|
|
$Class[[S]] *$Field_decl[[Next]];
|
2019-08-30 22:07:05 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
$Class[[S]] $Variable_decl[[Global]][2] = {$Class[[S]](), $Class[[S]]()};
|
|
|
|
auto [$Variable_decl[[G1]], $Variable_decl[[G2]]] = $Variable[[Global]];
|
|
|
|
void $Function_decl[[f]]($Class[[S]] $Parameter_decl[[P]]) {
|
|
|
|
int $LocalVariable_decl[[A]][2] = {1,2};
|
|
|
|
auto [$LocalVariable_decl[[B1]], $LocalVariable_decl[[B2]]] = $LocalVariable[[A]];
|
|
|
|
auto [$LocalVariable_decl[[G1]], $LocalVariable_decl[[G2]]] = $Variable[[Global]];
|
|
|
|
$Class_deduced[[auto]] [$LocalVariable_decl[[P1]], $LocalVariable_decl[[P2]]] = $Parameter[[P]];
|
2019-08-30 22:07:05 +08:00
|
|
|
// Highlights references to BindingDecls.
|
2020-08-07 13:31:03 +08:00
|
|
|
$LocalVariable[[B1]]++;
|
2019-08-30 22:07:05 +08:00
|
|
|
}
|
[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(
|
2021-01-27 16:47:17 +08:00
|
|
|
template<class $TemplateParameter_decl[[T]]>
|
|
|
|
class $Class_decl[[A]] {
|
|
|
|
using $TemplateParameter_decl[[TemplateParam1]] = $TemplateParameter[[T]];
|
|
|
|
typedef $TemplateParameter[[T]] $TemplateParameter_decl[[TemplateParam2]];
|
|
|
|
using $Primitive_decl[[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
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
using $Typedef_decl[[Pointer]] = $TemplateParameter[[T]] *;
|
|
|
|
using $Typedef_decl[[LVReference]] = $TemplateParameter[[T]] &;
|
|
|
|
using $Typedef_decl[[RVReference]] = $TemplateParameter[[T]]&&;
|
|
|
|
using $Typedef_decl[[Array]] = $TemplateParameter[[T]]*[3];
|
|
|
|
using $Typedef_decl[[MemberPointer]] = int ($Class[[A]]::*)(int);
|
2019-09-09 22:33:10 +08:00
|
|
|
|
|
|
|
// Use various previously defined typedefs in a function type.
|
2021-01-27 16:47:17 +08:00
|
|
|
void $Method_decl[[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(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
void $Function_decl[[phase1]]($TemplateParameter[[T]]);
|
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
void $Function_decl[[foo]]($TemplateParameter[[T]] $Parameter_decl[[P]]) {
|
2019-10-15 02:26:13 +08:00
|
|
|
$Function[[phase1]]($Parameter[[P]]);
|
2021-01-30 08:12:36 +08:00
|
|
|
$Unknown_dependentName[[phase2]]($Parameter[[P]]);
|
2019-10-15 02:26:13 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[A]] {
|
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
void $Method_decl[[bar]]($TemplateParameter[[T]]);
|
2019-10-15 02:26:13 +08:00
|
|
|
};
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
template <class $TemplateParameter_decl[[U]]>
|
|
|
|
void $Function_decl[[foo]]($TemplateParameter[[U]] $Parameter_decl[[P]]) {
|
2019-10-15 02:26:13 +08:00
|
|
|
$Class[[A]]().$Method[[bar]]($Parameter[[P]]);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[A]] {
|
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
static void $StaticMethod_decl_static[[foo]]($TemplateParameter[[T]]);
|
2019-10-15 02:26:13 +08:00
|
|
|
};
|
|
|
|
|
2021-01-27 16:47:17 +08:00
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
struct $Class_decl[[B]] {
|
|
|
|
void $Method_decl[[bar]]() {
|
|
|
|
$Class[[A]]::$StaticMethod_static[[foo]]($TemplateParameter[[T]]());
|
2019-10-15 02:26:13 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
2021-01-30 08:12:36 +08:00
|
|
|
void $Function_decl[[foo]](typename $TemplateParameter[[T]]::$Type_dependentName[[Type]]
|
|
|
|
= $TemplateParameter[[T]]::$Unknown_dependentName[[val]]);
|
2019-10-15 02:26:13 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
void $Function_decl[[foo]]($TemplateParameter[[T]] $Parameter_decl[[P]]) {
|
2021-01-30 08:12:36 +08:00
|
|
|
$Parameter[[P]].$Unknown_dependentName[[Field]];
|
2019-10-15 02:26:13 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <class $TemplateParameter_decl[[T]]>
|
|
|
|
class $Class_decl[[A]] {
|
|
|
|
int $Method_decl[[foo]]() {
|
2021-01-30 08:12:36 +08:00
|
|
|
return $TemplateParameter[[T]]::$Unknown_dependentName[[Field]];
|
2019-10-15 02:26:13 +08:00
|
|
|
}
|
|
|
|
};
|
2019-10-28 20:42:20 +08:00
|
|
|
)cpp",
|
|
|
|
// Highlighting the using decl as the underlying using shadow decl.
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
void $Function_decl[[foo]]();
|
2019-10-28 20:42:20 +08:00
|
|
|
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(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <template <class> class $TemplateParameter_decl[[TT]],
|
|
|
|
template <class> class ...$TemplateParameter_decl[[TTs]]>
|
|
|
|
struct $Class_decl[[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
|
|
|
$Class[[Foo]]<$TemplateParameter[[TT]], $TemplateParameter[[TTs]]...>
|
2021-01-27 16:47:17 +08:00
|
|
|
*$Field_decl[[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.
|
2020-08-26 16:50:31 +08:00
|
|
|
$InactiveCode[[#ifdef test]]
|
|
|
|
$InactiveCode[[#endif]]
|
2019-09-25 06:17:55 +08:00
|
|
|
|
|
|
|
// A declaration to cause the preamble to end.
|
2021-01-27 16:47:17 +08:00
|
|
|
int $Variable_decl[[EndPreamble]];
|
2019-09-25 06:17:55 +08:00
|
|
|
|
|
|
|
// Code after the preamble.
|
|
|
|
// Code inside inactive blocks does not get regular highlightings
|
|
|
|
// because it's not part of the AST.
|
2021-01-27 16:47:17 +08:00
|
|
|
#define $Macro_decl[[test2]]
|
2020-11-26 10:31:09 +08:00
|
|
|
$InactiveCode[[#if defined(test)]]
|
2020-08-26 16:50:31 +08:00
|
|
|
$InactiveCode[[int Inactive2;]]
|
2020-11-26 10:31:09 +08:00
|
|
|
$InactiveCode[[#elif defined(test2)]]
|
2021-01-27 16:47:17 +08:00
|
|
|
int $Variable_decl[[Active1]];
|
2020-11-26 10:31:09 +08:00
|
|
|
$InactiveCode[[#else]]
|
|
|
|
$InactiveCode[[int Inactive3;]]
|
2020-08-26 16:50:31 +08:00
|
|
|
$InactiveCode[[#endif]]
|
2019-09-25 06:17:55 +08:00
|
|
|
|
|
|
|
#ifndef $Macro[[test]]
|
2021-01-27 16:47:17 +08:00
|
|
|
int $Variable_decl[[Active2]];
|
2019-09-25 06:17:55 +08:00
|
|
|
#endif
|
|
|
|
|
2020-08-26 16:50:31 +08:00
|
|
|
$InactiveCode[[#ifdef test]]
|
2020-11-26 10:31:09 +08:00
|
|
|
$InactiveCode[[int Inactive4;]]
|
2020-08-26 16:50:31 +08:00
|
|
|
$InactiveCode[[#else]]
|
2021-01-27 16:47:17 +08:00
|
|
|
int $Variable_decl[[Active3]];
|
2019-09-25 06:17:55 +08:00
|
|
|
#endif
|
2019-12-06 03:27:23 +08:00
|
|
|
)cpp",
|
|
|
|
// Argument to 'sizeof...'
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <typename... $TemplateParameter_decl[[Elements]]>
|
|
|
|
struct $Class_decl[[TupleSize]] {
|
|
|
|
static const int $StaticField_decl_readonly_static[[size]] =
|
2019-12-06 03:28:56 +08:00
|
|
|
sizeof...($TemplateParameter[[Elements]]);
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
// More dependent types
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
struct $Class_decl[[Waldo]] {
|
|
|
|
using $Typedef_decl[[Location1]] = typename $TemplateParameter[[T]]
|
2021-01-30 08:12:36 +08:00
|
|
|
::$Type_dependentName[[Resolver]]::$Type_dependentName[[Location]];
|
2021-01-27 16:47:17 +08:00
|
|
|
using $Typedef_decl[[Location2]] = typename $TemplateParameter[[T]]
|
2021-01-30 08:12:36 +08:00
|
|
|
::template $Type_dependentName[[Resolver]]<$TemplateParameter[[T]]>
|
|
|
|
::$Type_dependentName[[Location]];
|
2021-01-27 16:47:17 +08:00
|
|
|
using $Typedef_decl[[Location3]] = typename $TemplateParameter[[T]]
|
2021-01-30 08:12:36 +08:00
|
|
|
::$Type_dependentName[[Resolver]]
|
|
|
|
::template $Type_dependentName[[Location]]<$TemplateParameter[[T]]>;
|
2021-01-27 16:47:17 +08:00
|
|
|
static const int $StaticField_decl_readonly_static[[Value]] = $TemplateParameter[[T]]
|
2021-01-30 08:12:36 +08:00
|
|
|
::$Type_dependentName[[Resolver]]::$Unknown_dependentName[[Value]];
|
2019-12-06 03:27:23 +08:00
|
|
|
};
|
2020-03-20 03:42:10 +08:00
|
|
|
)cpp",
|
|
|
|
// Dependent name with heuristic target
|
|
|
|
R"cpp(
|
|
|
|
template <typename>
|
2021-01-27 16:47:17 +08:00
|
|
|
struct $Class_decl[[Foo]] {
|
|
|
|
int $Field_decl[[Waldo]];
|
|
|
|
void $Method_decl[[bar]]() {
|
2021-01-30 08:12:36 +08:00
|
|
|
$Class[[Foo]]().$Field_dependentName[[Waldo]];
|
2020-03-20 03:42:10 +08:00
|
|
|
}
|
2021-01-27 16:47:17 +08:00
|
|
|
template <typename $TemplateParameter_decl[[U]]>
|
|
|
|
void $Method_decl[[bar1]]() {
|
2021-01-30 08:12:36 +08:00
|
|
|
$Class[[Foo]]<$TemplateParameter[[U]]>().$Field_dependentName[[Waldo]];
|
2020-03-20 03:42:10 +08:00
|
|
|
}
|
2022-03-16 16:01:43 +08:00
|
|
|
|
|
|
|
void $Method_decl[[Overload]]();
|
|
|
|
void $Method_decl_readonly[[Overload]]() const;
|
2020-03-20 03:42:10 +08:00
|
|
|
};
|
2022-03-16 16:01:43 +08:00
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
void $Function_decl[[baz]]($Class[[Foo]]<$TemplateParameter[[T]]> $Parameter_decl[[o]]) {
|
|
|
|
$Parameter[[o]].$Method_readonly_dependentName[[Overload]]();
|
|
|
|
}
|
2020-01-22 02:21:08 +08:00
|
|
|
)cpp",
|
|
|
|
// Concepts
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
concept $Concept_decl[[Fooable]] =
|
|
|
|
requires($TemplateParameter[[T]] $Parameter_decl[[F]]) {
|
2021-01-30 08:12:36 +08:00
|
|
|
$Parameter[[F]].$Unknown_dependentName[[foo]]();
|
2020-01-22 02:21:08 +08:00
|
|
|
};
|
2021-01-27 16:47:17 +08:00
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
2020-01-22 02:21:08 +08:00
|
|
|
requires $Concept[[Fooable]]<$TemplateParameter[[T]]>
|
2021-01-27 16:47:17 +08:00
|
|
|
void $Function_decl[[bar]]($TemplateParameter[[T]] $Parameter_decl[[F]]) {
|
2021-01-30 08:12:36 +08:00
|
|
|
$Parameter[[F]].$Unknown_dependentName[[foo]]();
|
2020-01-22 02:21:08 +08:00
|
|
|
}
|
2020-08-05 11:33:41 +08:00
|
|
|
)cpp",
|
|
|
|
// Dependent template name
|
|
|
|
R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
template <template <typename> class> struct $Class_decl[[A]] {};
|
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
using $Typedef_decl[[W]] = $Class[[A]]<
|
2021-01-30 08:12:36 +08:00
|
|
|
$TemplateParameter[[T]]::template $Class_dependentName[[Waldo]]
|
2020-08-05 11:33:41 +08:00
|
|
|
>;
|
2021-01-27 16:47:17 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
class $Class_decl_abstract[[Abstract]] {
|
2021-08-04 10:53:01 +08:00
|
|
|
public:
|
|
|
|
virtual void $Method_decl_abstract_virtual[[pure]]() = 0;
|
|
|
|
virtual void $Method_decl_virtual[[impl]]();
|
2021-01-27 16:47:17 +08:00
|
|
|
};
|
2021-08-04 10:53:01 +08:00
|
|
|
void $Function_decl[[foo]]($Class_abstract[[Abstract]]* $Parameter_decl[[A]]) {
|
|
|
|
$Parameter[[A]]->$Method_abstract_virtual[[pure]]();
|
|
|
|
$Parameter[[A]]->$Method_virtual[[impl]]();
|
|
|
|
}
|
2021-01-27 16:47:17 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
<:[deprecated]:> int $Variable_decl_deprecated[[x]];
|
|
|
|
)cpp",
|
2021-02-28 05:08:07 +08:00
|
|
|
R"cpp(
|
|
|
|
// ObjC: Classes and methods
|
|
|
|
@class $Class_decl[[Forward]];
|
|
|
|
|
|
|
|
@interface $Class_decl[[Foo]]
|
|
|
|
@end
|
|
|
|
@interface $Class_decl[[Bar]] : $Class[[Foo]]
|
2021-08-23 22:30:49 +08:00
|
|
|
-(id) $Method_decl[[x]]:(int)$Parameter_decl[[a]] $Method_decl[[y]]:(int)$Parameter_decl[[b]];
|
|
|
|
+(instancetype)$StaticMethod_decl_static[[sharedInstance]];
|
2021-02-28 05:08:07 +08:00
|
|
|
+(void) $StaticMethod_decl_static[[explode]];
|
|
|
|
@end
|
|
|
|
@implementation $Class_decl[[Bar]]
|
2021-08-23 22:30:49 +08:00
|
|
|
-(id) $Method_decl[[x]]:(int)$Parameter_decl[[a]] $Method_decl[[y]]:(int)$Parameter_decl[[b]] {
|
2021-02-28 05:08:07 +08:00
|
|
|
return self;
|
|
|
|
}
|
2021-08-23 22:30:49 +08:00
|
|
|
+(instancetype)$StaticMethod_decl_static[[sharedInstance]] { return 0; }
|
2021-02-28 05:08:07 +08:00
|
|
|
+(void) $StaticMethod_decl_static[[explode]] {}
|
|
|
|
@end
|
|
|
|
|
|
|
|
void $Function_decl[[m]]($Class[[Bar]] *$Parameter_decl[[b]]) {
|
|
|
|
[$Parameter[[b]] $Method[[x]]:1 $Method[[y]]:2];
|
|
|
|
[$Class[[Bar]] $StaticMethod_static[[explode]]];
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
// ObjC: Protocols
|
|
|
|
@protocol $Interface_decl[[Protocol]]
|
|
|
|
@end
|
|
|
|
@protocol $Interface_decl[[Protocol2]] <$Interface[[Protocol]]>
|
|
|
|
@end
|
|
|
|
@interface $Class_decl[[Klass]] <$Interface[[Protocol]]>
|
|
|
|
@end
|
2021-03-20 04:23:15 +08:00
|
|
|
id<$Interface[[Protocol]]> $Variable_decl[[x]];
|
2021-02-28 05:08:07 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
// ObjC: Categories
|
|
|
|
@interface $Class_decl[[Foo]]
|
|
|
|
@end
|
|
|
|
@interface $Class[[Foo]]($Namespace_decl[[Bar]])
|
|
|
|
@end
|
|
|
|
@implementation $Class[[Foo]]($Namespace_decl[[Bar]])
|
|
|
|
@end
|
|
|
|
)cpp",
|
2021-05-04 04:18:57 +08:00
|
|
|
R"cpp(
|
|
|
|
// ObjC: Properties and Ivars.
|
|
|
|
@interface $Class_decl[[Foo]] {
|
|
|
|
int $Field_decl[[_someProperty]];
|
|
|
|
}
|
|
|
|
@property(nonatomic, assign) int $Field_decl[[someProperty]];
|
2021-06-11 22:16:19 +08:00
|
|
|
@property(readonly, class) $Class[[Foo]] *$Field_decl_readonly_static[[sharedInstance]];
|
2021-05-04 04:18:57 +08:00
|
|
|
@end
|
|
|
|
@implementation $Class_decl[[Foo]]
|
|
|
|
@synthesize someProperty = _someProperty;
|
2021-06-11 22:16:19 +08:00
|
|
|
- (int)$Method_decl[[otherMethod]] {
|
|
|
|
return 0;
|
|
|
|
}
|
2021-05-04 04:18:57 +08:00
|
|
|
- (int)$Method_decl[[doSomething]] {
|
2021-06-11 22:16:19 +08:00
|
|
|
$Class[[Foo]].$Field_static[[sharedInstance]].$Field[[someProperty]] = 1;
|
|
|
|
self.$Field[[someProperty]] = self.$Field[[someProperty]] + self.$Field[[otherMethod]] + 1;
|
2021-05-04 04:18:57 +08:00
|
|
|
self->$Field[[_someProperty]] = $Field[[_someProperty]] + 1;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
)cpp",
|
2021-03-22 14:13:53 +08:00
|
|
|
// Member imported from dependent base
|
|
|
|
R"cpp(
|
|
|
|
template <typename> struct $Class_decl[[Base]] {
|
|
|
|
int $Field_decl[[member]];
|
|
|
|
};
|
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
struct $Class_decl[[Derived]] : $Class[[Base]]<$TemplateParameter[[T]]> {
|
2021-03-22 14:43:41 +08:00
|
|
|
using $Class[[Base]]<$TemplateParameter[[T]]>::$Field_dependentName[[member]];
|
2021-03-22 14:13:53 +08:00
|
|
|
|
|
|
|
void $Method_decl[[method]]() {
|
2021-03-22 14:43:41 +08:00
|
|
|
(void)$Field_dependentName[[member]];
|
2021-03-22 14:13:53 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
)cpp",
|
2021-09-13 12:34:02 +08:00
|
|
|
// Modifier for variables passed as non-const references
|
|
|
|
R"cpp(
|
2022-06-30 08:12:36 +08:00
|
|
|
struct $Class_decl[[ClassWithOp]] {
|
|
|
|
void operator()(int);
|
|
|
|
void operator()(int, int &);
|
|
|
|
void operator()(int, int, const int &);
|
2022-07-01 16:43:23 +08:00
|
|
|
int &operator[](int &);
|
|
|
|
int operator[](int) const;
|
2022-06-30 08:12:36 +08:00
|
|
|
};
|
2022-07-08 16:12:31 +08:00
|
|
|
struct $Class_decl[[ClassWithStaticMember]] {
|
|
|
|
static inline int $StaticField_decl_static[[j]] = 0;
|
|
|
|
};
|
|
|
|
struct $Class_decl[[ClassWithRefMembers]] {
|
|
|
|
$Class_decl[[ClassWithRefMembers]](int $Parameter_decl[[i]])
|
|
|
|
: $Field[[i1]]($Parameter[[i]]),
|
|
|
|
$Field_readonly[[i2]]($Parameter[[i]]),
|
|
|
|
$Field[[i3]]($Parameter_usedAsMutableReference[[i]]),
|
|
|
|
$Field_readonly[[i4]]($Class[[ClassWithStaticMember]]::$StaticField_static[[j]]),
|
|
|
|
$Field[[i5]]($Class[[ClassWithStaticMember]]::$StaticField_static_usedAsMutableReference[[j]])
|
|
|
|
{}
|
|
|
|
int $Field_decl[[i1]];
|
|
|
|
const int &$Field_decl_readonly[[i2]];
|
|
|
|
int &$Field_decl[[i3]];
|
|
|
|
const int &$Field_decl_readonly[[i4]];
|
|
|
|
int &$Field_decl[[i5]];
|
|
|
|
};
|
2021-09-13 12:34:02 +08:00
|
|
|
void $Function_decl[[fun]](int, const int,
|
|
|
|
int*, const int*,
|
|
|
|
int&, const int&,
|
|
|
|
int*&, const int*&, const int* const &,
|
|
|
|
int**, int**&, int** const &,
|
|
|
|
int = 123) {
|
|
|
|
int $LocalVariable_decl[[val]];
|
|
|
|
int* $LocalVariable_decl[[ptr]];
|
|
|
|
const int* $LocalVariable_decl_readonly[[constPtr]];
|
|
|
|
int** $LocalVariable_decl[[array]];
|
|
|
|
$Function[[fun]]($LocalVariable[[val]], $LocalVariable[[val]],
|
|
|
|
$LocalVariable[[ptr]], $LocalVariable_readonly[[constPtr]],
|
|
|
|
$LocalVariable_usedAsMutableReference[[val]], $LocalVariable[[val]],
|
|
|
|
|
|
|
|
$LocalVariable_usedAsMutableReference[[ptr]],
|
|
|
|
$LocalVariable_readonly_usedAsMutableReference[[constPtr]],
|
|
|
|
$LocalVariable_readonly[[constPtr]],
|
|
|
|
|
|
|
|
$LocalVariable[[array]], $LocalVariable_usedAsMutableReference[[array]],
|
|
|
|
$LocalVariable[[array]]
|
|
|
|
);
|
2022-06-30 08:12:36 +08:00
|
|
|
[](int){}($LocalVariable[[val]]);
|
|
|
|
[](int&){}($LocalVariable_usedAsMutableReference[[val]]);
|
|
|
|
[](const int&){}($LocalVariable[[val]]);
|
|
|
|
$Class[[ClassWithOp]] $LocalVariable_decl[[c]];
|
2022-07-01 16:43:23 +08:00
|
|
|
const $Class[[ClassWithOp]] $LocalVariable_decl_readonly[[c2]];
|
2022-06-30 08:12:36 +08:00
|
|
|
$LocalVariable[[c]]($LocalVariable[[val]]);
|
|
|
|
$LocalVariable[[c]](0, $LocalVariable_usedAsMutableReference[[val]]);
|
|
|
|
$LocalVariable[[c]](0, 0, $LocalVariable[[val]]);
|
2022-07-01 16:43:23 +08:00
|
|
|
$LocalVariable[[c]][$LocalVariable_usedAsMutableReference[[val]]];
|
|
|
|
$LocalVariable_readonly[[c2]][$LocalVariable[[val]]];
|
2021-09-13 12:34:02 +08:00
|
|
|
}
|
|
|
|
struct $Class_decl[[S]] {
|
|
|
|
$Class_decl[[S]](int&) {
|
|
|
|
$Class[[S]] $LocalVariable_decl[[s1]]($Field_usedAsMutableReference[[field]]);
|
|
|
|
$Class[[S]] $LocalVariable_decl[[s2]]($LocalVariable[[s1]].$Field_usedAsMutableReference[[field]]);
|
|
|
|
|
|
|
|
$Class[[S]] $LocalVariable_decl[[s3]]($StaticField_static_usedAsMutableReference[[staticField]]);
|
|
|
|
$Class[[S]] $LocalVariable_decl[[s4]]($Class[[S]]::$StaticField_static_usedAsMutableReference[[staticField]]);
|
|
|
|
}
|
|
|
|
int $Field_decl[[field]];
|
|
|
|
static int $StaticField_decl_static[[staticField]];
|
|
|
|
};
|
|
|
|
template <typename $TemplateParameter_decl[[X]]>
|
|
|
|
void $Function_decl[[foo]]($TemplateParameter[[X]]& $Parameter_decl[[x]]) {
|
|
|
|
// We do not support dependent types, so this one should *not* get the modifier.
|
|
|
|
$Function[[foo]]($Parameter[[x]]);
|
|
|
|
}
|
|
|
|
)cpp",
|
2021-09-21 15:44:31 +08:00
|
|
|
// init-captures
|
|
|
|
R"cpp(
|
|
|
|
void $Function_decl[[foo]]() {
|
|
|
|
int $LocalVariable_decl[[a]], $LocalVariable_decl[[b]];
|
|
|
|
[ $LocalVariable_decl[[c]] = $LocalVariable[[a]],
|
|
|
|
$LocalVariable_decl[[d]]($LocalVariable[[b]]) ]() {}();
|
|
|
|
}
|
|
|
|
)cpp",
|
2021-10-07 03:48:14 +08:00
|
|
|
// Enum base specifier
|
|
|
|
R"cpp(
|
|
|
|
using $Primitive_decl[[MyTypedef]] = int;
|
|
|
|
enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {};
|
|
|
|
)cpp",
|
|
|
|
// Enum base specifier
|
|
|
|
R"cpp(
|
|
|
|
typedef int $Primitive_decl[[MyTypedef]];
|
|
|
|
enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {};
|
|
|
|
)cpp",
|
2022-04-13 14:54:12 +08:00
|
|
|
// Issue 1096
|
|
|
|
R"cpp(
|
|
|
|
void $Function_decl[[Foo]]();
|
|
|
|
// Use <: :> digraphs for deprecated attribute to avoid conflict with annotation syntax
|
|
|
|
<:<:deprecated:>:> void $Function_decl_deprecated[[Foo]](int* $Parameter_decl[[x]]);
|
|
|
|
void $Function_decl[[Foo]](int $Parameter_decl[[x]]);
|
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
void $Function_decl[[Bar]]($TemplateParameter[[T]] $Parameter_decl[[x]]) {
|
|
|
|
$Function_deprecated[[Foo]]($Parameter[[x]]);
|
|
|
|
$Function_deprecated[[Foo]]($Parameter[[x]]);
|
|
|
|
$Function_deprecated[[Foo]]($Parameter[[x]]);
|
|
|
|
}
|
2022-06-06 13:58:00 +08:00
|
|
|
)cpp",
|
|
|
|
// Explicit template specialization
|
|
|
|
R"cpp(
|
|
|
|
struct $Class_decl[[Base]]{};
|
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
struct $Class_decl[[S]] : public $Class[[Base]] {};
|
|
|
|
template <>
|
|
|
|
struct $Class_decl[[S]]<void> : public $Class[[Base]] {};
|
|
|
|
|
|
|
|
template <typename $TemplateParameter_decl[[T]]>
|
|
|
|
$TemplateParameter[[T]] $Variable_decl[[x]] = {};
|
|
|
|
template <>
|
|
|
|
int $Variable_decl[[x]]<int> = (int)sizeof($Class[[Base]]);
|
2022-04-13 14:54:12 +08:00
|
|
|
)cpp"};
|
2021-01-30 06:18:34 +08:00
|
|
|
for (const auto &TestCase : TestCases)
|
|
|
|
// Mask off scope modifiers to keep the tests manageable.
|
|
|
|
// They're tested separately.
|
|
|
|
checkHighlightings(TestCase, {}, ~ScopeModifierMask);
|
2019-08-12 21:01:11 +08:00
|
|
|
|
|
|
|
checkHighlightings(R"cpp(
|
2021-01-27 16:47:17 +08:00
|
|
|
class $Class_decl[[A]] {
|
2019-08-12 21:01:11 +08:00
|
|
|
#include "imp.h"
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
{{"imp.h", R"cpp(
|
|
|
|
int someMethod();
|
|
|
|
void otherMethod();
|
2021-01-30 06:18:34 +08:00
|
|
|
)cpp"}},
|
|
|
|
~ScopeModifierMask);
|
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)
|
2021-01-30 06:18:34 +08:00
|
|
|
)cpp"}},
|
|
|
|
~ScopeModifierMask);
|
2021-04-30 01:03:10 +08:00
|
|
|
|
|
|
|
checkHighlightings(R"cpp(
|
|
|
|
#include "SYSObject.h"
|
|
|
|
@interface $Class_defaultLibrary[[SYSObject]] ($Namespace_decl[[UserCategory]])
|
|
|
|
@property(nonatomic, readonly) int $Field_decl_readonly[[user_property]];
|
|
|
|
@end
|
|
|
|
int $Function_decl[[somethingUsingSystemSymbols]]() {
|
|
|
|
$Class_defaultLibrary[[SYSObject]] *$LocalVariable_decl[[obj]] = [$Class_defaultLibrary[[SYSObject]] $StaticMethod_static_defaultLibrary[[new]]];
|
|
|
|
return $LocalVariable[[obj]].$Field_defaultLibrary[[value]] + $LocalVariable[[obj]].$Field_readonly[[user_property]];
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
{{"SystemSDK/SYSObject.h", R"cpp(
|
|
|
|
@interface SYSObject
|
|
|
|
@property(nonatomic, assign) int value;
|
|
|
|
+ (instancetype)new;
|
|
|
|
@end
|
|
|
|
)cpp"}},
|
|
|
|
~ScopeModifierMask, {"-isystemSystemSDK/"});
|
2021-01-30 06:18:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SemanticHighlighting, ScopeModifiers) {
|
|
|
|
const char *TestCases[] = {
|
|
|
|
R"cpp(
|
|
|
|
static int $Variable_fileScope[[x]];
|
|
|
|
namespace $Namespace_globalScope[[ns]] {
|
|
|
|
class $Class_globalScope[[x]];
|
|
|
|
}
|
|
|
|
namespace {
|
|
|
|
void $Function_fileScope[[foo]]();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
void $Function_globalScope[[foo]](int $Parameter_functionScope[[y]]) {
|
|
|
|
int $LocalVariable_functionScope[[z]];
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
// Lambdas are considered functions, not classes.
|
2021-09-21 15:44:31 +08:00
|
|
|
auto $Variable_fileScope[[x]] = [$LocalVariable_functionScope[[m]](42)] {
|
2021-01-30 06:18:34 +08:00
|
|
|
return $LocalVariable_functionScope[[m]];
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
// Classes in functions are classes.
|
|
|
|
void $Function_globalScope[[foo]]() {
|
|
|
|
class $Class_functionScope[[X]] {
|
|
|
|
int $Field_classScope[[x]];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <int $TemplateParameter_classScope[[T]]>
|
|
|
|
class $Class_globalScope[[X]] {
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
// No useful scope for template parameters of variable templates.
|
|
|
|
template <typename $TemplateParameter[[A]]>
|
|
|
|
unsigned $Variable_globalScope[[X]] =
|
2021-01-30 08:12:36 +08:00
|
|
|
$TemplateParameter[[A]]::$Unknown_classScope[[x]];
|
2021-01-30 06:18:34 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define $Macro_globalScope[[X]] 1
|
|
|
|
int $Variable_globalScope[[Y]] = $Macro_globalScope[[X]];
|
|
|
|
)cpp",
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const char *Test : TestCases)
|
|
|
|
checkHighlightings(Test, {}, ScopeModifierMask);
|
2019-06-26 21:08:36 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
// Ranges are highlighted as variables, unless highlighted as $Function etc.
|
|
|
|
std::vector<HighlightingToken> tokens(llvm::StringRef MarkedText) {
|
|
|
|
Annotations A(MarkedText);
|
|
|
|
std::vector<HighlightingToken> Results;
|
|
|
|
for (const Range& R : A.ranges())
|
2021-01-27 16:47:17 +08:00
|
|
|
Results.push_back({HighlightingKind::Variable, 0, R});
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
for (unsigned I = 0; I < static_cast<unsigned>(HighlightingKind::LastKind); ++I) {
|
|
|
|
HighlightingKind Kind = static_cast<HighlightingKind>(I);
|
|
|
|
for (const Range& R : A.ranges(llvm::to_string(Kind)))
|
2021-01-27 16:47:17 +08:00
|
|
|
Results.push_back({Kind, 0, R});
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
}
|
|
|
|
llvm::sort(Results);
|
|
|
|
return Results;
|
|
|
|
}
|
|
|
|
|
2020-03-24 09:24:47 +08:00
|
|
|
TEST(SemanticHighlighting, toSemanticTokens) {
|
2021-01-27 16:47:17 +08:00
|
|
|
auto Tokens = tokens(R"(
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
[[blah]]
|
2020-03-24 09:24:47 +08:00
|
|
|
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
$Function[[big]] [[bang]]
|
2021-01-27 16:47:17 +08:00
|
|
|
)");
|
|
|
|
Tokens.front().Modifiers |= unsigned(HighlightingModifier::Declaration);
|
|
|
|
Tokens.front().Modifiers |= unsigned(HighlightingModifier::Readonly);
|
2022-06-15 21:44:09 +08:00
|
|
|
auto Results = toSemanticTokens(Tokens, /*Code=*/"");
|
2020-03-24 09:24:47 +08:00
|
|
|
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
ASSERT_THAT(Results, SizeIs(3));
|
2020-03-24 09:24:47 +08:00
|
|
|
EXPECT_EQ(Results[0].tokenType, unsigned(HighlightingKind::Variable));
|
2021-01-27 16:47:17 +08:00
|
|
|
EXPECT_EQ(Results[0].tokenModifiers,
|
|
|
|
unsigned(HighlightingModifier::Declaration) |
|
|
|
|
unsigned(HighlightingModifier::Readonly));
|
2020-03-24 09:24:47 +08:00
|
|
|
EXPECT_EQ(Results[0].deltaLine, 1u);
|
|
|
|
EXPECT_EQ(Results[0].deltaStart, 1u);
|
|
|
|
EXPECT_EQ(Results[0].length, 4u);
|
|
|
|
|
|
|
|
EXPECT_EQ(Results[1].tokenType, unsigned(HighlightingKind::Function));
|
2021-01-27 16:47:17 +08:00
|
|
|
EXPECT_EQ(Results[1].tokenModifiers, 0u);
|
2020-03-24 09:24:47 +08:00
|
|
|
EXPECT_EQ(Results[1].deltaLine, 2u);
|
|
|
|
EXPECT_EQ(Results[1].deltaStart, 4u);
|
|
|
|
EXPECT_EQ(Results[1].length, 3u);
|
|
|
|
|
|
|
|
EXPECT_EQ(Results[2].tokenType, unsigned(HighlightingKind::Variable));
|
2021-01-27 16:47:17 +08:00
|
|
|
EXPECT_EQ(Results[1].tokenModifiers, 0u);
|
2020-03-24 09:24:47 +08:00
|
|
|
EXPECT_EQ(Results[2].deltaLine, 0u);
|
|
|
|
EXPECT_EQ(Results[2].deltaStart, 4u);
|
|
|
|
EXPECT_EQ(Results[2].length, 4u);
|
|
|
|
}
|
|
|
|
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
TEST(SemanticHighlighting, diffSemanticTokens) {
|
|
|
|
auto Before = toSemanticTokens(tokens(R"(
|
|
|
|
[[foo]] [[bar]] [[baz]]
|
|
|
|
[[one]] [[two]] [[three]]
|
2022-06-15 21:44:09 +08:00
|
|
|
)"),
|
|
|
|
/*Code=*/"");
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
EXPECT_THAT(diffTokens(Before, Before), IsEmpty());
|
|
|
|
|
|
|
|
auto After = toSemanticTokens(tokens(R"(
|
|
|
|
[[foo]] [[hello]] [[world]] [[baz]]
|
|
|
|
[[one]] [[two]] [[three]]
|
2022-06-15 21:44:09 +08:00
|
|
|
)"),
|
|
|
|
/*Code=*/"");
|
[clangd] Support textDocument/semanticTokens/edits
Summary:
This returns incremental highlights as a set of edits against the
previous highlights.
Server-side, we compute the full set of highlights, this just saves
wire-format size.
For now, the diff used is trivial: everything from the first change to
the last change is sent as a single edit.
The wire format is grungy - the replacement offset/length refer to
positions in the encoded array instead of the logical list of tokens.
We use token-oriented structs and translating to LSP forms when serializing.
This departs from LSP (but is consistent with semanticTokens today).
Tested in VSCode insiders (with a patched client to enable experimental
features).
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77225
2020-04-01 22:21:44 +08:00
|
|
|
|
|
|
|
// Replace [bar, baz] with [hello, world, baz]
|
|
|
|
auto Diff = diffTokens(Before, After);
|
|
|
|
ASSERT_THAT(Diff, SizeIs(1));
|
|
|
|
EXPECT_EQ(1u, Diff.front().startToken);
|
|
|
|
EXPECT_EQ(2u, Diff.front().deleteTokens);
|
|
|
|
ASSERT_THAT(Diff.front().tokens, SizeIs(3));
|
|
|
|
// hello
|
|
|
|
EXPECT_EQ(0u, Diff.front().tokens[0].deltaLine);
|
|
|
|
EXPECT_EQ(4u, Diff.front().tokens[0].deltaStart);
|
|
|
|
EXPECT_EQ(5u, Diff.front().tokens[0].length);
|
|
|
|
// world
|
|
|
|
EXPECT_EQ(0u, Diff.front().tokens[1].deltaLine);
|
|
|
|
EXPECT_EQ(6u, Diff.front().tokens[1].deltaStart);
|
|
|
|
EXPECT_EQ(5u, Diff.front().tokens[1].length);
|
|
|
|
// baz
|
|
|
|
EXPECT_EQ(0u, Diff.front().tokens[2].deltaLine);
|
|
|
|
EXPECT_EQ(6u, Diff.front().tokens[2].deltaStart);
|
|
|
|
EXPECT_EQ(3u, Diff.front().tokens[2].length);
|
|
|
|
}
|
|
|
|
|
2022-06-15 21:44:09 +08:00
|
|
|
TEST(SemanticHighlighting, MultilineTokens) {
|
|
|
|
llvm::StringRef AnnotatedCode = R"cpp(
|
|
|
|
[[fo
|
|
|
|
o
|
|
|
|
o]] [[bar]])cpp";
|
|
|
|
auto Toks = toSemanticTokens(tokens(AnnotatedCode),
|
|
|
|
Annotations(AnnotatedCode).code());
|
|
|
|
ASSERT_THAT(Toks, SizeIs(4));
|
|
|
|
// foo
|
|
|
|
EXPECT_EQ(Toks[0].deltaLine, 1u);
|
|
|
|
EXPECT_EQ(Toks[0].deltaStart, 2u);
|
|
|
|
EXPECT_EQ(Toks[0].length, 2u);
|
|
|
|
EXPECT_EQ(Toks[1].deltaLine, 1u);
|
|
|
|
EXPECT_EQ(Toks[1].deltaStart, 0u);
|
|
|
|
EXPECT_EQ(Toks[1].length, 1u);
|
|
|
|
EXPECT_EQ(Toks[2].deltaLine, 1u);
|
|
|
|
EXPECT_EQ(Toks[2].deltaStart, 0u);
|
|
|
|
EXPECT_EQ(Toks[2].length, 1u);
|
|
|
|
|
|
|
|
// bar
|
|
|
|
EXPECT_EQ(Toks[3].deltaLine, 0u);
|
|
|
|
EXPECT_EQ(Toks[3].deltaStart, 2u);
|
|
|
|
EXPECT_EQ(Toks[3].length, 3u);
|
|
|
|
}
|
2019-06-26 21:08:36 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
2019-10-13 21:15:27 +08:00
|
|
|
} // namespace clang
|