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 @@ -25,7 +25,9 @@ enum class HighlightingKind { Variable = 0, + Field, Function, + Method, Class, Enum, Namespace, 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 @@ -40,6 +40,16 @@ return true; } + bool VisitMemberExpr(MemberExpr *ME) { + const auto *MD = ME->getMemberDecl(); + if (isa(MD)) + // When calling the destructor manually like: AAA::~A(); The ~ is a + // MemberExpr. Other methods should still be highlighted though. + return true; + addToken(ME->getMemberLoc(), MD); + return true; + } + bool VisitNamedDecl(NamedDecl *ND) { // UsingDirectiveDecl's namespaces do not show up anywhere else in the // Visit/Traverse mehods. But they should also be highlighted as a @@ -115,6 +125,14 @@ addToken(Loc, HighlightingKind::Class); return; } + if (isa(D)) { + addToken(Loc, HighlightingKind::Method); + return; + } + if (isa(D)) { + addToken(Loc, HighlightingKind::Field); + return; + } if (isa(D)) { addToken(Loc, HighlightingKind::Enum); return; @@ -243,8 +261,12 @@ switch (Kind) { case HighlightingKind::Function: return "entity.name.function.cpp"; + case HighlightingKind::Method: + return "entity.name.function.method.cpp"; case HighlightingKind::Variable: - return "variable.cpp"; + return "variable.other.cpp"; + case HighlightingKind::Field: + return "variable.other.field.cpp"; case HighlightingKind::Class: return "entity.name.type.class.cpp"; case HighlightingKind::Enum: 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 @@ -5,12 +5,18 @@ # CHECK: "semanticHighlighting": { # CHECK-NEXT: "scopes": [ # CHECK-NEXT: [ -# CHECK-NEXT: "variable.cpp" +# CHECK-NEXT: "variable.other.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "variable.other.field.cpp" # CHECK-NEXT: ], # CHECK-NEXT: [ # CHECK-NEXT: "entity.name.function.cpp" # CHECK-NEXT: ], # CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.method.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ # CHECK-NEXT: "entity.name.type.class.cpp" # 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 @@ -37,7 +37,9 @@ {HighlightingKind::Function, "Function"}, {HighlightingKind::Class, "Class"}, {HighlightingKind::Enum, "Enum"}, - {HighlightingKind::Namespace, "Namespace"}}; + {HighlightingKind::Namespace, "Namespace"}, + {HighlightingKind::Field, "Field"}, + {HighlightingKind::Method, "Method"}}; std::vector ExpectedTokens; for (const auto &KindString : KindToString) { std::vector Toks = makeHighlightingTokens( @@ -53,14 +55,14 @@ const char *TestCases[] = { R"cpp( struct $Class[[AS]] { - double SomeMember; + double $Field[[SomeMember]]; }; struct { } $Variable[[S]]; void $Function[[foo]](int $Variable[[A]], $Class[[AS]] $Variable[[As]]) { auto $Variable[[VeryLongVariableName]] = 12312; $Class[[AS]] $Variable[[AA]]; - auto $Variable[[L]] = $Variable[[AA]].SomeMember + $Variable[[A]]; + auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]]; auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {}; $Variable[[FN]](12312); } @@ -72,19 +74,19 @@ auto $Variable[[Bou]] = $Function[[Gah]]; } struct $Class[[A]] { - void $Function[[abc]](); + void $Method[[abc]](); }; )cpp", R"cpp( namespace $Namespace[[abc]] { template struct $Class[[A]] { - T t; + T $Field[[t]]; }; } template struct $Class[[C]] : $Namespace[[abc]]::A { - typename T::A* D; + typename T::A* $Field[[D]]; }; $Namespace[[abc]]::$Class[[A]] $Variable[[AA]]; typedef $Namespace[[abc]]::$Class[[A]] AAA; @@ -92,7 +94,7 @@ $Class[[B]](); ~$Class[[B]](); void operator<<($Class[[B]]); - $Class[[AAA]] AA; + $Class[[AAA]] $Field[[AA]]; }; $Class[[B]]::$Class[[B]]() {} $Class[[B]]::~$Class[[B]]() {} @@ -106,8 +108,8 @@ enum class $Enum[[E]] {}; enum $Enum[[EE]] {}; struct $Class[[A]] { - $Enum[[E]] EEE; - $Enum[[EE]] EEEE; + $Enum[[E]] $Field[[EEE]]; + $Enum[[EE]] $Field[[EEEE]]; }; )cpp", R"cpp( @@ -132,6 +134,30 @@ $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::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 $Variable[[S]]; + void $Method[[foo]]() { + $Field[[B]] = 123; + this->$Field[[B]] = 156; + this->$Method[[foo]](); + $Method[[foo]](); + $Variable[[S]] = 90.1; + } + }; + void $Function[[foo]]() { + $Class[[A]] $Variable[[AA]]; + $Variable[[AA]].$Field[[B]] += 2; + $Variable[[AA]].$Method[[foo]](); + $Variable[[AA]].$Field[[E]].$Field[[C]]; + $Class[[A]]::$Variable[[S]] = 90; + } )cpp"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase); @@ -181,7 +207,7 @@ toSemanticHighlightingInformation(Tokens); std::vector ExpectedResults = { {1, "AAAAAQAEAAA="}, - {3, "AAAACAAEAAAAAAAEAAMAAQ=="}}; + {3, "AAAACAAEAAAAAAAEAAMAAg=="}}; EXPECT_EQ(ActualResults, ExpectedResults); }