1323 lines · cpp
1//==- SemanticHighlightingTests.cpp - SemanticHighlighting tests-*- C++ -* -==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Annotations.h"10#include "Config.h"11#include "Protocol.h"12#include "SemanticHighlighting.h"13#include "SourceCode.h"14#include "TestTU.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/Support/Error.h"19#include "llvm/Support/ScopedPrinter.h"20#include "llvm/Support/raw_ostream.h"21#include "gmock/gmock.h"22#include <algorithm>23 24namespace clang {25namespace clangd {26namespace {27 28using testing::IsEmpty;29using testing::SizeIs;30 31/// Annotates the input code with provided semantic highlightings. Results look32/// something like:33/// class $Class[[X]] {34/// $Primitive[[int]] $Field[[a]] = 0;35/// };36std::string annotate(llvm::StringRef Input,37 llvm::ArrayRef<HighlightingToken> Tokens) {38 assert(llvm::is_sorted(39 Tokens, [](const HighlightingToken &L, const HighlightingToken &R) {40 return L.R.start < R.R.start;41 }));42 43 std::string Buf;44 llvm::raw_string_ostream OS(Buf);45 unsigned NextChar = 0;46 for (auto &T : Tokens) {47 unsigned StartOffset = llvm::cantFail(positionToOffset(Input, T.R.start));48 unsigned EndOffset = llvm::cantFail(positionToOffset(Input, T.R.end));49 assert(StartOffset <= EndOffset);50 assert(NextChar <= StartOffset);51 52 bool hasDef =53 T.Modifiers & (1 << uint32_t(HighlightingModifier::Definition));54 bool hasDecl =55 T.Modifiers & (1 << uint32_t(HighlightingModifier::Declaration));56 EXPECT_TRUE(!hasDef || hasDecl);57 58 OS << Input.substr(NextChar, StartOffset - NextChar);59 OS << '$' << T.Kind;60 for (unsigned I = 0;61 I <= static_cast<uint32_t>(HighlightingModifier::LastModifier); ++I) {62 if (T.Modifiers & (1 << I)) {63 // _decl_def is common and redundant, just print _def instead.64 if (I != uint32_t(HighlightingModifier::Declaration) || !hasDef)65 OS << '_' << static_cast<HighlightingModifier>(I);66 }67 }68 OS << "[[" << Input.substr(StartOffset, EndOffset - StartOffset) << "]]";69 NextChar = EndOffset;70 }71 OS << Input.substr(NextChar);72 return std::move(OS.str());73}74 75void checkHighlightings(llvm::StringRef Code,76 std::vector<std::pair</*FileName*/ llvm::StringRef,77 /*FileContent*/ llvm::StringRef>>78 AdditionalFiles = {},79 uint32_t ModifierMask = -1,80 std::vector<std::string> AdditionalArgs = {}) {81 Annotations Test(Code);82 TestTU TU;83 TU.Code = std::string(Test.code());84 85 TU.ExtraArgs.push_back("-std=c++20");86 TU.ExtraArgs.push_back("-xobjective-c++");87 TU.ExtraArgs.insert(std::end(TU.ExtraArgs), std::begin(AdditionalArgs),88 std::end(AdditionalArgs));89 90 for (auto File : AdditionalFiles)91 TU.AdditionalFiles.insert({File.first, std::string(File.second)});92 auto AST = TU.build();93 auto Actual =94 getSemanticHighlightings(AST, /*IncludeInactiveRegionTokens=*/true);95 for (auto &Token : Actual)96 Token.Modifiers &= ModifierMask;97 98 EXPECT_EQ(Code, annotate(Test.code(), Actual));99}100 101constexpr static uint32_t ScopeModifierMask =102 1 << unsigned(HighlightingModifier::FunctionScope) |103 1 << unsigned(HighlightingModifier::ClassScope) |104 1 << unsigned(HighlightingModifier::FileScope) |105 1 << unsigned(HighlightingModifier::GlobalScope);106 107TEST(SemanticHighlighting, GetsCorrectTokens) {108 const char *TestCases[] = {109 R"cpp(110 struct $Class_def[[AS]] {111 double $Field_decl[[SomeMember]];112 };113 struct {114 } $Variable_def[[S]];115 void $Function_def[[foo]](int $Parameter_def[[A]], $Class[[AS]] $Parameter_def[[As]]) {116 $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_def[[VeryLongVariableName]] = 12312;117 $Class[[AS]] $LocalVariable_def[[AA]];118 $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_def[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] $Operator[[+]] $Parameter[[A]];119 auto $LocalVariable_def[[FN]] = [ $LocalVariable[[AA]]](int $Parameter_def[[A]]) -> void {};120 $LocalVariable[[FN]]$Operator_userDefined[[(]]12312$Operator_userDefined[[)]];121 }122 )cpp",123 R"cpp(124 void $Function_decl[[foo]](int);125 void $Function_decl[[Gah]]();126 void $Function_def[[foo]]() {127 auto $LocalVariable_def[[Bou]] = $Function[[Gah]];128 }129 struct $Class_def[[A]] {130 void $Method_decl[[abc]]();131 };132 )cpp",133 R"cpp(134 namespace $Namespace_decl[[abc]] {135 template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]136 struct $Class_def[[A]] {137 $TemplateParameter[[T]] $Field_decl[[t]];138 };139 }140 template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]141 struct $Class_def[[C]] : $Namespace[[abc]]::$Class[[A]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] {142 typename $TemplateParameter[[T]]::$Type_dependentName[[A]]* $Field_decl[[D]];143 };144 $Namespace[[abc]]::$Class[[A]]$Bracket[[<]]int$Bracket[[>]] $Variable_def[[AA]];145 typedef $Namespace[[abc]]::$Class[[A]]$Bracket[[<]]int$Bracket[[>]] $Class_decl[[AAA]];146 struct $Class_def[[B]] {147 $Class_decl_constrDestr[[B]]();148 ~$Class_decl_constrDestr[[B]]();149 void operator$Operator_decl[[<<]]($Class[[B]]);150 $Class[[AAA]] $Field_decl[[AA]];151 };152 $Class[[B]]::$Class_def_constrDestr[[B]]() {}153 $Class[[B]]::~$Class_def_constrDestr[[B]]() {}154 void $Function_def[[f]] () {155 $Class[[B]] $LocalVariable_def[[BB]] = $Class[[B]]();156 $LocalVariable[[BB]].~$Class_constrDestr[[B]]();157 $Class[[B]]();158 }159 )cpp",160 R"cpp(161 enum class $Enum_decl[[E]] {162 $EnumConstant_decl_readonly[[A]],163 $EnumConstant_decl_readonly[[B]],164 };165 enum $Enum_decl[[EE]] {166 $EnumConstant_decl_readonly[[Hi]],167 };168 struct $Class_def[[A]] {169 $Enum[[E]] $Field_decl[[EEE]];170 $Enum[[EE]] $Field_decl[[EEEE]];171 };172 int $Variable_def[[I]] = $EnumConstant_readonly[[Hi]];173 $Enum[[E]] $Variable_def[[L]] = $Enum[[E]]::$EnumConstant_readonly[[B]];174 )cpp",175 R"cpp(176 namespace $Namespace_decl[[abc]] {177 namespace {}178 namespace $Namespace_decl[[bcd]] {179 struct $Class_def[[A]] {};180 namespace $Namespace_decl[[cde]] {181 struct $Class_def[[A]] {182 enum class $Enum_decl[[B]] {183 $EnumConstant_decl_readonly[[Hi]],184 };185 };186 }187 }188 }189 using namespace $Namespace[[abc]]::$Namespace[[bcd]];190 namespace $Namespace_decl[[vwz]] =191 $Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]];192 $Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable_def[[AA]];193 $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable_def[[AAA]] =194 $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::$EnumConstant_readonly[[Hi]];195 ::$Namespace[[vwz]]::$Class[[A]] $Variable_def[[B]];196 ::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable_def[[BB]];197 )cpp",198 R"cpp(199 struct $Class_def[[D]] {200 double $Field_decl[[C]];201 };202 struct $Class_def[[A]] {203 double $Field_decl[[B]];204 $Class[[D]] $Field_decl[[E]];205 static double $StaticField_decl_static[[S]];206 static void $StaticMethod_def_static[[bar]]() {}207 void $Method_def[[foo]]() {208 $Field[[B]] $Operator[[=]] 123;209 this->$Field[[B]] $Operator[[=]] 156;210 this->$Method[[foo]]();211 $Method[[foo]]();212 $StaticMethod_static[[bar]]();213 $StaticField_static[[S]] $Operator[[=]] 90.1;214 }215 };216 void $Function_def[[foo]]() {217 $Class[[A]] $LocalVariable_def[[AA]];218 $LocalVariable[[AA]].$Field[[B]] $Operator[[+=]] 2;219 $LocalVariable[[AA]].$Method[[foo]]();220 $LocalVariable[[AA]].$Field[[E]].$Field[[C]];221 $Class[[A]]::$StaticField_static[[S]] $Operator[[=]] 90;222 }223 )cpp",224 R"cpp(225 struct $Class_def[[AA]] {226 int $Field_decl[[A]];227 };228 int $Variable_def[[B]];229 $Class[[AA]] $Variable_def[[A]]{$Variable[[B]]};230 )cpp",231 R"cpp(232 namespace $Namespace_decl[[a]] {233 struct $Class_def[[A]] {};234 typedef char $Primitive_decl[[C]];235 }236 typedef $Namespace[[a]]::$Class[[A]] $Class_decl[[B]];237 using $Class_decl[[BB]] = $Namespace[[a]]::$Class[[A]];238 enum class $Enum_decl[[E]] {};239 typedef $Enum[[E]] $Enum_decl[[C]];240 typedef $Enum[[C]] $Enum_decl[[CC]];241 using $Enum_decl[[CD]] = $Enum[[CC]];242 $Enum[[CC]] $Function_decl[[f]]($Class[[B]]);243 $Enum[[CD]] $Function_decl[[f]]($Class[[BB]]);244 typedef $Namespace[[a]]::$Primitive[[C]] $Primitive_decl[[PC]];245 typedef float $Primitive_decl[[F]];246 )cpp",247 R"cpp(248 template$Bracket[[<]]typename $TemplateParameter_def[[T]], typename = void$Bracket[[>]]249 class $Class_def[[A]] {250 $TemplateParameter[[T]] $Field_decl[[AA]];251 $TemplateParameter[[T]] $Method_decl[[foo]]();252 };253 template$Bracket[[<]]class $TemplateParameter_def[[TT]]$Bracket[[>]]254 class $Class_def[[B]] {255 $Class[[A]]$Bracket[[<]]$TemplateParameter[[TT]]$Bracket[[>]] $Field_decl[[AA]];256 };257 template$Bracket[[<]]class $TemplateParameter_def[[TT]], class $TemplateParameter_def[[GG]]$Bracket[[>]]258 class $Class_def[[BB]] {};259 template$Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]260 class $Class_def[[BB]]$Bracket[[<]]$TemplateParameter[[T]], int$Bracket[[>]] {};261 template$Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]262 class $Class_def[[BB]]$Bracket[[<]]$TemplateParameter[[T]], $TemplateParameter[[T]]*$Bracket[[>]] {};263 264 template$Bracket[[<]]template$Bracket[[<]]class$Bracket[[>]] class $TemplateParameter_def[[T]], class $TemplateParameter_def[[C]]$Bracket[[>]]265 $TemplateParameter[[T]]$Bracket[[<]]$TemplateParameter[[C]]$Bracket[[>]] $Function_decl[[f]]();266 267 template$Bracket[[<]]typename$Bracket[[>]]268 class $Class_def[[Foo]] {};269 270 template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]271 void $Function_decl[[foo]]($TemplateParameter[[T]] ...);272 )cpp",273 R"cpp(274 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]275 struct $Class_def[[Tmpl]] {$TemplateParameter[[T]] $Field_decl[[x]] = 0;};276 extern template struct $Class_def[[Tmpl]]$Bracket[[<]]float$Bracket[[>]];277 template struct $Class_def[[Tmpl]]$Bracket[[<]]double$Bracket[[>]];278 )cpp",279 // This test is to guard against highlightings disappearing when using280 // conversion operators as their behaviour in the clang AST differ from281 // other CXXMethodDecls.282 R"cpp(283 class $Class_def[[Foo]] {};284 struct $Class_def[[Bar]] {285 explicit operator $Class[[Foo]]*() const;286 explicit operator int() const;287 operator $Class[[Foo]]();288 };289 void $Function_def[[f]]() {290 $Class[[Bar]] $LocalVariable_def[[B]];291 $Class[[Foo]] $LocalVariable_def[[F]] = $LocalVariable[[B]];292 $Class[[Foo]] *$LocalVariable_def[[FP]] = ($Class[[Foo]]*)$LocalVariable[[B]];293 int $LocalVariable_def[[I]] = (int)$LocalVariable[[B]];294 }295 )cpp",296 R"cpp(297 struct $Class_def[[B]] {};298 struct $Class_def[[A]] {299 $Class[[B]] $Field_decl[[BB]];300 $Class[[A]] &operator$Operator_decl[[=]]($Class[[A]] &&$Parameter_def[[O]]);301 };302 303 $Class[[A]] &$Class[[A]]::operator$Operator_def[[=]]($Class[[A]] &&$Parameter_def[[O]]) = default;304 )cpp",305 R"cpp(306 enum $Enum_decl[[En]] {307 $EnumConstant_decl_readonly[[EC]],308 };309 class $Class_def[[Foo]] {};310 class $Class_def[[Bar]] {311 public:312 $Class[[Foo]] $Field_decl[[Fo]];313 $Enum[[En]] $Field_decl[[E]];314 int $Field_decl[[I]];315 $Class_def_constrDestr[[Bar]] ($Class[[Foo]] $Parameter_def[[F]],316 $Enum[[En]] $Parameter_def[[E]])317 : $Field[[Fo]] ($Parameter[[F]]), $Field[[E]] ($Parameter[[E]]),318 $Field[[I]] (123) {}319 };320 class $Class_def[[Bar2]] : public $Class[[Bar]] {321 $Class_def_constrDestr[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant_readonly[[EC]]) {}322 };323 )cpp",324 R"cpp(325 enum $Enum_decl[[E]] {326 $EnumConstant_decl_readonly[[E]],327 };328 class $Class_def[[Foo]] {};329 $Enum_deduced[[auto]] $Variable_def[[AE]] = $Enum[[E]]::$EnumConstant_readonly[[E]];330 $Class_deduced[[auto]] $Variable_def[[AF]] = $Class[[Foo]]();331 $Class_deduced[[decltype]](auto) $Variable_def[[AF2]] = $Class[[Foo]]();332 $Class_deduced[[auto]] *$Variable_def[[AFP]] = $Operator[[&]]$Variable[[AF]];333 $Enum_deduced[[auto]] &$Variable_def[[AER]] = $Variable[[AE]];334 $Primitive_deduced_defaultLibrary[[auto]] $Variable_def[[Form]] = 10.2 $Operator[[+]] 2 $Operator[[*]] 4;335 $Primitive_deduced_defaultLibrary[[decltype]]($Variable[[Form]]) $Variable_def[[F]] = 10;336 auto $Variable_def[[Fun]] = []()->void{};337 )cpp",338 R"cpp(339 class $Class_def[[G]] {};340 template$Bracket[[<]]$Class[[G]] *$TemplateParameter_def_readonly[[U]]$Bracket[[>]]341 class $Class_def[[GP]] {};342 template$Bracket[[<]]$Class[[G]] &$TemplateParameter_def_readonly[[U]]$Bracket[[>]]343 class $Class_def[[GR]] {};344 template$Bracket[[<]]int *$TemplateParameter_def_readonly[[U]]$Bracket[[>]]345 class $Class_def[[IP]] {346 void $Method_def[[f]]() {347 $Operator[[*]]$TemplateParameter_readonly[[U]] $Operator[[+=]] 5;348 }349 };350 template$Bracket[[<]]unsigned $TemplateParameter_def_readonly[[U]] = 2$Bracket[[>]]351 class $Class_def[[Foo]] {352 void $Method_def[[f]]() {353 for(int $LocalVariable_def[[I]] = 0;354 $LocalVariable[[I]] $Operator[[<]] $TemplateParameter_readonly[[U]];) {}355 }356 };357 358 $Class[[G]] $Variable_def[[L]];359 void $Function_def[[f]]() {360 $Class[[Foo]]$Bracket[[<]]123$Bracket[[>]] $LocalVariable_def[[F]];361 $Class[[GP]]$Bracket[[<]]$Operator[[&]]$Variable[[L]]$Bracket[[>]] $LocalVariable_def[[LL]];362 $Class[[GR]]$Bracket[[<]]$Variable[[L]]$Bracket[[>]] $LocalVariable_def[[LLL]];363 }364 )cpp",365 R"cpp(366 template$Bracket[[<]]typename $TemplateParameter_def[[T]],367 void ($TemplateParameter[[T]]::*$TemplateParameter_def_readonly[[method]])(int)$Bracket[[>]]368 struct $Class_def[[G]] {369 void $Method_def[[foo]](370 $TemplateParameter[[T]] *$Parameter_def[[O]]) {371 ($Parameter[[O]]$Operator_userDefined[[->*]]$TemplateParameter_readonly[[method]])(10);372 373 }374 };375 struct $Class_def[[F]] {376 void $Method_decl[[f]](int);377 };378 template$Bracket[[<]]void (*$TemplateParameter_def_readonly[[Func]])()$Bracket[[>]]379 struct $Class_def[[A]] {380 void $Method_def[[f]]() {381 ($Operator[[*]]$TemplateParameter_readonly[[Func]])();382 }383 };384 385 void $Function_def[[foo]]() {386 $Class[[F]] $LocalVariable_def[[FF]];387 $Class[[G]]$Bracket[[<]]$Class[[F]], $Operator[[&]]$Class[[F]]::$Method[[f]]$Bracket[[>]] $LocalVariable_def[[GG]];388 $LocalVariable[[GG]].$Method[[foo]]($Operator[[&]]$LocalVariable_usedAsMutablePointer[[FF]]);389 $Class[[A]]$Bracket[[<]]$Function[[foo]]$Bracket[[>]] $LocalVariable_def[[AA]];390 }391 )cpp",392 // Tokens that share a source range but have conflicting Kinds are not393 // highlighted.394 R"cpp(395 #define $Macro_decl[[DEF_MULTIPLE]](X) namespace X { class X { int X; }; }396 #define $Macro_decl[[DEF_CLASS]](T) class T {};397 // Preamble ends.398 $Macro[[DEF_MULTIPLE]](XYZ);399 $Macro[[DEF_MULTIPLE]](XYZW);400 $Macro[[DEF_CLASS]]($Class_def[[A]])401 #define $Macro_decl[[MACRO_CONCAT]](X, V, T) T foo##X = V402 #define $Macro_decl[[DEF_VAR]](X, V) int X = V403 #define $Macro_decl[[DEF_VAR_T]](T, X, V) T X = V404 #define $Macro_decl[[DEF_VAR_REV]](V, X) $Macro[[DEF_VAR]](X, V)405 #define $Macro_decl[[CPY]](X) X406 #define $Macro_decl[[DEF_VAR_TYPE]](X, Y) X Y407 #define $Macro_decl[[SOME_NAME]] variable408 #define $Macro_decl[[SOME_NAME_SET]] variable2 = 123409 #define $Macro_decl[[INC_VAR]](X) X += 2410 void $Function_def[[foo]]() {411 $Macro[[DEF_VAR]]($LocalVariable_def[[X]], 123);412 $Macro[[DEF_VAR_REV]](908, $LocalVariable_def[[XY]]);413 int $Macro[[CPY]]( $LocalVariable_def[[XX]] );414 $Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable_def[[AA]]);415 double $Macro[[SOME_NAME]];416 int $Macro[[SOME_NAME_SET]];417 $LocalVariable[[variable]] $Operator[[=]] 20.1;418 $Macro[[MACRO_CONCAT]](var, 2, float);419 $Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]](420 $Macro[[CPY]]($LocalVariable_def[[Nested]])),421 $Macro[[CPY]]($Class[[A]]()));422 $Macro[[INC_VAR]]($LocalVariable[[variable]]);423 }424 void $Macro[[SOME_NAME]]();425 $Macro[[DEF_VAR]]($Variable_def[[MMMMM]], 567);426 $Macro[[DEF_VAR_REV]](756, $Variable_def[[AB]]);427 428 #define $Macro_decl[[CALL_FN]](F) F();429 #define $Macro_decl[[DEF_FN]](F) void F ()430 $Macro[[DEF_FN]]($Function_def[[g]]) {431 $Macro[[CALL_FN]]($Function[[foo]]);432 }433 )cpp",434 R"cpp(435 #define $Macro_decl[[fail]](expr) expr436 #define $Macro_decl[[assert]](COND) if (!(COND)) { $Macro[[fail]]("assertion failed" #COND); }437 // Preamble ends.438 int $Variable_def[[x]];439 int $Variable_def[[y]];440 int $Function_decl[[f]]();441 void $Function_def[[foo]]() {442 $Macro[[assert]]($Variable[[x]] $Operator[[!=]] $Variable[[y]]);443 $Macro[[assert]]($Variable[[x]] $Operator[[!=]] $Function[[f]]());444 }445 )cpp",446 // highlighting all macro references447 R"cpp(448 #ifndef $Macro[[name]]449 #define $Macro_decl[[name]]450 #endif451 452 #define $Macro_decl[[test]]453 #undef $Macro[[test]]454 #ifdef $Macro[[test]]455 #endif456 457 #if defined($Macro[[test]])458 #endif459 )cpp",460 R"cpp(461 struct $Class_def[[S]] {462 float $Field_decl[[Value]];463 $Class[[S]] *$Field_decl[[Next]];464 };465 $Class[[S]] $Variable_def[[Global]][2] = {$Class[[S]](), $Class[[S]]()};466 auto [$Variable_decl[[G1]], $Variable_decl[[G2]]] = $Variable[[Global]];467 void $Function_def[[f]]($Class[[S]] $Parameter_def[[P]]) {468 int $LocalVariable_def[[A]][2] = {1,2};469 auto [$LocalVariable_decl[[B1]], $LocalVariable_decl[[B2]]] = $LocalVariable[[A]];470 auto [$LocalVariable_decl[[G1]], $LocalVariable_decl[[G2]]] = $Variable[[Global]];471 $Class_deduced[[auto]] [$LocalVariable_decl[[P1]], $LocalVariable_decl[[P2]]] = $Parameter[[P]];472 // Highlights references to BindingDecls.473 $LocalVariable[[B1]]$Operator[[++]];474 }475 )cpp",476 R"cpp(477 template$Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]478 class $Class_def[[A]] {479 using $TemplateParameter_decl[[TemplateParam1]] = $TemplateParameter[[T]];480 typedef $TemplateParameter[[T]] $TemplateParameter_decl[[TemplateParam2]];481 using $Primitive_decl[[IntType]] = int;482 483 using $Typedef_decl[[Pointer]] = $TemplateParameter[[T]] *;484 using $Typedef_decl[[LVReference]] = $TemplateParameter[[T]] &;485 using $Typedef_decl[[RVReference]] = $TemplateParameter[[T]]&&;486 using $Typedef_decl[[Array]] = $TemplateParameter[[T]]*[3];487 using $Typedef_decl[[MemberPointer]] = int ($Class[[A]]::*)(int);488 489 // Use various previously defined typedefs in a function type.490 void $Method_decl[[func]](491 $Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]],492 $Typedef[[Array]], $Typedef[[MemberPointer]]);493 };494 )cpp",495 R"cpp(496 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]497 void $Function_decl[[phase1]]($TemplateParameter[[T]]);498 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]499 void $Function_def[[foo]]($TemplateParameter[[T]] $Parameter_def[[P]]) {500 $Function[[phase1]]($Parameter[[P]]);501 $Unknown_dependentName[[phase2]]($Parameter[[P]]);502 }503 )cpp",504 R"cpp(505 class $Class_def[[A]] {506 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]507 void $Method_decl[[bar]]($TemplateParameter[[T]]);508 };509 510 template $Bracket[[<]]class $TemplateParameter_def[[U]]$Bracket[[>]]511 void $Function_def[[foo]]($TemplateParameter[[U]] $Parameter_def[[P]]) {512 $Class[[A]]().$Method[[bar]]($Parameter[[P]]);513 }514 )cpp",515 R"cpp(516 struct $Class_def[[A]] {517 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]518 static void $StaticMethod_decl_static[[foo]]($TemplateParameter[[T]]);519 };520 521 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]522 struct $Class_def[[B]] {523 void $Method_def[[bar]]() {524 $Class[[A]]::$StaticMethod_static[[foo]]($TemplateParameter[[T]]());525 }526 };527 )cpp",528 R"cpp(529 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]530 void $Function_decl[[foo]](typename $TemplateParameter[[T]]::$Type_dependentName[[Type]]531 = $TemplateParameter[[T]]::$Unknown_dependentName[[val]]);532 )cpp",533 R"cpp(534 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]535 void $Function_def[[foo]]($TemplateParameter[[T]] $Parameter_def[[P]]) {536 $Parameter[[P]].$Unknown_dependentName[[Field]];537 }538 )cpp",539 R"cpp(540 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]541 class $Class_def[[A]] {542 int $Method_def[[foo]]() {543 return $TemplateParameter[[T]]::$Unknown_dependentName[[Field]];544 }545 };546 )cpp",547 // Highlighting the using decl as the underlying using shadow decl.548 R"cpp(549 void $Function_decl[[foo]]();550 using ::$Function[[foo]];551 )cpp",552 // Highlighting of template template arguments.553 R"cpp(554 template $Bracket[[<]]template $Bracket[[<]]class$Bracket[[>]] class $TemplateParameter_def[[TT]],555 template $Bracket[[<]]class$Bracket[[>]] class ...$TemplateParameter_def[[TTs]]$Bracket[[>]]556 struct $Class_def[[Foo]] {557 $Class[[Foo]]$Bracket[[<]]$TemplateParameter[[TT]], $TemplateParameter[[TTs]]...$Bracket[[>]]558 *$Field_decl[[t]];559 };560 )cpp",561 // Inactive code highlighting562 R"cpp(563 // Code in the preamble.564 // Inactive lines get an empty InactiveCode token at the beginning.565 #ifdef $Macro[[test]]566$InactiveCode[[int Inactive1;]]567 #endif568 569 // A declaration to cause the preamble to end.570 int $Variable_def[[EndPreamble]];571 572 // Code after the preamble.573 // Code inside inactive blocks does not get regular highlightings574 // because it's not part of the AST.575 #define $Macro_decl[[test2]]576 #if defined($Macro[[test]])577$InactiveCode[[int Inactive2;]]578 #elif defined($Macro[[test2]])579 int $Variable_def[[Active1]];580 #else581$InactiveCode[[int Inactive3;]]582 #endif583 584 #ifndef $Macro[[test]]585 int $Variable_def[[Active2]];586 #endif587 588 #ifdef $Macro[[test]]589$InactiveCode[[int Inactive4;]]590 #else591 int $Variable_def[[Active3]];592 #endif593 )cpp",594 // Argument to 'sizeof...'595 R"cpp(596 template $Bracket[[<]]typename... $TemplateParameter_def[[Elements]]$Bracket[[>]]597 struct $Class_def[[TupleSize]] {598 static const int $StaticField_decl_readonly_static[[size]] =599sizeof...($TemplateParameter[[Elements]]);600 };601 )cpp",602 // More dependent types603 R"cpp(604 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]605 struct $Class_def[[Waldo]] {606 using $Typedef_decl[[Location1]] = typename $TemplateParameter[[T]]607 ::$Type_dependentName[[Resolver]]::$Type_dependentName[[Location]];608 using $Typedef_decl[[Location2]] = typename $TemplateParameter[[T]]609 ::template $Type_dependentName[[Resolver]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]610 ::$Type_dependentName[[Location]];611 using $Typedef_decl[[Location3]] = typename $TemplateParameter[[T]]612 ::$Type_dependentName[[Resolver]]613 ::template $Type_dependentName[[Location]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]];614 static const int $StaticField_decl_readonly_static[[Value]] = $TemplateParameter[[T]]615 ::$Type_dependentName[[Resolver]]::$Unknown_dependentName[[Value]];616 };617 )cpp",618 // Dependent name with heuristic target619 R"cpp(620 template $Bracket[[<]]typename$Bracket[[>]]621 struct $Class_def[[Foo]] {622 int $Field_decl[[Waldo]];623 void $Method_def[[bar]]() {624 $Class[[Foo]]().$Field[[Waldo]];625 }626 template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]]627 void $Method_def[[bar1]]() {628 $Class[[Foo]]$Bracket[[<]]$TemplateParameter[[U]]$Bracket[[>]]().$Field_dependentName[[Waldo]];629 }630 631 void $Method_decl[[Overload]]();632 void $Method_decl_readonly[[Overload]]() const;633 };634 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]635 void $Function_def[[baz]]($Class[[Foo]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] $Parameter_def[[o]]) {636 $Parameter[[o]].$Method_readonly_dependentName[[Overload]]();637 }638 )cpp",639 // Concepts640 R"cpp(641 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]642 concept $Concept_decl[[Fooable]] =643 requires($TemplateParameter[[T]] $Parameter_def[[F]]) {644 $Parameter[[F]].$Unknown_dependentName[[foo]]();645 };646 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]647 requires $Concept[[Fooable]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]648 void $Function_def[[bar]]($TemplateParameter[[T]] $Parameter_def[[F]]) {649 $Parameter[[F]].$Unknown_dependentName[[foo]]();650 }651 652 struct $Class_def[[F]] {653 void $Method_def[[foo]]() {};654 };655 $Concept[[Fooable]] $Class_deduced[[auto]] $Variable_def[[f]] = $Class[[F]]();656 657 void $Function_def[[Bar]]($Concept[[Fooable]] $TemplateParameter[[auto]] $Parameter_def[[x]]) {}658 659 template$Bracket[[<]]$Concept[[Fooable]] auto $TemplateParameter_def_readonly[[x]]$Bracket[[>]] void $Function_def[[Boo]]() {}660 bool $Variable_def[[b]] = $Concept[[Fooable]]$Bracket[[<]]int$Bracket[[>]];661 )cpp",662 // Dependent template name663 R"cpp(664 template $Bracket[[<]]template $Bracket[[<]]typename$Bracket[[>]] class$Bracket[[>]] struct $Class_def[[A]] {};665 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]666 using $Typedef_decl[[W]] = $Class[[A]]$Bracket[[<]]667 $TemplateParameter[[T]]::template $Class_dependentName[[Waldo]]668 $Bracket[[>]];669 )cpp",670 R"cpp(671 class $Class_def_abstract[[Abstract]] {672 public:673 virtual void $Method_decl_abstract_virtual[[pure]]() = 0;674 virtual void $Method_decl_virtual[[impl]]();675 };676 void $Function_def[[foo]]($Class_abstract[[Abstract]]* $Parameter_def[[A]]) {677 $Parameter[[A]]->$Method_abstract_virtual[[pure]]();678 $Parameter[[A]]->$Method_virtual[[impl]]();679 }680 )cpp",681 R"cpp(682 <:[deprecated]:> int $Variable_def_deprecated[[x]];683 )cpp",684 R"cpp(685 // ObjC: Classes and methods686 @class $Class_decl[[Forward]];687 688 @interface $Class_def[[Foo]]689 @end690 @interface $Class_def[[Bar]] : $Class[[Foo]]691 -(id) $Method_decl[[x]]:(int)$Parameter_def[[a]] $Method_decl[[y]]:(int)$Parameter_def[[b]];692 +(instancetype)$StaticMethod_decl_static[[sharedInstance]];693 +(void) $StaticMethod_decl_static[[explode]];694 @end695 @implementation $Class_def[[Bar]]696 -(id) $Method_def[[x]]:(int)$Parameter_def[[a]] $Method_def[[y]]:(int)$Parameter_def[[b]] {697 return self;698 }699 +(instancetype)$StaticMethod_def_static[[sharedInstance]] { return 0; }700 +(void) $StaticMethod_def_static[[explode]] {}701 @end702 703 void $Function_def[[m]]($Class[[Bar]] *$Parameter_def[[b]]) {704 [$Parameter[[b]] $Method[[x]]:1 $Method[[y]]:2];705 [$Class[[Bar]] $StaticMethod_static[[explode]]];706 }707 )cpp",708 R"cpp(709 // ObjC: Protocols710 @protocol $Interface_def[[Protocol]]711 @end712 @protocol $Interface_def[[Protocol2]] <$Interface[[Protocol]]>713 @end714 @interface $Class_def[[Klass]] <$Interface[[Protocol]]>715 @end716 id<$Interface[[Protocol]]> $Variable_def[[x]];717 )cpp",718 R"cpp(719 // ObjC: Categories720 @interface $Class_def[[Foo]]721 @end722 @interface $Class[[Foo]]($Namespace_def[[Bar]])723 @end724 @implementation $Class[[Foo]]($Namespace_def[[Bar]])725 @end726 )cpp",727 R"cpp(728 // ObjC: Properties and Ivars.729 @interface $Class_def[[Foo]] {730 int $Field_decl[[_someProperty]];731 }732 @property(nonatomic, assign) int $Field_decl[[someProperty]];733 @property(readonly, class) $Class[[Foo]] *$Field_decl_readonly_static[[sharedInstance]];734 @end735 @implementation $Class_def[[Foo]]736 @synthesize someProperty = _someProperty;737 - (int)$Method_def[[otherMethod]] {738 return 0;739 }740 - (int)$Method_def[[doSomething]] {741 $Class[[Foo]].$Field_static[[sharedInstance]].$Field[[someProperty]] $Operator[[=]] 1;742 self.$Field[[someProperty]] $Operator[[=]] self.$Field[[someProperty]] $Operator[[+]] self.$Field[[otherMethod]] $Operator[[+]] 1;743 self->$Field[[_someProperty]] $Operator[[=]] $Field[[_someProperty]] $Operator[[+]] 1;744 return 0;745 }746 @end747 )cpp",748 // Member imported from dependent base749 R"cpp(750 template $Bracket[[<]]typename$Bracket[[>]] struct $Class_def[[Base]] {751 int $Field_decl[[member]];752 };753 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]754 struct $Class_def[[Derived]] : $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] {755 using $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Field_dependentName[[member]];756 757 void $Method_def[[method]]() {758 (void)$Field_dependentName[[member]];759 }760 };761 )cpp",762 // Modifier for variables passed as non-const references763 R"cpp(764 struct $Class_def[[ClassWithOp]] {765 void operator$Operator_decl[[(]]$Operator_decl[[)]](int);766 void operator$Operator_decl[[(]]$Operator_decl[[)]](int, int &);767 void operator$Operator_decl[[(]]$Operator_decl[[)]](int, int, const int &);768 int &operator$Operator_decl[[[]]$Operator_decl[[]]](int &);769 int operator$Operator_decl[[[]]$Operator_decl[[]]](int) const;770 };771 struct $Class_def[[ClassWithStaticMember]] {772 static inline int $StaticField_def_static[[j]] = 0;773 };774 struct $Class_def[[ClassWithRefMembers]] {775 $Class_def_constrDestr[[ClassWithRefMembers]](int $Parameter_def[[i]])776 : $Field[[i1]]($Parameter[[i]]),777 $Field_readonly[[i2]]($Parameter[[i]]),778 $Field[[i3]]($Parameter_usedAsMutableReference[[i]]),779 $Field_readonly[[i4]]($Class[[ClassWithStaticMember]]::$StaticField_static[[j]]),780 $Field[[i5]]($Class[[ClassWithStaticMember]]::$StaticField_static_usedAsMutableReference[[j]])781 {}782 int $Field_decl[[i1]];783 const int &$Field_decl_readonly[[i2]];784 int &$Field_decl[[i3]];785 const int &$Field_decl_readonly[[i4]];786 int &$Field_decl[[i5]];787 };788 void $Function_def[[fun]](int, const int,789 int*, const int*,790 int&, const int&,791 int*&, const int*&, const int* const &,792 int**, int**&, int** const &,793 int = 123) {794 int $LocalVariable_def[[val]];795 int* $LocalVariable_def[[ptr]];796 const int* $LocalVariable_def_readonly[[constPtr]];797 int** $LocalVariable_def[[array]];798 $Function[[fun]]($LocalVariable[[val]], $LocalVariable[[val]],799 $LocalVariable_usedAsMutablePointer[[ptr]], $LocalVariable_readonly[[constPtr]],800 $LocalVariable_usedAsMutableReference[[val]], $LocalVariable[[val]],801 802 $LocalVariable_usedAsMutableReference[[ptr]],803 $LocalVariable_readonly_usedAsMutableReference[[constPtr]],804 $LocalVariable_readonly[[constPtr]],805 806 $LocalVariable_usedAsMutablePointer[[array]], $LocalVariable_usedAsMutableReference[[array]],807 $LocalVariable[[array]]808 );809 [](int){}$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]];810 [](int&){}$Operator_userDefined[[(]]$LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[)]];811 [](const int&){}$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]];812 $Class[[ClassWithOp]] $LocalVariable_def[[c]];813 const $Class[[ClassWithOp]] $LocalVariable_def_readonly[[c2]];814 $LocalVariable[[c]]$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]];815 $LocalVariable[[c]]$Operator_userDefined[[(]]0, $LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[)]];816 $LocalVariable[[c]]$Operator_userDefined[[(]]0, 0, $LocalVariable[[val]]$Operator_userDefined[[)]];817 $LocalVariable[[c]]$Operator_userDefined[[[]]$LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[]]];818 $LocalVariable_readonly[[c2]]$Operator_userDefined[[[]]$LocalVariable[[val]]$Operator_userDefined[[]]];819 }820 struct $Class_def[[S]] {821 $Class_def_constrDestr[[S]](int&) {822 $Class[[S]] $LocalVariable_def[[s1]]($Field_usedAsMutableReference[[field]]);823 $Class[[S]] $LocalVariable_def[[s2]]($LocalVariable[[s1]].$Field_usedAsMutableReference[[field]]);824 825 $Class[[S]] $LocalVariable_def[[s3]]($StaticField_static_usedAsMutableReference[[staticField]]);826 $Class[[S]] $LocalVariable_def[[s4]]($Class[[S]]::$StaticField_static_usedAsMutableReference[[staticField]]);827 }828 int $Field_decl[[field]];829 static int $StaticField_decl_static[[staticField]];830 };831 template $Bracket[[<]]typename $TemplateParameter_def[[X]]$Bracket[[>]]832 void $Function_def[[foo]]($TemplateParameter[[X]]& $Parameter_def[[x]]) {833 // We do not support dependent types, so this one should *not* get the modifier.834 $Function[[foo]]($Parameter[[x]]);835 }836 )cpp",837 // init-captures838 R"cpp(839 void $Function_def[[foo]]() {840 int $LocalVariable_def[[a]], $LocalVariable_def[[b]];841 [ $LocalVariable_def[[c]] = $LocalVariable[[a]],842 $LocalVariable_def[[d]]($LocalVariable[[b]]) ]() {}$Operator_userDefined[[(]]$Operator_userDefined[[)]];843 }844 )cpp",845 // Enum base specifier846 R"cpp(847 using $Primitive_decl[[MyTypedef]] = int;848 enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {};849 )cpp",850 // Enum base specifier851 R"cpp(852 typedef int $Primitive_decl[[MyTypedef]];853 enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {};854 )cpp",855 // Using enum856 R"cpp(857 enum class $Enum_decl[[Color]] { $EnumConstant_decl_readonly[[Black]] };858 namespace $Namespace_decl[[ns]] {859 using enum $Enum[[Color]];860 $Enum[[Color]] $Variable_def[[ModelT]] = $EnumConstant[[Black]];861 }862 )cpp",863 // Issue 1096864 R"cpp(865 void $Function_decl[[Foo]]();866 // Use <: :> digraphs for deprecated attribute to avoid conflict with annotation syntax867 <:<:deprecated:>:> void $Function_decl_deprecated[[Foo]](int* $Parameter_def[[x]]);868 void $Function_decl[[Foo]](int $Parameter_def[[x]]);869 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]870 void $Function_def[[Bar]]($TemplateParameter[[T]] $Parameter_def[[x]]) {871 $Function_deprecated[[Foo]]($Parameter[[x]]);872 $Function_deprecated[[Foo]]($Parameter[[x]]);873 $Function_deprecated[[Foo]]($Parameter[[x]]);874 }875 )cpp",876 // Predefined identifiers877 R"cpp(878 void $Function_def[[Foo]]() {879 const char *$LocalVariable_def_readonly[[s]] = $LocalVariable_readonly_static[[__func__]];880 }881 )cpp",882 // override and final883 R"cpp(884 class $Class_def_abstract[[Base]] { virtual void $Method_decl_abstract_virtual[[m]]() = 0; };885 class $Class_def[[override]] : public $Class_abstract[[Base]] { void $Method_decl_virtual[[m]]() $Modifier[[override]]; };886 class $Class_def[[final]] : public $Class[[override]] { void $Method_decl_virtual[[m]]() $Modifier[[override]] $Modifier[[final]]; };887 )cpp",888 // Issue 1222: readonly modifier for generic parameter889 R"cpp(890 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]891 auto $Function_def[[foo]](const $TemplateParameter[[T]] $Parameter_def_readonly[[template_type]],892 const $TemplateParameter[[auto]] $Parameter_def_readonly[[auto_type]],893 const int $Parameter_def_readonly[[explicit_type]]) {894 return $Parameter_readonly[[template_type]]895 $Operator_userDefined[[+]] $Parameter_readonly[[auto_type]]896 $Operator_userDefined[[+]] $Parameter_readonly[[explicit_type]];897 }898 )cpp",899 // Explicit template specialization900 R"cpp(901 struct $Class_def[[Base]]{};902 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]903 struct $Class_def[[S]] : public $Class[[Base]] {};904 template $Bracket[[<]]$Bracket[[>]]905 struct $Class_def[[S]]$Bracket[[<]]void$Bracket[[>]] : public $Class[[Base]] {};906 907 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]908 $TemplateParameter[[T]] $Variable_def[[x]] = {};909 template $Bracket[[<]]$Bracket[[>]]910 int $Variable_def[[x]]$Bracket[[<]]int$Bracket[[>]] = (int)sizeof($Class[[Base]]);911 )cpp",912 // operator calls in template913 R"cpp(914 template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] class $Class_def[[C]] {915 bool $Method_def[[compare]]($TemplateParameter[[T]] $Parameter_def[[t1]], $TemplateParameter[[T]] $Parameter_def[[t2]]) { return $Parameter[[t1]] $Operator_userDefined[[==]] $Parameter[[t2]]; }916 $TemplateParameter[[T]] $Method_def[[deref]]($TemplateParameter[[T]] *$Parameter_def[[t]]) { return $Operator_userDefined[[*]]$Parameter[[t]]; }917 };918 )cpp",919 // new and delete920 R"cpp(921 struct $Class_def[[S]] { int *$Field_decl[[a]]; };922 void $Function_def[[f]]() {923 $Class[[S]] *$LocalVariable_def[[s]] = $Operator[[new]] $Class[[S]];924 $LocalVariable[[s]]->$Field[[a]] $Operator[[=]] $Operator[[new]] int[10];925 $Operator[[delete]][] $LocalVariable[[s]]->$Field[[a]];926 $Operator[[delete]] $LocalVariable[[s]];927 }928 )cpp",929 // explicit operator invocation930 R"cpp(931 struct $Class_def[[S]] {932 $Class[[S]] operator$Operator_decl[[+]](const $Class[[S]] &$Parameter_def_readonly[[other]]);933 };934 void $Function_def[[f]]() {935 $Class[[S]] $LocalVariable_def[[s]];936 $Class[[S]] $LocalVariable_def[[s2]] = $LocalVariable[[s]].operator$Operator_userDefined[[+]]($LocalVariable[[s]]);937 }938 )cpp",939 R"cpp(940 // Brackets support: C++ casts941 void $Function_def[[f]]() {942 struct $Class_def[[B]] { virtual ~$Class_decl_constrDestr[[B]](); };943 struct $Class_def[[D]] : public $Class[[B]] {};944 $Class[[B]] $LocalVariable_def[[b]];945 int $LocalVariable_def[[i]] = static_cast$Bracket[[<]]int$Bracket[[>]](3.5);946 void *$LocalVariable_def[[p]] = reinterpret_cast$Bracket[[<]]void *$Bracket[[>]](0);947 $Class[[D]] &$LocalVariable_def[[d]] = dynamic_cast$Bracket[[<]]$Class[[D]] &$Bracket[[>]]($LocalVariable[[b]]);948 }949 )cpp",950 // Brackets support: Nested template instantiations.951 R"cpp(952 template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] struct $Class_def[[S]] {};953 void $Function_def[[f]]() {954 $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s1]];955 $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\956$Bracket[[>]] $LocalVariable_def[[s2]];957 $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]$Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s3]];958 $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\959$Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s4]];960 $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\961 $Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s5]];962 $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\963$Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s6]];964 $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]$Bracket[[>]]\965 $Bracket[[>]] $LocalVariable_def[[s7]];966 }967 )cpp",968 // Brackets support: One of the brackets is a macro.969 R"cpp(970 #define $Macro_decl[[LESS]] <971 template $Macro[[LESS]] typename $TemplateParameter_def[[T]] > class $Class_def[[A]] {};972 )cpp",973 // Brackets support: Specializations974 R"cpp(975 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] class $Class_def[[S]] {976 public:977 template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]] class $Class_decl[[Nested]];978 };979 template $Bracket[[<]]$Bracket[[>]] class $Class_def[[S]]$Bracket[[<]]int$Bracket[[>]] {};980 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]981 class $Class_def[[S]]$Bracket[[<]]$TemplateParameter[[T]]*$Bracket[[>]] {};982 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]983 template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]]984 class $Class[[S]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Class_def[[Nested]] {};985 template $Bracket[[<]]$Bracket[[>]]986 template $Bracket[[<]]$Bracket[[>]]987 class $Class[[S]]$Bracket[[<]]float$Bracket[[>]]::$Class_def[[Nested]]$Bracket[[<]]float$Bracket[[>]] {};988 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] void $Function_decl[[foo]]();989 void $Function_def[[bar]]() {990 $Function[[foo]]$Bracket[[<]]int$Bracket[[>]]();991 }992 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] constexpr int $Variable_def_readonly[[V]] = 42;993 constexpr int $Variable_def_readonly[[Y]] = $Variable_readonly[[V]]$Bracket[[<]]char$Bracket[[>]];994 template $Bracket[[<]]$Bracket[[>]]995 constexpr int $Variable_def_readonly[[V]]$Bracket[[<]]int$Bracket[[>]] = 5;996 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]997 constexpr int $Variable_def_readonly[[V]]$Bracket[[<]]$TemplateParameter[[T]]*$Bracket[[>]] = 6;998 template $Bracket[[<]]typename$Bracket[[>]]999 class $Class_def[[A]] {1000 enum class $Enum_decl[[E]];1001 };1002 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]1003 enum class $Class[[A]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Enum_decl[[E]] {$EnumConstant_decl_readonly[[X]], $EnumConstant_decl_readonly[[Y]], $EnumConstant_decl_readonly[[Z]]};1004 template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]]1005 class $Class_def[[B]] {1006 template $Bracket[[<]]class $TemplateParameter_def[[U]]$Bracket[[>]] void $Method_def[[foo]]($TemplateParameter[[U]]) { }1007 template$Bracket[[<]]$Bracket[[>]] void $Method_def[[foo]]$Bracket[[<]]int$Bracket[[>]](int) { }1008 friend void $Function_decl[[foo]]$Bracket[[<]]$Bracket[[>]]($TemplateParameter[[T]]);1009 };1010 )cpp",1011 // Brackets support: Function calls1012 R"cpp(1013 template $Bracket[[<]]typename$Bracket[[>]] void $Function_decl[[free]]();1014 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]1015 struct $Class_def[[A]] {1016 template $Bracket[[<]]typename$Bracket[[>]] void $Method_decl[[mem]]();1017 };1018 void $Function_def[[foo]]() {1019 $Class[[A]]$Bracket[[<]]int$Bracket[[>]] $LocalVariable_def[[a]];1020 $LocalVariable[[a]].$Method[[mem]]$Bracket[[<]]int$Bracket[[>]]();1021 }1022 template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]1023 void $Function_def[[bar]]() {1024 $Function[[free]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]();1025 $Class[[A]]$Bracket[[<]]int$Bracket[[>]] $LocalVariable_def[[a]];1026 $LocalVariable[[a]].$Method[[mem]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]();1027 $Class[[A]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] $LocalVariable_def[[b]];1028 $LocalVariable[[b]].template $Method_dependentName[[mem]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]();1029 }1030 )cpp",1031 // Brackets support: Concepts1032 R"cpp(1033 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]1034 concept $Concept_decl[[C]] = true;1035 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] requires $Concept[[C]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]1036 class $Class_def[[Z]] {};1037 template $Bracket[[<]]typename, typename$Bracket[[>]]1038 concept $Concept_decl[[C2]] = true;1039 template $Bracket[[<]]$Concept[[C2]]$Bracket[[<]]int$Bracket[[>]] $TemplateParameter_def[[A]]$Bracket[[>]]1040 class $Class_def[[B]] {};1041 )cpp",1042 // Labels1043 R"cpp(1044 bool $Function_def[[funcWithGoto]](bool $Parameter_def[[b]]) {1045 if ($Parameter[[b]])1046 goto $Label[[return_true]];1047 return false;1048 $Label_decl[[return_true]]:1049 return true;1050 }1051 )cpp",1052 // no crash1053 R"cpp(1054 struct $Class_def[[Foo]] {1055 void $Method_decl[[foo]]();1056 };1057 1058 void $Function_def[[s]]($Class[[Foo]] $Parameter_def[[f]]) {1059 auto $LocalVariable_def[[k]] = $Operator[[&]]$Class[[Foo]]::$Method[[foo]];1060 ($Parameter[[f]]$Operator[[.*]]$LocalVariable[[k]])(); // no crash on VisitCXXMemberCallExpr1061 }1062 )cpp",1063 R"cpp(1064 template$Bracket[[<]]typename$Bracket[[>]]1065 class $Class_def[[Foo]] {};1066 1067 template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]1068 void $Function_def[[k]]() {1069 auto $LocalVariable_def[[s]] = $Operator[[new]] $Class[[Foo]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]();1070 $Operator[[delete]] $LocalVariable[[s]];1071 }1072 )cpp",1073 // Recursive UsingValueDecl1074 R"cpp(1075 template $Bracket[[<]]int$Bracket[[>]] class $Class_def[[X]] {1076 template $Bracket[[<]]int$Bracket[[>]] class $Class_def[[Y]] {1077 using $Class[[Y]]$Bracket[[<]]0$Bracket[[>]]::$Unknown_dependentName[[xxx]];1078 };1079 };1080 )cpp",1081 // Heuristically resolved IndirectFieldDecl1082 R"cpp(1083 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]1084 struct $Class_def[[Base]] {1085 struct {1086 int $Field_decl[[waldo]];1087 };1088 };1089 template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]1090 struct $Class_def[[Derived]] : $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] {1091 using $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Field_dependentName[[waldo]];1092 void $Method_def[[foo]]() {1093 $Field_dependentName[[waldo]];1094 }1095 };1096 )cpp",1097 // Pointer-to-member with nested-name-specifiers1098 R"cpp(1099 struct $Class_def[[Outer]] {1100 struct $Class_def[[Inner]] {};1101 };1102 using $Typedef_decl[[Alias]] = void ($Class[[Outer]]::$Class[[Inner]]:: *)();1103 )cpp"};1104 for (const auto &TestCase : TestCases)1105 // Mask off scope modifiers to keep the tests manageable.1106 // They're tested separately.1107 checkHighlightings(TestCase, {}, ~ScopeModifierMask);1108 1109 checkHighlightings(R"cpp(1110 class $Class_def[[A]] {1111 #include "imp.h"1112 };1113 )cpp",1114 {{"imp.h", R"cpp(1115 int someMethod();1116 void otherMethod();1117 )cpp"}},1118 ~ScopeModifierMask);1119 1120 // A separate test for macros in headers.1121 checkHighlightings(R"cpp(1122 #include "imp.h"1123 $Macro[[DEFINE_Y]]1124 $Macro[[DXYZ_Y]](A);1125 )cpp",1126 {{"imp.h", R"cpp(1127 #define DXYZ(X) class X {};1128 #define DXYZ_Y(Y) DXYZ(x##Y)1129 #define DEFINE(X) int X;1130 #define DEFINE_Y DEFINE(Y)1131 )cpp"}},1132 ~ScopeModifierMask);1133 1134 checkHighlightings(R"cpp(1135 #include "SYSObject.h"1136 @interface $Class_defaultLibrary[[SYSObject]] ($Namespace_def[[UserCategory]])1137 @property(nonatomic, readonly) int $Field_decl_readonly[[user_property]];1138 @end1139 int $Function_def[[somethingUsingSystemSymbols]]() {1140 $Class_defaultLibrary[[SYSObject]] *$LocalVariable_def[[obj]] = [$Class_defaultLibrary[[SYSObject]] $StaticMethod_static_defaultLibrary[[new]]];1141 return $LocalVariable[[obj]].$Field_defaultLibrary[[value]] $Operator[[+]] $LocalVariable[[obj]].$Field_readonly[[user_property]];1142 }1143 )cpp",1144 {{"SystemSDK/SYSObject.h", R"cpp(1145 @interface SYSObject1146 @property(nonatomic, assign) int value;1147 + (instancetype)new;1148 @end1149 )cpp"}},1150 ~ScopeModifierMask, {"-isystemSystemSDK/"});1151}1152 1153TEST(SemanticHighlighting, ScopeModifiers) {1154 const char *TestCases[] = {1155 R"cpp(1156 static int $Variable_fileScope[[x]];1157 namespace $Namespace_globalScope[[ns]] {1158 class $Class_globalScope[[x]];1159 }1160 namespace {1161 void $Function_fileScope[[foo]]();1162 }1163 )cpp",1164 R"cpp(1165 void $Function_globalScope[[foo]](int $Parameter_functionScope[[y]]) {1166 int $LocalVariable_functionScope[[z]];1167 }1168 )cpp",1169 R"cpp(1170 // Lambdas are considered functions, not classes.1171 auto $Variable_fileScope[[x]] = [$LocalVariable_functionScope[[m]](42)] {1172 return $LocalVariable_functionScope[[m]];1173 };1174 )cpp",1175 R"cpp(1176 // Classes in functions are classes.1177 void $Function_globalScope[[foo]]() {1178 class $Class_functionScope[[X]] {1179 int $Field_classScope[[x]];1180 };1181 };1182 )cpp",1183 R"cpp(1184 template $Bracket[[<]]int $TemplateParameter_classScope[[T]]$Bracket[[>]]1185 class $Class_globalScope[[X]] {1186 };1187 )cpp",1188 R"cpp(1189 // No useful scope for template parameters of variable templates.1190 template $Bracket[[<]]typename $TemplateParameter[[A]]$Bracket[[>]]1191 unsigned $Variable_globalScope[[X]] =1192 $TemplateParameter[[A]]::$Unknown_classScope[[x]];1193 )cpp",1194 R"cpp(1195 #define $Macro_globalScope[[X]] 11196 int $Variable_globalScope[[Y]] = $Macro_globalScope[[X]];1197 )cpp",1198 };1199 1200 for (const char *Test : TestCases)1201 checkHighlightings(Test, {}, ScopeModifierMask);1202}1203 1204// Ranges are highlighted as variables, unless highlighted as $Function etc.1205std::vector<HighlightingToken> tokens(llvm::StringRef MarkedText) {1206 Annotations A(MarkedText);1207 std::vector<HighlightingToken> Results;1208 for (const Range& R : A.ranges())1209 Results.push_back({HighlightingKind::Variable, 0, R});1210 for (unsigned I = 0; I < static_cast<unsigned>(HighlightingKind::LastKind); ++I) {1211 HighlightingKind Kind = static_cast<HighlightingKind>(I);1212 for (const Range& R : A.ranges(llvm::to_string(Kind)))1213 Results.push_back({Kind, 0, R});1214 }1215 llvm::sort(Results);1216 return Results;1217}1218 1219TEST(SemanticHighlighting, toSemanticTokens) {1220 auto Tokens = tokens(R"(1221 [[blah]]1222 1223 $Function[[big]] [[bang]]1224 )");1225 Tokens.front().Modifiers |= unsigned(HighlightingModifier::Declaration);1226 Tokens.front().Modifiers |= unsigned(HighlightingModifier::Readonly);1227 auto Results = toSemanticTokens(Tokens, /*Code=*/"");1228 1229 ASSERT_THAT(Results, SizeIs(3));1230 EXPECT_EQ(Results[0].tokenType, unsigned(HighlightingKind::Variable));1231 EXPECT_EQ(Results[0].tokenModifiers,1232 unsigned(HighlightingModifier::Declaration) |1233 unsigned(HighlightingModifier::Readonly));1234 EXPECT_EQ(Results[0].deltaLine, 1u);1235 EXPECT_EQ(Results[0].deltaStart, 1u);1236 EXPECT_EQ(Results[0].length, 4u);1237 1238 EXPECT_EQ(Results[1].tokenType, unsigned(HighlightingKind::Function));1239 EXPECT_EQ(Results[1].tokenModifiers, 0u);1240 EXPECT_EQ(Results[1].deltaLine, 2u);1241 EXPECT_EQ(Results[1].deltaStart, 4u);1242 EXPECT_EQ(Results[1].length, 3u);1243 1244 EXPECT_EQ(Results[2].tokenType, unsigned(HighlightingKind::Variable));1245 EXPECT_EQ(Results[1].tokenModifiers, 0u);1246 EXPECT_EQ(Results[2].deltaLine, 0u);1247 EXPECT_EQ(Results[2].deltaStart, 4u);1248 EXPECT_EQ(Results[2].length, 4u);1249}1250 1251TEST(SemanticHighlighting, diffSemanticTokens) {1252 auto Before = toSemanticTokens(tokens(R"(1253 [[foo]] [[bar]] [[baz]]1254 [[one]] [[two]] [[three]]1255 )"),1256 /*Code=*/"");1257 EXPECT_THAT(diffTokens(Before, Before), IsEmpty());1258 1259 auto After = toSemanticTokens(tokens(R"(1260 [[foo]] [[hello]] [[world]] [[baz]]1261 [[one]] [[two]] [[three]]1262 )"),1263 /*Code=*/"");1264 1265 // Replace [bar, baz] with [hello, world, baz]1266 auto Diff = diffTokens(Before, After);1267 ASSERT_THAT(Diff, SizeIs(1));1268 EXPECT_EQ(1u, Diff.front().startToken);1269 EXPECT_EQ(2u, Diff.front().deleteTokens);1270 ASSERT_THAT(Diff.front().tokens, SizeIs(3));1271 // hello1272 EXPECT_EQ(0u, Diff.front().tokens[0].deltaLine);1273 EXPECT_EQ(4u, Diff.front().tokens[0].deltaStart);1274 EXPECT_EQ(5u, Diff.front().tokens[0].length);1275 // world1276 EXPECT_EQ(0u, Diff.front().tokens[1].deltaLine);1277 EXPECT_EQ(6u, Diff.front().tokens[1].deltaStart);1278 EXPECT_EQ(5u, Diff.front().tokens[1].length);1279 // baz1280 EXPECT_EQ(0u, Diff.front().tokens[2].deltaLine);1281 EXPECT_EQ(6u, Diff.front().tokens[2].deltaStart);1282 EXPECT_EQ(3u, Diff.front().tokens[2].length);1283}1284 1285TEST(SemanticHighlighting, MultilineTokens) {1286 llvm::StringRef AnnotatedCode = R"cpp(1287 [[fo1288o1289o]] [[bar]])cpp";1290 auto Toks = toSemanticTokens(tokens(AnnotatedCode),1291 Annotations(AnnotatedCode).code());1292 ASSERT_THAT(Toks, SizeIs(4));1293 // foo1294 EXPECT_EQ(Toks[0].deltaLine, 1u);1295 EXPECT_EQ(Toks[0].deltaStart, 2u);1296 EXPECT_EQ(Toks[0].length, 2u);1297 EXPECT_EQ(Toks[1].deltaLine, 1u);1298 EXPECT_EQ(Toks[1].deltaStart, 0u);1299 EXPECT_EQ(Toks[1].length, 1u);1300 EXPECT_EQ(Toks[2].deltaLine, 1u);1301 EXPECT_EQ(Toks[2].deltaStart, 0u);1302 EXPECT_EQ(Toks[2].length, 1u);1303 1304 // bar1305 EXPECT_EQ(Toks[3].deltaLine, 0u);1306 EXPECT_EQ(Toks[3].deltaStart, 2u);1307 EXPECT_EQ(Toks[3].length, 3u);1308}1309 1310TEST(SemanticHighlighting, WithHighlightingFilter) {1311 llvm::StringRef AnnotatedCode = R"cpp(1312int *$Variable[[x]] = new int;1313)cpp";1314 Config Cfg;1315 Cfg.SemanticTokens.DisabledKinds = {"Operator"};1316 Cfg.SemanticTokens.DisabledModifiers = {"Declaration", "Definition"};1317 WithContextValue WithCfg(Config::Key, std::move(Cfg));1318 checkHighlightings(AnnotatedCode, {}, ~ScopeModifierMask);1319}1320} // namespace1321} // namespace clangd1322} // namespace clang1323