From becbdc66dcb5df6685831257ad6a5d1f22cd332b Mon Sep 17 00:00:00 2001 From: Johan Vikstrom Date: Fri, 30 Aug 2019 15:47:27 +0000 Subject: [PATCH] [clangd] Add highlighting for macro expansions. Summary: https://github.com/clangd/clangd/issues/134 Reviewers: hokein, ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66995 llvm-svn: 370482 --- .../clangd/SemanticHighlighting.cpp | 19 +++++--- .../clangd/SemanticHighlighting.h | 1 + .../clangd/test/semantic-highlighting.test | 3 ++ .../unittests/SemanticHighlightingTests.cpp | 48 ++++++++++--------- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index e71c0a733a63..eaa57f8ab660 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -24,16 +24,20 @@ namespace { class HighlightingTokenCollector : public RecursiveASTVisitor { std::vector Tokens; - ASTContext &Ctx; - const SourceManager &SM; + ParsedAST * public: - HighlightingTokenCollector(ParsedAST &AST) - : Ctx(AST.getASTContext()), SM(AST.getSourceManager()) {} + HighlightingTokenCollector(ParsedAST &AST) : AST(AST) {} std::vector collectTokens() { Tokens.clear(); - TraverseAST(Ctx); + TraverseAST(AST.getASTContext()); + // Add highlightings for macro expansions as they are not traversed by the + // visitor. + // FIXME: Should add highlighting to the macro definitions as well. But this + // information is not collected in ParsedAST right now. + for (const SourceLocation &L : AST.getMainFileExpansions()) + addToken(L, HighlightingKind::Macro); // Initializer lists can give duplicates of tokens, therefore all tokens // must be deduplicated. llvm::sort(Tokens); @@ -264,6 +268,7 @@ private: } void addToken(SourceLocation Loc, HighlightingKind Kind) { + const auto &SM = AST.getSourceManager(); if (Loc.isMacroID()) { // Only intereseted in highlighting arguments in macros (DEF_X(arg)). if (!SM.isMacroArgExpansion(Loc)) @@ -279,7 +284,7 @@ private: if (!isInsideMainFile(Loc, SM)) return; - auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc); + auto R = getTokenRange(SM, AST.getASTContext().getLangOpts(), Loc); if (!R) { // R should always have a value, if it doesn't something is very wrong. elog("Tried to add semantic token with an invalid range"); @@ -466,6 +471,8 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) { return "entity.name.type.template.cpp"; case HighlightingKind::Primitive: return "storage.type.primitive.cpp"; + case HighlightingKind::Macro: + return "entity.name.function.preprocessor.cpp"; case HighlightingKind::NumKinds: llvm_unreachable("must not pass NumKinds to the function"); } diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h index 928c99c8223f..6d58884ac434 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -38,6 +38,7 @@ enum class HighlightingKind { Namespace, TemplateParameter, Primitive, + Macro, NumKinds, }; diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test index e984b5d61402..005d01cad8bf 100644 --- a/clang-tools-extra/clangd/test/semantic-highlighting.test +++ b/clang-tools-extra/clangd/test/semantic-highlighting.test @@ -45,6 +45,9 @@ # CHECK-NEXT: ], # CHECK-NEXT: [ # CHECK-NEXT: "storage.type.primitive.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.preprocessor.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 index 04828d0e741e..cc60e62255b0 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -47,7 +47,8 @@ std::vector getExpectedTokens(Annotations &Test) { {HighlightingKind::Method, "Method"}, {HighlightingKind::StaticMethod, "StaticMethod"}, {HighlightingKind::TemplateParameter, "TemplateParameter"}, - {HighlightingKind::Primitive, "Primitive"}}; + {HighlightingKind::Primitive, "Primitive"}, + {HighlightingKind::Macro, "Macro"}}; std::vector ExpectedTokens; for (const auto &KindString : KindToString) { std::vector Toks = makeHighlightingTokens( @@ -391,9 +392,9 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { R"cpp( #define DEF_MULTIPLE(X) namespace X { class X { int X; }; } #define DEF_CLASS(T) class T {}; - DEF_MULTIPLE(XYZ); - DEF_MULTIPLE(XYZW); - DEF_CLASS($Class[[A]]) + $Macro[[DEF_MULTIPLE]](XYZ); + $Macro[[DEF_MULTIPLE]](XYZW); + $Macro[[DEF_CLASS]]($Class[[A]]) #define MACRO_CONCAT(X, V, T) T foo##X = V #define DEF_VAR(X, V) int X = V #define DEF_VAR_T(T, X, V) T X = V @@ -404,26 +405,27 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { #define SOME_NAME_SET variable2 = 123 #define INC_VAR(X) X += 2 $Primitive[[void]] $Function[[foo]]() { - DEF_VAR($LocalVariable[[X]], 123); - DEF_VAR_REV(908, $LocalVariable[[XY]]); - $Primitive[[int]] CPY( $LocalVariable[[XX]] ); - DEF_VAR_TYPE($Class[[A]], $LocalVariable[[AA]]); - $Primitive[[double]] SOME_NAME; - $Primitive[[int]] SOME_NAME_SET; + $Macro[[DEF_VAR]]($LocalVariable[[X]], 123); + $Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]); + $Primitive[[int]] $Macro[[CPY]]( $LocalVariable[[XX]] ); + $Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]); + $Primitive[[double]] $Macro[[SOME_NAME]]; + $Primitive[[int]] $Macro[[SOME_NAME_SET]]; $LocalVariable[[variable]] = 20.1; - MACRO_CONCAT(var, 2, $Primitive[[float]]); - DEF_VAR_T($Class[[A]], CPY(CPY($LocalVariable[[Nested]])), - CPY($Class[[A]]())); - INC_VAR($LocalVariable[[variable]]); + $Macro[[MACRO_CONCAT]](var, 2, $Primitive[[float]]); + $Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]]( + $Macro[[CPY]]($LocalVariable[[Nested]])), + $Macro[[CPY]]($Class[[A]]())); + $Macro[[INC_VAR]]($LocalVariable[[variable]]); } - $Primitive[[void]] SOME_NAME(); - DEF_VAR($Variable[[XYZ]], 567); - DEF_VAR_REV(756, $Variable[[AB]]); + $Primitive[[void]] $Macro[[SOME_NAME]](); + $Macro[[DEF_VAR]]($Variable[[XYZ]], 567); + $Macro[[DEF_VAR_REV]](756, $Variable[[AB]]); #define CALL_FN(F) F(); #define DEF_FN(F) void F () - DEF_FN($Function[[g]]) { - CALL_FN($Function[[foo]]); + $Macro[[DEF_FN]]($Function[[g]]) { + $Macro[[CALL_FN]]($Function[[foo]]); } )cpp", R"cpp( @@ -433,8 +435,8 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { $Primitive[[int]] $Variable[[y]]; $Primitive[[int]] $Function[[f]](); $Primitive[[void]] $Function[[foo]]() { - assert($Variable[[x]] != $Variable[[y]]); - assert($Variable[[x]] != $Function[[f]]()); + $Macro[[assert]]($Variable[[x]] != $Variable[[y]]); + $Macro[[assert]]($Variable[[x]] != $Function[[f]]()); } )cpp", R"cpp( @@ -470,8 +472,8 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { // A separate test for macros in headers. checkHighlightings(R"cpp( #include "imp.h" - DEFINE_Y - DXYZ_Y(A); + $Macro[[DEFINE_Y]] + $Macro[[DXYZ_Y]](A); )cpp", {{"imp.h", R"cpp( #define DXYZ(X) class X {};