diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 37f3d90ea4ae..1f8fa9541a6b 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -40,6 +40,16 @@ public: 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 @@ private: 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; @@ -247,8 +265,12 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) { 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/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h index e375f1be1c17..eaeeb861f9a2 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -26,6 +26,8 @@ namespace clangd { enum class HighlightingKind { Variable = 0, Function, + Method, + Field, Class, Enum, EnumConstant, diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test index 99f48050bceb..7de25d1713dc 100644 --- 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: "entity.name.function.cpp" # CHECK-NEXT: ], # CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.method.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "variable.other.field.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 index 9ada83864108..7ba35fee6d85 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -38,7 +38,9 @@ void checkHighlightings(llvm::StringRef Code) { {HighlightingKind::Class, "Class"}, {HighlightingKind::Enum, "Enum"}, {HighlightingKind::Namespace, "Namespace"}, - {HighlightingKind::EnumConstant, "EnumConstant"}}; + {HighlightingKind::EnumConstant, "EnumConstant"}, + {HighlightingKind::Field, "Field"}, + {HighlightingKind::Method, "Method"}}; std::vector ExpectedTokens; for (const auto &KindString : KindToString) { std::vector Toks = makeHighlightingTokens( @@ -54,14 +56,14 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { 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); } @@ -73,19 +75,19 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { 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; @@ -93,7 +95,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { $Class[[B]](); ~$Class[[B]](); void operator<<($Class[[B]]); - $Class[[AAA]] AA; + $Class[[AAA]] $Field[[AA]]; }; $Class[[B]]::$Class[[B]]() {} $Class[[B]]::~$Class[[B]]() {} @@ -112,8 +114,8 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { $EnumConstant[[Hi]], }; struct $Class[[A]] { - $Enum[[E]] EEE; - $Enum[[EE]] EEEE; + $Enum[[E]] $Field[[EEE]]; + $Enum[[EE]] $Field[[EEEE]]; }; int $Variable[[I]] = $EnumConstant[[Hi]]; $Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]]; @@ -140,6 +142,30 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { $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 $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);