From 8dd26fd84e7c0cbb193e07961c57f6c895801f5e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 10 Sep 2019 10:10:36 +0000 Subject: [PATCH] [clangd] Collect location of macro definition in the ParsedAST allows semantic hightlighting macro definition Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67264 llvm-svn: 371504 --- clang-tools-extra/clangd/ParsedAST.cpp | 33 +++++++++++-------- clang-tools-extra/clangd/ParsedAST.h | 14 ++++---- .../clangd/SemanticHighlighting.cpp | 6 ++-- .../clangd/unittests/ParsedASTTests.cpp | 17 +++++----- .../unittests/SemanticHighlightingTests.cpp | 24 +++++++------- 5 files changed, 52 insertions(+), 42 deletions(-) diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 4e39c37fe9b6..3619144eae92 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -98,23 +98,30 @@ private: std::vector TopLevelDecls; }; -// This collects macro expansions in the main file. +// This collects macro expansions/definitions in the main file. // (Contrast with CollectMainFileMacros in Preamble.cpp, which collects macro // *definitions* in the preamble region of the main file). -class CollectMainFileMacroExpansions : public PPCallbacks { +class CollectMainFileMacros : public PPCallbacks { const SourceManager &SM; std::vector &MainFileMacroLocs; + void addLoc(SourceLocation Loc) { + if (!Loc.isMacroID() && isInsideMainFile(Loc, SM)) + MainFileMacroLocs.push_back(Loc); + } + public: - CollectMainFileMacroExpansions(const SourceManager &SM, - std::vector &MainFileMacroLocs) + CollectMainFileMacros(const SourceManager &SM, + std::vector &MainFileMacroLocs) : SM(SM), MainFileMacroLocs(MainFileMacroLocs) {} + void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) override { + addLoc(MacroNameTok.getLocation()); + } void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override { - SourceLocation L = MacroNameTok.getLocation(); - if (!L.isMacroID() && isInsideMainFile(L, SM)) - MainFileMacroLocs.push_back(L); + addLoc(MacroNameTok.getLocation()); } }; @@ -358,8 +365,8 @@ ParsedAST::build(std::unique_ptr CI, // Collect the macro expansions in the main file. std::vector MainFileMacroExpLocs; Clang->getPreprocessor().addPPCallbacks( - std::make_unique( - Clang->getSourceManager(), MainFileMacroExpLocs)); + std::make_unique(Clang->getSourceManager(), + MainFileMacroExpLocs)); // Copy over the includes from the preamble, then combine with the // non-preamble includes below. @@ -453,8 +460,8 @@ llvm::ArrayRef ParsedAST::getLocalTopLevelDecls() { return LocalTopLevelDecls; } -llvm::ArrayRef ParsedAST::getMainFileExpansions() const { - return MainFileMacroExpLocs; +llvm::ArrayRef ParsedAST::getMacros() const { + return MacroIdentifierLocs; } const std::vector &ParsedAST::getDiagnostics() const { return Diags; } @@ -503,13 +510,13 @@ ParsedAST::ParsedAST(std::shared_ptr Preamble, std::unique_ptr Clang, std::unique_ptr Action, syntax::TokenBuffer Tokens, - std::vector MainFileMacroExpLocs, + std::vector MacroIdentifierLocs, std::vector LocalTopLevelDecls, std::vector Diags, IncludeStructure Includes, CanonicalIncludes CanonIncludes) : Preamble(std::move(Preamble)), Clang(std::move(Clang)), Action(std::move(Action)), Tokens(std::move(Tokens)), - MainFileMacroExpLocs(std::move(MainFileMacroExpLocs)), + MacroIdentifierLocs(std::move(MacroIdentifierLocs)), Diags(std::move(Diags)), LocalTopLevelDecls(std::move(LocalTopLevelDecls)), Includes(std::move(Includes)), CanonIncludes(std::move(CanonIncludes)) { diff --git a/clang-tools-extra/clangd/ParsedAST.h b/clang-tools-extra/clangd/ParsedAST.h index 5486e91dd1e5..f37e14d80516 100644 --- a/clang-tools-extra/clangd/ParsedAST.h +++ b/clang-tools-extra/clangd/ParsedAST.h @@ -89,9 +89,10 @@ public: const IncludeStructure &getIncludeStructure() const; const CanonicalIncludes &getCanonicalIncludes() const; - /// The start locations of all macro expansions spelled inside the main file. - /// Does not include expansions from inside other macro expansions. - llvm::ArrayRef getMainFileExpansions() const; + /// Gets all macro locations (definition, expansions) present in the main + /// file. + /// NOTE: macros inside the preamble are not included. + llvm::ArrayRef getMacros() const; /// Tokens recorded while parsing the main file. /// (!) does not have tokens from the preamble. const syntax::TokenBuffer &getTokens() const { return Tokens; } @@ -120,9 +121,10 @@ private: /// - Does not have spelled or expanded tokens for files from preamble. syntax::TokenBuffer Tokens; - /// The start locations of all macro expansions spelled inside the main file. - /// Does not include expansions from inside other macro expansions. - std::vector MainFileMacroExpLocs; + /// The start locations of all macro definitions/expansions spelled **after** + /// preamble. + /// Does not include locations from inside other macro expansions. + std::vector MacroIdentifierLocs; // Data, stored after parsing. std::vector Diags; // Top-level decls inside the current file. Not that this does not include diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 5744e866d1be..c38bf87cb335 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -38,10 +38,8 @@ public: 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); + for (SourceLocation Loc : AST.getMacros()) + addToken(Loc, HighlightingKind::Macro); // Initializer lists can give duplicates of tokens, therefore all tokens // must be deduplicated. llvm::sort(Tokens); diff --git a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp index da55e541d039..65020bf2a95f 100644 --- a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp +++ b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp @@ -230,26 +230,28 @@ TEST(ParsedASTTest, CanBuildInvocationWithUnknownArgs) { TEST(ParsedASTTest, CollectsMainFileMacroExpansions) { Annotations TestCase(R"cpp( #define MACRO_ARGS(X, Y) X Y + // - premable ends, macros inside preamble are not considered in main file. ^ID(int A); // Macro arguments included. ^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^ID(= 2)); // Macro names inside other macros not included. - #define FOO BAR - #define BAR 1 + #define ^MACRO_ARGS2(X, Y) X Y + #define ^FOO BAR + #define ^BAR 1 int A = ^FOO; // Macros from token concatenations not included. - #define CONCAT(X) X##A() - #define PREPEND(X) MACRO##X() - #define MACROA() 123 + #define ^CONCAT(X) X##A() + #define ^PREPEND(X) MACRO##X() + #define ^MACROA() 123 int B = ^CONCAT(MACRO); int D = ^PREPEND(A) // Macros included not from preamble not included. #include "foo.inc" - #define assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); } + #define ^assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); } void test() { // Includes macro expansions in arguments that are expressions @@ -268,8 +270,7 @@ TEST(ParsedASTTest, CollectsMainFileMacroExpansions) { int D = DEF; )cpp"; ParsedAST AST = TU.build(); - const std::vector &MacroExpansionLocations = - AST.getMainFileExpansions(); + const std::vector &MacroExpansionLocations = AST.getMacros(); std::vector MacroExpansionPositions; for (const auto &L : MacroExpansionLocations) MacroExpansionPositions.push_back( diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index abc0f4e56a37..50955b3e69e5 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -427,18 +427,19 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { R"cpp( #define DEF_MULTIPLE(X) namespace X { class X { int X; }; } #define DEF_CLASS(T) class T {}; + // Preamble ends. $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 - #define DEF_VAR_REV(V, X) DEF_VAR(X, V) - #define CPY(X) X - #define DEF_VAR_TYPE(X, Y) X Y - #define SOME_NAME variable - #define SOME_NAME_SET variable2 = 123 - #define INC_VAR(X) X += 2 + #define $Macro[[MACRO_CONCAT]](X, V, T) T foo##X = V + #define $Macro[[DEF_VAR]](X, V) int X = V + #define $Macro[[DEF_VAR_T]](T, X, V) T X = V + #define $Macro[[DEF_VAR_REV]](V, X) DEF_VAR(X, V) + #define $Macro[[CPY]](X) X + #define $Macro[[DEF_VAR_TYPE]](X, Y) X Y + #define $Macro[[SOME_NAME]] variable + #define $Macro[[SOME_NAME_SET]] variable2 = 123 + #define $Macro[[INC_VAR]](X) X += 2 $Primitive[[void]] $Function[[foo]]() { $Macro[[DEF_VAR]]($LocalVariable[[X]], 123); $Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]); @@ -457,8 +458,8 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { $Macro[[DEF_VAR]]($Variable[[XYZ]], 567); $Macro[[DEF_VAR_REV]](756, $Variable[[AB]]); - #define CALL_FN(F) F(); - #define DEF_FN(F) void F () + #define $Macro[[CALL_FN]](F) F(); + #define $Macro[[DEF_FN]](F) void F () $Macro[[DEF_FN]]($Function[[g]]) { $Macro[[CALL_FN]]($Function[[foo]]); } @@ -466,6 +467,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { R"cpp( #define fail(expr) expr #define assert(COND) if (!(COND)) { fail("assertion failed" #COND); } + // Preamble ends. $Primitive[[int]] $Variable[[x]]; $Primitive[[int]] $Variable[[y]]; $Primitive[[int]] $Function[[f]]();