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, + MemberVariable, 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,22 @@ return true; } + bool VisitMemberExpr(MemberExpr *ME) { + if (const CXXMethodDecl *MD = + dyn_cast(ME->getMemberDecl())) { + // When calling the destructor manually like: AAA::~A(); The ~ is a + // MemberExpr. + if (!isa(MD)) + addToken(ME->getMemberLoc(), MD); + return true; + } + + // The MemberDecl is VarDecl for static members, therefore getMemberDecl + // does not work for all member variables. + addToken(ME->getMemberLoc(), ME); + 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 @@ -123,6 +139,10 @@ addToken(Loc, HighlightingKind::Variable); return; } + if(isa(D)) { + addToken(Loc, HighlightingKind::Method); + return; + } if (isa(D)) { addToken(Loc, HighlightingKind::Function); return; @@ -135,6 +155,17 @@ addToken(Loc, HighlightingKind::Namespace); return; } + if (isa(D)) { + addToken(Loc, HighlightingKind::MemberVariable); + return; + } + } + + void addToken(SourceLocation Loc, const Expr *D) { + if (isa(D)) { + addToken(Loc, HighlightingKind::MemberVariable); + return; + } } void addToken(SourceLocation Loc, HighlightingKind Kind) { @@ -243,8 +274,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::MemberVariable: + return "variable.other.member.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.member.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::MemberVariable, "MemberVariable"}, + {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 $MemberVariable[[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]].$MemberVariable[[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 $MemberVariable[[t]]; }; } template struct $Class[[C]] : $Namespace[[abc]]::A { - typename T::A* D; + typename T::A* $MemberVariable[[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]] $MemberVariable[[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]] $MemberVariable[[EEE]]; + $Enum[[EE]] $MemberVariable[[EEEE]]; }; )cpp", R"cpp( @@ -132,6 +134,27 @@ $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 $MemberVariable[[C]]; + }; + struct $Class[[A]] { + double $MemberVariable[[B]]; + $Class[[D]] $MemberVariable[[E]]; + void $Method[[foo]]() { + $MemberVariable[[B]] = 123; + this->$MemberVariable[[B]] = 156; + this->$Method[[foo]](); + $Method[[foo]](); + } + }; + void $Function[[foo]]() { + $Class[[A]] $Variable[[AA]]; + $Variable[[AA]].$MemberVariable[[B]] += 2; + $Variable[[AA]].$Method[[foo]](); + $Variable[[AA]].$MemberVariable[[E]].$MemberVariable[[C]]; + } )cpp"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase); @@ -181,7 +204,7 @@ toSemanticHighlightingInformation(Tokens); std::vector ExpectedResults = { {1, "AAAAAQAEAAA="}, - {3, "AAAACAAEAAAAAAAEAAMAAQ=="}}; + {3, "AAAACAAEAAAAAAAEAAMAAg=="}}; EXPECT_EQ(ActualResults, ExpectedResults); }