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 @@ -26,6 +26,8 @@ enum class HighlightingKind { Variable = 0, Function, + Constructor, + Destructor, NumKinds, }; 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 @@ -36,7 +36,10 @@ bool VisitNamedDecl(NamedDecl *ND) { // FIXME: (De)Constructors/operator need to be highlighted some other way. - if (ND->getDeclName().getNameKind() != DeclarationName::Identifier) + auto Kind = ND->getDeclName().getNameKind(); + if (Kind != DeclarationName::Identifier && + Kind != DeclarationName::CXXConstructorName && + Kind != DeclarationName::CXXDestructorName) return true; if (ND->getDeclName().isEmpty()) @@ -58,6 +61,21 @@ private: void addToken(SourceLocation Loc, const Decl *D) { + if (Loc.isMacroID()) + // FIXME: skip tokens inside macros for now. + return; + + if(isa(D)) { + addToken(Loc, HighlightingKind::Constructor); + return; + } + if (isa(D)) { + addToken( + Loc, + dyn_cast(D)->getDeclName().getAsString().size(), + HighlightingKind::Destructor); + return; + } if (isa(D)) { addToken(Loc, HighlightingKind::Variable); return; @@ -69,10 +87,6 @@ } void addToken(SourceLocation Loc, HighlightingKind Kind) { - if (Loc.isMacroID()) - // FIXME: skip tokens inside macros for now. - return; - auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc); if (!R) { // R should always have a value, if it doesn't something is very wrong. @@ -82,6 +96,13 @@ Tokens.push_back({Kind, R.getValue()}); } + void addToken(SourceLocation Loc, int Len, HighlightingKind Kind) { + auto StartLoc = sourceLocToPosition(SM, Loc); + Position EndLoc; + EndLoc.line = StartLoc.line; + EndLoc.character = StartLoc.character + Len; + Tokens.push_back({Kind, {StartLoc, EndLoc}}); + } }; // Encode binary data into base64. @@ -176,6 +197,10 @@ return "entity.name.function.cpp"; case HighlightingKind::Variable: return "variable.cpp"; + case HighlightingKind::Constructor: + return "entity.name.function.constructor.cpp"; + case HighlightingKind::Destructor: + return "entity.name.function.destructor.cpp"; case HighlightingKind::NumKinds: llvm_unreachable("must not pass NumKinds to the function"); } diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test --- a/clang-tools-extra/clangd/test/semantic-highlighting.test +++ b/clang-tools-extra/clangd/test/semantic-highlighting.test @@ -10,6 +10,12 @@ # CHECK-NEXT: [ # CHECK-NEXT: "entity.name.function.cpp" # CHECK-NEXT: ] +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.constructor.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.destructor.cpp" +# CHECK-NEXT: ] # CHECK-NEXT: ] # 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 @@ -34,7 +34,9 @@ auto AST = TestTU::withCode(Test.code()).build(); static const std::map KindToString{ {HighlightingKind::Variable, "Variable"}, - {HighlightingKind::Function, "Function"}}; + {HighlightingKind::Function, "Function"}, + {HighlightingKind::Constructor, "Constructor"}, + {HighlightingKind::Destructor, "Destructor"}}; std::vector ExpectedTokens; for (const auto &KindString : KindToString) { std::vector Toks = @@ -71,11 +73,12 @@ )cpp", R"cpp( struct A { - A(); - ~A(); + $Constructor[[A]](); + $Destructor[[~A]]() {} void $Function[[abc]](); void operator<<(int); }; + struct B {}; )cpp"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase);