diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -490,6 +490,15 @@ return Types; } +static std::vector semanticTokenModifiers() { + std::vector Modifiers; + for (unsigned I = 0; + I <= static_cast(HighlightingModifier::LastModifier); ++I) + Modifiers.push_back( + toSemanticTokenModifier(static_cast(I))); + return Modifiers; +} + void ClangdLSPServer::onInitialize(const InitializeParams &Params, Callback Reply) { // Determine character encoding first as it affects constructed ClangdServer. @@ -623,8 +632,9 @@ {"full", llvm::json::Object{{"delta", true}}}, {"range", false}, {"legend", - llvm::json::Object{{"tokenTypes", semanticTokenTypes()}, - {"tokenModifiers", llvm::json::Array()}}}, + llvm::json::Object{ + {"tokenTypes", semanticTokenTypes()}, + {"tokenModifiers", semanticTokenModifiers()}}}, }}, {"signatureHelpProvider", llvm::json::Object{ diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -64,12 +64,34 @@ LastKind = InactiveCode }; + llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K); +enum class HighlightingModifier { + Declaration, + // FIXME: Definition (needs findExplicitReferences support) + Deprecated, + Deduced, + Readonly, + Static, + Abstract, + + LastModifier = Abstract +}; +static_assert(static_cast(HighlightingModifier::LastModifier) < 32, + "Increase width of modifiers bitfield!"); +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K); + // Contains all information needed for the highlighting a token. struct HighlightingToken { HighlightingKind Kind; + uint32_t Modifiers = 0; Range R; + + HighlightingToken &addModifier(HighlightingModifier M) { + Modifiers |= 1 << static_cast(M); + return *this; + } }; bool operator==(const HighlightingToken &L, const HighlightingToken &R); @@ -90,6 +112,7 @@ std::vector toSemanticTokens(llvm::ArrayRef); llvm::StringRef toSemanticTokenType(HighlightingKind Kind); +llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier); std::vector diffTokens(llvm::ArrayRef Before, llvm::ArrayRef After); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -15,6 +15,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" @@ -118,17 +120,79 @@ return llvm::None; } -llvm::Optional kindForReference(const ReferenceLoc &R) { - llvm::Optional Result; - for (const NamedDecl *Decl : R.Targets) { - if (!canHighlightName(Decl->getDeclName())) - return llvm::None; - auto Kind = kindForDecl(Decl); - if (!Kind || (Result && Kind != Result)) - return llvm::None; - Result = Kind; +// Whether T is const in a loose sense - is a variable with this type readonly? +bool isConst(QualType T) { + if (T.isNull() || T->isDependentType()) + return false; + T = T.getNonReferenceType(); + if (T.isConstQualified()) + return true; + if (const auto *AT = T->getAsArrayTypeUnsafe()) + return isConst(AT->getElementType()); + return isConst(T->getPointeeType()); +} + +// Whether D is const in a loose sense (should it be highlighted as such?) +bool isConst(const Decl *D) { + if (llvm::isa(D) || llvm::isa(D)) + return true; + if (llvm::isa(D) || llvm::isa(D) || + llvm::isa(D) || llvm::isa(D)) { + if (isConst(llvm::cast(D)->getType())) + return true; } - return Result; + if (const auto *OCPD = llvm::dyn_cast(D)) { + if (OCPD->isReadOnly()) + return true; + } + if (const auto *MPD = llvm::dyn_cast(D)) { + if (!MPD->hasSetter()) + return true; + } + if (const auto *CMD = llvm::dyn_cast(D)) { + if (CMD->isConst()) + return true; + } + return false; +} + +// "Static" means many things in C++, only some get the "static" modifier. +// +// Meanings that do: +// - Members associated with the class rather than the instance. +// This is what 'static' most often means across languages. +// - static local variables +// These are similarly "detached from their context" by the static keyword. +// In practice, these are rarely used inside classes, reducing confusion. +// +// Meanings that don't: +// - Namespace-scoped variables, which have static storage class. +// This is implicit, so the keyword "static" isn't so strongly associated. +// If we want a modifier for these, "global scope" is probably the concept. +// - Namespace-scoped variables/functions explicitly marked "static". +// There the keyword changes *linkage* , which is a totally different concept. +// If we want to model this, "file scope" would be a nice modifier. +// +// This is confusing, and maybe we should use another name, but because "static" +// is a standard LSP modifier, having one with that name has advantages. +bool isStatic(const Decl *D) { + if (const auto *CMD = llvm::dyn_cast(D)) + return CMD->isStatic(); + if (const VarDecl *VD = llvm::dyn_cast(D)) + return VD->isStaticDataMember() || VD->isStaticLocal(); + if (const auto *FD = llvm::dyn_cast(D)) + return FD->isCXXClassMember() && !FD->isCXXInstanceMember(); + if (const auto *OMD = llvm::dyn_cast(D)) + return OMD->isClassMethod(); + return false; +} + +bool isAbstract(const Decl *D) { + if (const auto *CMD = llvm::dyn_cast(D)) + return CMD->isPure(); + if (const auto *CRD = llvm::dyn_cast(D)) + return CRD->isAbstract(); + return false; } // For a macro usage `DUMP(foo)`, we want: @@ -182,18 +246,24 @@ : TB(AST.getTokens()), SourceMgr(AST.getSourceManager()), LangOpts(AST.getLangOpts()) {} - void addToken(HighlightingToken T) { Tokens.push_back(T); } - - void addToken(SourceLocation Loc, HighlightingKind Kind) { + HighlightingToken &addToken(SourceLocation Loc, HighlightingKind Kind) { Loc = getHighlightableSpellingToken(Loc, SourceMgr); if (Loc.isInvalid()) - return; + return Dummy; const auto *Tok = TB.spelledTokenAt(Loc); assert(Tok); + return addToken( + halfOpenToRange(SourceMgr, + Tok->range(SourceMgr).toCharRange(SourceMgr)), + Kind); + } - auto Range = halfOpenToRange(SourceMgr, - Tok->range(SourceMgr).toCharRange(SourceMgr)); - Tokens.push_back(HighlightingToken{Kind, std::move(Range)}); + HighlightingToken &addToken(Range R, HighlightingKind Kind) { + HighlightingToken HT; + HT.R = std::move(R); + HT.Kind = Kind; + Tokens.push_back(std::move(HT)); + return Tokens.back(); } std::vector collect(ParsedAST &AST) && { @@ -248,10 +318,13 @@ MainCode.drop_front(*StartOfLine).take_until([](char C) { return C == '\n'; }); - WithInactiveLines.push_back( - {HighlightingKind::InactiveCode, - {Position{Line, 0}, - Position{Line, static_cast(lspLength(LineText))}}}); + HighlightingToken HT; + WithInactiveLines.emplace_back(); + WithInactiveLines.back().Kind = HighlightingKind::InactiveCode; + WithInactiveLines.back().R.start.line = Line; + WithInactiveLines.back().R.end.line = Line; + WithInactiveLines.back().R.end.character = + static_cast(lspLength(LineText)); } else { elog("Failed to convert position to offset: {0}", StartOfLine.takeError()); @@ -277,6 +350,7 @@ const SourceManager &SourceMgr; const LangOptions &LangOpts; std::vector Tokens; + HighlightingToken Dummy; // returned from addToken(InvalidLoc) }; /// Produces highlightings, which are not captured by findExplicitReferences, @@ -288,7 +362,8 @@ bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) { if (auto K = kindForType(L.getTypePtr())) - H.addToken(L.getBeginLoc(), *K); + H.addToken(L.getBeginLoc(), *K) + .addModifier(HighlightingModifier::Deduced); return true; } @@ -297,7 +372,8 @@ if (!AT) return true; if (auto K = kindForType(AT->getDeducedType().getTypePtrOrNull())) - H.addToken(D->getTypeSpecStartLoc(), *K); + H.addToken(D->getTypeSpecStartLoc(), *K) + .addModifier(HighlightingModifier::Deduced); return true; } @@ -391,16 +467,45 @@ CollectExtraHighlightings(Builder).TraverseAST(C); // Highlight all decls and references coming from the AST. findExplicitReferences(C, [&](ReferenceLoc R) { - if (auto Kind = kindForReference(R)) - Builder.addToken(R.NameLoc, *Kind); + llvm::Optional Result; + for (const NamedDecl *Decl : R.Targets) { + if (!canHighlightName(Decl->getDeclName())) + continue; + auto Kind = kindForDecl(Decl); + if (!Kind || (Result && Kind != Result)) + continue; + Result = Kind; + + auto &Tok = Builder.addToken(R.NameLoc, *Kind); + + // The attribute tests don't want to look at the template. + if (auto *TD = dyn_cast(Decl)) { + if (auto *Templated = TD->getTemplatedDecl()) + Decl = Templated; + } + if (isConst(Decl)) + Tok.addModifier(HighlightingModifier::Readonly); + if (isStatic(Decl)) + Tok.addModifier(HighlightingModifier::Static); + if (isAbstract(Decl)) + Tok.addModifier(HighlightingModifier::Abstract); + if (Decl->isDeprecated()) + Tok.addModifier(HighlightingModifier::Deprecated); + if (R.IsDecl) + Tok.addModifier(HighlightingModifier::Declaration); + } }); // Add highlightings for macro references. - for (const auto &SIDToRefs : AST.getMacros().MacroRefs) { + auto AddMacro = [&](const MacroOccurrence &M) { + auto &T = Builder.addToken(M.Rng, HighlightingKind::Macro); + if (M.IsDefinition) + T.addModifier(HighlightingModifier::Declaration); + }; + for (const auto &SIDToRefs : AST.getMacros().MacroRefs) for (const auto &M : SIDToRefs.second) - Builder.addToken({HighlightingKind::Macro, M.Rng}); - } + AddMacro(M); for (const auto &M : AST.getMacros().UnknownMacros) - Builder.addToken({HighlightingKind::Macro, M.Rng}); + AddMacro(M); return std::move(Builder).collect(AST); } @@ -450,6 +555,14 @@ } llvm_unreachable("invalid HighlightingKind"); } +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K) { + switch (K) { + case HighlightingModifier::Declaration: + return OS << "decl"; // abbrevation for common case + default: + return OS << toSemanticTokenModifier(K); + } +} std::vector diffHighlightings(ArrayRef New, @@ -510,10 +623,12 @@ } bool operator==(const HighlightingToken &L, const HighlightingToken &R) { - return std::tie(L.R, L.Kind) == std::tie(R.R, R.Kind); + return std::tie(L.R, L.Kind, L.Modifiers) == + std::tie(R.R, R.Kind, R.Modifiers); } bool operator<(const HighlightingToken &L, const HighlightingToken &R) { - return std::tie(L.R, L.Kind) < std::tie(R.R, R.Kind); + return std::tie(L.R, L.Kind, R.Modifiers) < + std::tie(R.R, R.Kind, R.Modifiers); } bool operator==(const LineHighlightings &L, const LineHighlightings &R) { return std::tie(L.Line, L.Tokens) == std::tie(R.Line, R.Tokens); @@ -544,6 +659,7 @@ assert(Tok.R.end.line == Tok.R.start.line); Out.length = Tok.R.end.character - Tok.R.start.character; Out.tokenType = static_cast(Tok.Kind); + Out.tokenModifiers = Tok.Modifiers; Last = &Tok; } @@ -575,7 +691,6 @@ case HighlightingKind::Typedef: return "type"; case HighlightingKind::DependentType: - return "dependent"; // nonstandard case HighlightingKind::DependentName: return "dependent"; // nonstandard case HighlightingKind::Namespace: @@ -594,6 +709,23 @@ llvm_unreachable("unhandled HighlightingKind"); } +llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier) { + switch (Modifier) { + case HighlightingModifier::Declaration: + return "declaration"; + case HighlightingModifier::Deprecated: + return "deprecated"; + case HighlightingModifier::Readonly: + return "readonly"; + case HighlightingModifier::Static: + return "static"; + case HighlightingModifier::Deduced: + return "deduced"; // nonstandard + case HighlightingModifier::Abstract: + return "abstract"; + } +} + std::vector toTheiaSemanticHighlightingInformation( llvm::ArrayRef Tokens) { diff --git a/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp b/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp --- a/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp @@ -8,6 +8,7 @@ #include "SemanticHighlighting.h" #include "refactor/Tweak.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ScopedPrinter.h" namespace clang { namespace clangd { @@ -67,9 +68,19 @@ if (!InsertOffset) return InsertOffset.takeError(); - auto InsertReplacement = tooling::Replacement( - FilePath, *InsertOffset, 0, - ("/* " + toTextMateScope(Token.Kind) + " */").str()); + std::string Comment = "/* "; + Comment.append(llvm::to_string(Token.Kind)); + for (unsigned I = 0; + I <= static_cast(HighlightingModifier::LastModifier); ++I) { + if (Token.Modifiers & (1 << I)) { + Comment.append(" ["); + Comment.append(llvm::to_string(static_cast(I))); + Comment.push_back(']'); + } + } + Comment.append(" */"); + auto InsertReplacement = + tooling::Replacement(FilePath, *InsertOffset, 0, Comment); if (auto Err = Result.add(InsertReplacement)) return std::move(Err); } diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test --- a/clang-tools-extra/clangd/test/initialize-params.test +++ b/clang-tools-extra/clangd/test/initialize-params.test @@ -81,7 +81,14 @@ # CHECK-NEXT: "delta": true # CHECK-NEXT: }, # CHECK-NEXT: "legend": { -# CHECK-NEXT: "tokenModifiers": [], +# CHECK-NEXT: "tokenModifiers": [ +# CHECK-NEXT: "declaration", +# CHECK-NEXT: "deprecated", +# CHECK-NEXT: "deduced", +# CHECK-NEXT: "readonly", +# CHECK-NEXT: "static", +# CHECK-NEXT: "abstract" +# CHECK-NEXT: ], # CHECK-NEXT: "tokenTypes": [ # CHECK-NEXT: "variable", # CHECK: ] diff --git a/clang-tools-extra/clangd/test/semantic-tokens.test b/clang-tools-extra/clangd/test/semantic-tokens.test --- a/clang-tools-extra/clangd/test/semantic-tokens.test +++ b/clang-tools-extra/clangd/test/semantic-tokens.test @@ -18,12 +18,12 @@ # CHECK-NEXT: "jsonrpc": "2.0", # CHECK-NEXT: "result": { # CHECK-NEXT: "data": [ -# First line, char 5, variable, no modifiers. +# First line, char 5, variable, declaration # CHECK-NEXT: 0, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0 +# CHECK-NEXT: 1 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "1" # CHECK-NEXT: } @@ -44,12 +44,12 @@ # CHECK-NEXT: "edits": [ # CHECK-NEXT: { # CHECK-NEXT: "data": [ -# Next line, char 5, variable, no modifiers +# Next line, char 5, variable, declaration # CHECK-NEXT: 1, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0 +# CHECK-NEXT: 1 # CHECK-NEXT: ], # Inserted at position 1 # CHECK-NEXT: "deleteCount": 0, @@ -72,12 +72,12 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0, +# CHECK-NEXT: 1, # CHECK-NEXT: 1, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0 +# CHECK-NEXT: 1 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "3" # CHECK-NEXT: } diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/raw_ostream.h" #include "gmock/gmock.h" #include @@ -86,7 +87,8 @@ return L.R.start < R.R.start; })); - std::string Result; + std::string Buf; + llvm::raw_string_ostream OS(Buf); unsigned NextChar = 0; for (auto &T : Tokens) { unsigned StartOffset = llvm::cantFail(positionToOffset(Input, T.R.start)); @@ -94,14 +96,18 @@ assert(StartOffset <= EndOffset); assert(NextChar <= StartOffset); - Result += Input.substr(NextChar, StartOffset - NextChar); - Result += std::string( - llvm::formatv("${0}[[{1}]]", T.Kind, - Input.substr(StartOffset, EndOffset - StartOffset))); + OS << Input.substr(NextChar, StartOffset - NextChar); + OS << '$' << T.Kind; + for (unsigned I = 0; + I < static_cast(HighlightingModifier::LastModifier); ++I) { + if (T.Modifiers & (1 << I)) + OS << '_' << static_cast(I); + } + OS << "[[" << Input.substr(StartOffset, EndOffset - StartOffset) << "]]"; NextChar = EndOffset; } - Result += Input.substr(NextChar); - return Result; + OS << Input.substr(NextChar); + return std::move(OS.str()); } void checkHighlightings(llvm::StringRef Code, @@ -160,337 +166,340 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { const char *TestCases[] = { R"cpp( - struct $Class[[AS]] { - double $Field[[SomeMember]]; + struct $Class_decl[[AS]] { + double $Field_decl[[SomeMember]]; }; struct { - } $Variable[[S]]; - void $Function[[foo]](int $Parameter[[A]], $Class[[AS]] $Parameter[[As]]) { - $Primitive[[auto]] $LocalVariable[[VeryLongVariableName]] = 12312; - $Class[[AS]] $LocalVariable[[AA]]; - $Primitive[[auto]] $LocalVariable[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]]; - auto $LocalVariable[[FN]] = [ $LocalVariable[[AA]]](int $Parameter[[A]]) -> void {}; + } $Variable_decl[[S]]; + void $Function_decl[[foo]](int $Parameter_decl[[A]], $Class[[AS]] $Parameter_decl[[As]]) { + $Primitive_deduced[[auto]] $LocalVariable_decl[[VeryLongVariableName]] = 12312; + $Class[[AS]] $LocalVariable_decl[[AA]]; + $Primitive_deduced[[auto]] $LocalVariable_decl[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]]; + auto $LocalVariable_decl[[FN]] = [ $LocalVariable[[AA]]](int $Parameter_decl[[A]]) -> void {}; $LocalVariable[[FN]](12312); } )cpp", R"cpp( - void $Function[[foo]](int); - void $Function[[Gah]](); - void $Function[[foo]]() { - auto $LocalVariable[[Bou]] = $Function[[Gah]]; + void $Function_decl[[foo]](int); + void $Function_decl[[Gah]](); + void $Function_decl[[foo]]() { + auto $LocalVariable_decl[[Bou]] = $Function[[Gah]]; } - struct $Class[[A]] { - void $Method[[abc]](); + struct $Class_decl[[A]] { + void $Method_decl[[abc]](); }; )cpp", R"cpp( - namespace $Namespace[[abc]] { - template - struct $Class[[A]] { - $TemplateParameter[[T]] $Field[[t]]; + namespace $Namespace_decl[[abc]] { + template + struct $Class_decl[[A]] { + $TemplateParameter[[T]] $Field_decl[[t]]; }; } - template - struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> { - typename $TemplateParameter[[T]]::$DependentType[[A]]* $Field[[D]]; - }; - $Namespace[[abc]]::$Class[[A]] $Variable[[AA]]; - typedef $Namespace[[abc]]::$Class[[A]] $Class[[AAA]]; - struct $Class[[B]] { - $Class[[B]](); - ~$Class[[B]](); + template + struct $Class_decl[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> { + typename $TemplateParameter[[T]]::$DependentType[[A]]* $Field_decl[[D]]; + }; + $Namespace[[abc]]::$Class[[A]] $Variable_decl[[AA]]; + typedef $Namespace[[abc]]::$Class[[A]] $Class_decl[[AAA]]; + struct $Class_decl[[B]] { + $Class_decl[[B]](); + ~$Class[[B]](); // FIXME: inconsistent with constructor void operator<<($Class[[B]]); - $Class[[AAA]] $Field[[AA]]; + $Class[[AAA]] $Field_decl[[AA]]; }; - $Class[[B]]::$Class[[B]]() {} - $Class[[B]]::~$Class[[B]]() {} - void $Function[[f]] () { - $Class[[B]] $LocalVariable[[BB]] = $Class[[B]](); + $Class[[B]]::$Class_decl[[B]]() {} + $Class[[B]]::~$Class[[B]]() {} // FIXME: inconsistent with constructor + void $Function_decl[[f]] () { + $Class[[B]] $LocalVariable_decl[[BB]] = $Class[[B]](); $LocalVariable[[BB]].~$Class[[B]](); $Class[[B]](); } )cpp", R"cpp( - enum class $Enum[[E]] { - $EnumConstant[[A]], - $EnumConstant[[B]], + enum class $Enum_decl[[E]] { + $EnumConstant_decl_readonly[[A]], + $EnumConstant_decl_readonly[[B]], }; - enum $Enum[[EE]] { - $EnumConstant[[Hi]], + enum $Enum_decl[[EE]] { + $EnumConstant_decl_readonly[[Hi]], }; - struct $Class[[A]] { - $Enum[[E]] $Field[[EEE]]; - $Enum[[EE]] $Field[[EEEE]]; + struct $Class_decl[[A]] { + $Enum[[E]] $Field_decl[[EEE]]; + $Enum[[EE]] $Field_decl[[EEEE]]; }; - int $Variable[[I]] = $EnumConstant[[Hi]]; - $Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]]; + int $Variable_decl[[I]] = $EnumConstant_readonly[[Hi]]; + $Enum[[E]] $Variable_decl[[L]] = $Enum[[E]]::$EnumConstant_readonly[[B]]; )cpp", R"cpp( - namespace $Namespace[[abc]] { + namespace $Namespace_decl[[abc]] { namespace {} - namespace $Namespace[[bcd]] { - struct $Class[[A]] {}; - namespace $Namespace[[cde]] { - struct $Class[[A]] { - enum class $Enum[[B]] { - $EnumConstant[[Hi]], + 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]], }; }; } } } using namespace $Namespace[[abc]]::$Namespace[[bcd]]; - namespace $Namespace[[vwz]] = + namespace $Namespace_decl[[vwz]] = $Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]]; - $Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[AA]]; - $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable[[AAA]] = - $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::$EnumConstant[[Hi]]; - ::$Namespace[[vwz]]::$Class[[A]] $Variable[[B]]; - ::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[BB]]; - )cpp", - R"cpp( - struct $Class[[D]] { - double $Field[[C]]; - }; - struct $Class[[A]] { - double $Field[[B]]; - $Class[[D]] $Field[[E]]; - static double $StaticField[[S]]; - static void $StaticMethod[[bar]]() {} - void $Method[[foo]]() { + $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]]() { $Field[[B]] = 123; this->$Field[[B]] = 156; this->$Method[[foo]](); $Method[[foo]](); - $StaticMethod[[bar]](); - $StaticField[[S]] = 90.1; + $StaticMethod_static[[bar]](); + $StaticField_static[[S]] = 90.1; } }; - void $Function[[foo]]() { - $Class[[A]] $LocalVariable[[AA]]; + void $Function_decl[[foo]]() { + $Class[[A]] $LocalVariable_decl[[AA]]; $LocalVariable[[AA]].$Field[[B]] += 2; $LocalVariable[[AA]].$Method[[foo]](); $LocalVariable[[AA]].$Field[[E]].$Field[[C]]; - $Class[[A]]::$StaticField[[S]] = 90; + $Class[[A]]::$StaticField_static[[S]] = 90; } )cpp", R"cpp( - struct $Class[[AA]] { - int $Field[[A]]; + struct $Class_decl[[AA]] { + int $Field_decl[[A]]; }; - int $Variable[[B]]; - $Class[[AA]] $Variable[[A]]{$Variable[[B]]}; + int $Variable_decl[[B]]; + $Class[[AA]] $Variable_decl[[A]]{$Variable[[B]]}; )cpp", R"cpp( - namespace $Namespace[[a]] { - struct $Class[[A]] {}; - typedef char $Primitive[[C]]; + namespace $Namespace_decl[[a]] { + struct $Class_decl[[A]] {}; + typedef char $Primitive_decl[[C]]; } - typedef $Namespace[[a]]::$Class[[A]] $Class[[B]]; - using $Class[[BB]] = $Namespace[[a]]::$Class[[A]]; - enum class $Enum[[E]] {}; - typedef $Enum[[E]] $Enum[[C]]; - typedef $Enum[[C]] $Enum[[CC]]; - using $Enum[[CD]] = $Enum[[CC]]; - $Enum[[CC]] $Function[[f]]($Class[[B]]); - $Enum[[CD]] $Function[[f]]($Class[[BB]]); - typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]]; - typedef float $Primitive[[F]]; - )cpp", - R"cpp( - template - class $Class[[A]] { - $TemplateParameter[[T]] $Field[[AA]]; - $TemplateParameter[[T]] $Method[[foo]](); - }; - template - class $Class[[B]] { - $Class[[A]]<$TemplateParameter[[TT]]> $Field[[AA]]; - }; - template - class $Class[[BB]] {}; - template - class $Class[[BB]]<$TemplateParameter[[T]], int> {}; - template - class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {}; - - template class $TemplateParameter[[T]], class $TemplateParameter[[C]]> - $TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function[[f]](); + 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 + class $Class_decl[[A]] { + $TemplateParameter[[T]] $Field_decl[[AA]]; + $TemplateParameter[[T]] $Method_decl[[foo]](); + }; + template + class $Class_decl[[B]] { + $Class[[A]]<$TemplateParameter[[TT]]> $Field_decl[[AA]]; + }; + template + class $Class_decl[[BB]] {}; + template + class $Class_decl[[BB]]<$TemplateParameter[[T]], int> {}; + template + class $Class_decl[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {}; + + template class $TemplateParameter_decl[[T]], class $TemplateParameter_decl[[C]]> + $TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function_decl[[f]](); template - class $Class[[Foo]] {}; + class $Class_decl[[Foo]] {}; - template - void $Function[[foo]]($TemplateParameter[[T]] ...); + template + void $Function_decl[[foo]]($TemplateParameter[[T]] ...); )cpp", R"cpp( - template - struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;}; - extern template struct $Class[[Tmpl]]; - template struct $Class[[Tmpl]]; + template + struct $Class_decl[[Tmpl]] {$TemplateParameter[[T]] $Field_decl[[x]] = 0;}; + // FIXME: highlights dropped due to conflicts. + // explicitReferenceTargets reports ClassTemplateSpecializationDecl twice + // at its location, calling it a declaration/non-declaration once each. + extern template struct Tmpl; + template struct Tmpl; )cpp", // 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( - class $Class[[Foo]] {}; - struct $Class[[Bar]] { + class $Class_decl[[Foo]] {}; + struct $Class_decl[[Bar]] { explicit operator $Class[[Foo]]*() const; explicit operator int() const; operator $Class[[Foo]](); }; - void $Function[[f]]() { - $Class[[Bar]] $LocalVariable[[B]]; - $Class[[Foo]] $LocalVariable[[F]] = $LocalVariable[[B]]; - $Class[[Foo]] *$LocalVariable[[FP]] = ($Class[[Foo]]*)$LocalVariable[[B]]; - int $LocalVariable[[I]] = (int)$LocalVariable[[B]]; + 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]]; } )cpp", R"cpp( - struct $Class[[B]] {}; - struct $Class[[A]] { - $Class[[B]] $Field[[BB]]; - $Class[[A]] &operator=($Class[[A]] &&$Parameter[[O]]); + struct $Class_decl[[B]] {}; + struct $Class_decl[[A]] { + $Class[[B]] $Field_decl[[BB]]; + $Class[[A]] &operator=($Class[[A]] &&$Parameter_decl[[O]]); }; - $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter[[O]]) = default; + $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter_decl[[O]]) = default; )cpp", R"cpp( - enum $Enum[[En]] { - $EnumConstant[[EC]], + enum $Enum_decl[[En]] { + $EnumConstant_decl_readonly[[EC]], }; - class $Class[[Foo]] {}; - class $Class[[Bar]] { + class $Class_decl[[Foo]] {}; + class $Class_decl[[Bar]] { public: - $Class[[Foo]] $Field[[Fo]]; - $Enum[[En]] $Field[[E]]; - int $Field[[I]]; - $Class[[Bar]] ($Class[[Foo]] $Parameter[[F]], - $Enum[[En]] $Parameter[[E]]) + $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]]) : $Field[[Fo]] ($Parameter[[F]]), $Field[[E]] ($Parameter[[E]]), $Field[[I]] (123) {} }; - class $Class[[Bar2]] : public $Class[[Bar]] { - $Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) {} + class $Class_decl[[Bar2]] : public $Class[[Bar]] { + $Class_decl[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant_readonly[[EC]]) {} }; )cpp", R"cpp( - enum $Enum[[E]] { - $EnumConstant[[E]], + enum $Enum_decl[[E]] { + $EnumConstant_decl_readonly[[E]], }; - class $Class[[Foo]] {}; - $Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]]; - $Class[[auto]] $Variable[[AF]] = $Class[[Foo]](); - $Class[[decltype]](auto) $Variable[[AF2]] = $Class[[Foo]](); - $Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]]; - $Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]]; - $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4; - $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10; - auto $Variable[[Fun]] = []()->void{}; + 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]]; + $Primitive_deduced[[auto]] $Variable_decl[[Form]] = 10.2 + 2 * 4; + $Primitive_deduced[[decltype]]($Variable[[Form]]) $Variable_decl[[F]] = 10; + auto $Variable_decl[[Fun]] = []()->void{}; )cpp", R"cpp( - class $Class[[G]] {}; - template<$Class[[G]] *$TemplateParameter[[U]]> - class $Class[[GP]] {}; - template<$Class[[G]] &$TemplateParameter[[U]]> - class $Class[[GR]] {}; - template - class $Class[[IP]] { - void $Method[[f]]() { - *$TemplateParameter[[U]] += 5; + 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 + class $Class_decl[[IP]] { + void $Method_decl[[f]]() { + *$TemplateParameter_readonly[[U]] += 5; } }; - template - class $Class[[Foo]] { - void $Method[[f]]() { - for(int $LocalVariable[[I]] = 0; - $LocalVariable[[I]] < $TemplateParameter[[U]];) {} + template + class $Class_decl[[Foo]] { + void $Method_decl[[f]]() { + for(int $LocalVariable_decl[[I]] = 0; + $LocalVariable[[I]] < $TemplateParameter_readonly[[U]];) {} } }; - $Class[[G]] $Variable[[L]]; - void $Function[[f]]() { - $Class[[Foo]]<123> $LocalVariable[[F]]; - $Class[[GP]]<&$Variable[[L]]> $LocalVariable[[LL]]; - $Class[[GR]]<$Variable[[L]]> $LocalVariable[[LLL]]; + $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]]; } )cpp", R"cpp( - template - struct $Class[[G]] { - void $Method[[foo]]( - $TemplateParameter[[T]] *$Parameter[[O]]) { - ($Parameter[[O]]->*$TemplateParameter[[method]])(10); + template + struct $Class_decl[[G]] { + void $Method_decl[[foo]]( + $TemplateParameter[[T]] *$Parameter_decl[[O]]) { + ($Parameter[[O]]->*$TemplateParameter_readonly[[method]])(10); } }; - struct $Class[[F]] { - void $Method[[f]](int); + struct $Class_decl[[F]] { + void $Method_decl[[f]](int); }; - template - struct $Class[[A]] { - void $Method[[f]]() { - (*$TemplateParameter[[Func]])(); + template + struct $Class_decl[[A]] { + void $Method_decl[[f]]() { + (*$TemplateParameter_readonly[[Func]])(); } }; - void $Function[[foo]]() { - $Class[[F]] $LocalVariable[[FF]]; - $Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $LocalVariable[[GG]]; + void $Function_decl[[foo]]() { + $Class[[F]] $LocalVariable_decl[[FF]]; + $Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $LocalVariable_decl[[GG]]; $LocalVariable[[GG]].$Method[[foo]](&$LocalVariable[[FF]]); - $Class[[A]]<$Function[[foo]]> $LocalVariable[[AA]]; + $Class[[A]]<$Function[[foo]]> $LocalVariable_decl[[AA]]; } )cpp", // Tokens that share a source range but have conflicting Kinds are not // highlighted. R"cpp( - #define $Macro[[DEF_MULTIPLE]](X) namespace X { class X { int X; }; } - #define $Macro[[DEF_CLASS]](T) class T {}; + #define $Macro_decl[[DEF_MULTIPLE]](X) namespace X { class X { int X; }; } + #define $Macro_decl[[DEF_CLASS]](T) class T {}; // Preamble ends. $Macro[[DEF_MULTIPLE]](XYZ); $Macro[[DEF_MULTIPLE]](XYZW); - $Macro[[DEF_CLASS]]($Class[[A]]) - #define $Macro[[MACRO_CONCAT]](X, V, T) T foo##X = V - #define $Macro[[DEF_VAR]](X, V) int X = V - #define $Macro[[DEF_VAR_T]](T, X, V) T X = V - #define $Macro[[DEF_VAR_REV]](V, X) DEF_VAR(X, V) - #define $Macro[[CPY]](X) X - #define $Macro[[DEF_VAR_TYPE]](X, Y) X Y - #define $Macro[[SOME_NAME]] variable - #define $Macro[[SOME_NAME_SET]] variable2 = 123 - #define $Macro[[INC_VAR]](X) X += 2 - void $Function[[foo]]() { - $Macro[[DEF_VAR]]($LocalVariable[[X]], 123); - $Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]); - int $Macro[[CPY]]( $LocalVariable[[XX]] ); - $Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]); + $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]]); double $Macro[[SOME_NAME]]; int $Macro[[SOME_NAME_SET]]; $LocalVariable[[variable]] = 20.1; $Macro[[MACRO_CONCAT]](var, 2, float); $Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]]( - $Macro[[CPY]]($LocalVariable[[Nested]])), + $Macro[[CPY]]($LocalVariable_decl[[Nested]])), $Macro[[CPY]]($Class[[A]]())); $Macro[[INC_VAR]]($LocalVariable[[variable]]); } void $Macro[[SOME_NAME]](); - $Macro[[DEF_VAR]]($Variable[[MMMMM]], 567); - $Macro[[DEF_VAR_REV]](756, $Variable[[AB]]); + $Macro[[DEF_VAR]]($Variable_decl[[MMMMM]], 567); + $Macro[[DEF_VAR_REV]](756, $Variable_decl[[AB]]); - #define $Macro[[CALL_FN]](F) F(); - #define $Macro[[DEF_FN]](F) void F () - $Macro[[DEF_FN]]($Function[[g]]) { + #define $Macro_decl[[CALL_FN]](F) F(); + #define $Macro_decl[[DEF_FN]](F) void F () + $Macro[[DEF_FN]]($Function_decl[[g]]) { $Macro[[CALL_FN]]($Function[[foo]]); } )cpp", R"cpp( - #define $Macro[[fail]](expr) expr - #define $Macro[[assert]](COND) if (!(COND)) { fail("assertion failed" #COND); } + #define $Macro_decl[[fail]](expr) expr + #define $Macro_decl[[assert]](COND) if (!(COND)) { fail("assertion failed" #COND); } // Preamble ends. - int $Variable[[x]]; - int $Variable[[y]]; - int $Function[[f]](); - void $Function[[foo]]() { + int $Variable_decl[[x]]; + int $Variable_decl[[y]]; + int $Function_decl[[f]](); + void $Function_decl[[foo]]() { $Macro[[assert]]($Variable[[x]] != $Variable[[y]]); $Macro[[assert]]($Variable[[x]] != $Function[[f]]()); } @@ -498,10 +507,10 @@ // highlighting all macro references R"cpp( #ifndef $Macro[[name]] - #define $Macro[[name]] + #define $Macro_decl[[name]] #endif - #define $Macro[[test]] + #define $Macro_decl[[test]] #undef $Macro[[test]] $InactiveCode[[#ifdef test]] $InactiveCode[[#endif]] @@ -510,104 +519,104 @@ $InactiveCode[[#endif]] )cpp", R"cpp( - struct $Class[[S]] { - float $Field[[Value]]; - $Class[[S]] *$Field[[Next]]; + struct $Class_decl[[S]] { + float $Field_decl[[Value]]; + $Class[[S]] *$Field_decl[[Next]]; }; - $Class[[S]] $Variable[[Global]][2] = {$Class[[S]](), $Class[[S]]()}; - auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]]; - void $Function[[f]]($Class[[S]] $Parameter[[P]]) { - int $LocalVariable[[A]][2] = {1,2}; - auto [$LocalVariable[[B1]], $LocalVariable[[B2]]] = $LocalVariable[[A]]; - auto [$LocalVariable[[G1]], $LocalVariable[[G2]]] = $Variable[[Global]]; - $Class[[auto]] [$LocalVariable[[P1]], $LocalVariable[[P2]]] = $Parameter[[P]]; + $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]]; // Highlights references to BindingDecls. $LocalVariable[[B1]]++; } )cpp", R"cpp( - template - class $Class[[A]] { - using $TemplateParameter[[TemplateParam1]] = $TemplateParameter[[T]]; - typedef $TemplateParameter[[T]] $TemplateParameter[[TemplateParam2]]; - using $Primitive[[IntType]] = int; + template + class $Class_decl[[A]] { + using $TemplateParameter_decl[[TemplateParam1]] = $TemplateParameter[[T]]; + typedef $TemplateParameter[[T]] $TemplateParameter_decl[[TemplateParam2]]; + using $Primitive_decl[[IntType]] = int; - using $Typedef[[Pointer]] = $TemplateParameter[[T]] *; - using $Typedef[[LVReference]] = $TemplateParameter[[T]] &; - using $Typedef[[RVReference]] = $TemplateParameter[[T]]&&; - using $Typedef[[Array]] = $TemplateParameter[[T]]*[3]; - using $Typedef[[MemberPointer]] = int ($Class[[A]]::*)(int); + 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); // Use various previously defined typedefs in a function type. - void $Method[[func]]( + void $Method_decl[[func]]( $Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]], $Typedef[[Array]], $Typedef[[MemberPointer]]); }; )cpp", R"cpp( - template - void $Function[[phase1]]($TemplateParameter[[T]]); - template - void $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) { + template + void $Function_decl[[phase1]]($TemplateParameter[[T]]); + template + void $Function_decl[[foo]]($TemplateParameter[[T]] $Parameter_decl[[P]]) { $Function[[phase1]]($Parameter[[P]]); $DependentName[[phase2]]($Parameter[[P]]); } )cpp", R"cpp( - class $Class[[A]] { - template - void $Method[[bar]]($TemplateParameter[[T]]); + class $Class_decl[[A]] { + template + void $Method_decl[[bar]]($TemplateParameter[[T]]); }; - template - void $Function[[foo]]($TemplateParameter[[U]] $Parameter[[P]]) { + template + void $Function_decl[[foo]]($TemplateParameter[[U]] $Parameter_decl[[P]]) { $Class[[A]]().$Method[[bar]]($Parameter[[P]]); } )cpp", R"cpp( - struct $Class[[A]] { - template - static void $StaticMethod[[foo]]($TemplateParameter[[T]]); + struct $Class_decl[[A]] { + template + static void $StaticMethod_decl_static[[foo]]($TemplateParameter[[T]]); }; - template - struct $Class[[B]] { - void $Method[[bar]]() { - $Class[[A]]::$StaticMethod[[foo]]($TemplateParameter[[T]]()); + template + struct $Class_decl[[B]] { + void $Method_decl[[bar]]() { + $Class[[A]]::$StaticMethod_static[[foo]]($TemplateParameter[[T]]()); } }; )cpp", R"cpp( - template - void $Function[[foo]](typename $TemplateParameter[[T]]::$DependentType[[Type]] + template + void $Function_decl[[foo]](typename $TemplateParameter[[T]]::$DependentType[[Type]] = $TemplateParameter[[T]]::$DependentName[[val]]); )cpp", R"cpp( - template - void $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) { + template + void $Function_decl[[foo]]($TemplateParameter[[T]] $Parameter_decl[[P]]) { $Parameter[[P]].$DependentName[[Field]]; } )cpp", R"cpp( - template - class $Class[[A]] { - int $Method[[foo]]() { + template + class $Class_decl[[A]] { + int $Method_decl[[foo]]() { return $TemplateParameter[[T]]::$DependentName[[Field]]; } }; )cpp", // Highlighting the using decl as the underlying using shadow decl. R"cpp( - void $Function[[foo]](); + void $Function_decl[[foo]](); using ::$Function[[foo]]; )cpp", // Highlighting of template template arguments. R"cpp( - template