Author: Utkarsh Saxena Date: 2019-11-18T16:47:18+01:00 New Revision: 2054ed052f15b584e1bce57c8f765991eab2da7d
URL: https://github.com/llvm/llvm-project/commit/2054ed052f15b584e1bce57c8f765991eab2da7d DIFF: https://github.com/llvm/llvm-project/commit/2054ed052f15b584e1bce57c8f765991eab2da7d.diff LOG: [clangd] Store xref for Macros in ParsedAST. This patch adds the cross references for Macros in the MainFile. We add references for the main file to the ParsedAST. We query the references from it using the SymbolID. Xref outside main file will be added to the index in a separate patch. Added: clang-tools-extra/clangd/unittests/CollectMacrosTests.cpp Modified: clang-tools-extra/clangd/CollectMacros.h clang-tools-extra/clangd/SemanticHighlighting.cpp clang-tools-extra/clangd/XRefs.cpp clang-tools-extra/clangd/unittests/CMakeLists.txt clang-tools-extra/clangd/unittests/ParsedASTTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/CollectMacros.h b/clang-tools-extra/clangd/CollectMacros.h index 619c9f54b58a..17e9917542bd 100644 --- a/clang-tools-extra/clangd/CollectMacros.h +++ b/clang-tools-extra/clangd/CollectMacros.h @@ -9,10 +9,13 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTEDMACROS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTEDMACROS_H +#include "AST.h" #include "Protocol.h" #include "SourceCode.h" +#include "index/SymbolID.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Lex/PPCallbacks.h" +#include "llvm/ADT/DenseMap.h" #include <string> namespace clang { @@ -22,7 +25,11 @@ struct MainFileMacros { llvm::StringSet<> Names; // Instead of storing SourceLocation, we have to store the token range because // SourceManager from preamble is not available when we build the AST. - std::vector<Range> Ranges; + llvm::DenseMap<SymbolID, std::vector<Range>> MacroRefs; + // Somtimes it is not possible to compute the SymbolID for the Macro, e.g. a + // reference to an undefined macro. Store them separately, e.g. for semantic + // highlighting. + std::vector<Range> UnknownMacros; }; /// Collects macro references (e.g. definitions, expansions) in the main file. @@ -80,8 +87,12 @@ class CollectMainFileMacros : public PPCallbacks { return; if (auto Range = getTokenRange(SM, LangOpts, Loc)) { - Out.Names.insert(MacroNameTok.getIdentifierInfo()->getName()); - Out.Ranges.push_back(*Range); + auto Name = MacroNameTok.getIdentifierInfo()->getName(); + Out.Names.insert(Name); + if (auto SID = getSymbolID(Name, MI, SM)) + Out.MacroRefs[*SID].push_back(*Range); + else + Out.UnknownMacros.push_back(*Range); } } const SourceManager &SM; diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 9838600584c6..4e47a83d8da0 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -311,9 +311,14 @@ std::vector<HighlightingToken> getSemanticHighlightings(ParsedAST &AST) { if (auto Kind = kindForReference(R)) Builder.addToken(R.NameLoc, *Kind); }); - // Add highlightings for macro expansions. - for (const auto &M : AST.getMacros().Ranges) + // Add highlightings for macro references. + for (const auto &SIDToRefs : AST.getMacros().MacroRefs) { + for (const auto &M : SIDToRefs.second) + Builder.addToken({HighlightingKind::Macro, M}); + } + for (const auto &M : AST.getMacros().UnknownMacros) Builder.addToken({HighlightingKind::Macro, M}); + return std::move(Builder).collect(); } diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index d604379b75fc..9697b8eec19a 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -917,8 +917,7 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, MainFileRefs.end()); for (const auto &Ref : MainFileRefs) { if (auto Range = - getTokenRange(AST.getASTContext().getSourceManager(), - AST.getASTContext().getLangOpts(), Ref.Loc)) { + getTokenRange(SM, AST.getASTContext().getLangOpts(), Ref.Loc)) { Location Result; Result.range = *Range; Result.uri = URIForFile::canonicalize(*MainFilePath, *MainFilePath); diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index 7e298b6ad053..21c29196034f 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -30,6 +30,7 @@ add_unittest(ClangdUnitTests ClangdTests ClangdTests.cpp CodeCompleteTests.cpp CodeCompletionStringsTests.cpp + CollectMacrosTests.cpp ContextTests.cpp DexTests.cpp DiagnosticsTests.cpp diff --git a/clang-tools-extra/clangd/unittests/CollectMacrosTests.cpp b/clang-tools-extra/clangd/unittests/CollectMacrosTests.cpp new file mode 100644 index 000000000000..d4438e0a9a0b --- /dev/null +++ b/clang-tools-extra/clangd/unittests/CollectMacrosTests.cpp @@ -0,0 +1,109 @@ +//===-- CollectMacrosTests.cpp ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "Annotations.h" +#include "CollectMacros.h" +#include "Matchers.h" +#include "SourceCode.h" +#include "TestTU.h" +#include "index/SymbolID.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/Support/ScopedPrinter.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +using testing::UnorderedElementsAreArray; + +TEST(CollectMainFileMacros, SelectedMacros) { + // References of the same symbol must have the ranges with the same + // name(integer). If there are N diff erent symbols then they must be named + // from 1 to N. Macros for which SymbolID cannot be computed must be named + // "Unknown". + const char *Tests[] = { + R"cpp(// Macros: Cursor on definition. + #define $1[[FOO]](x,y) (x + y) + int main() { int x = $1[[FOO]]($1[[FOO]](3, 4), $1[[FOO]](5, 6)); } + )cpp", + R"cpp( + #define $1[[M]](X) X; + #define $2[[abc]] 123 + int s = $1[[M]]($2[[abc]]); + )cpp", + // FIXME: Locating macro in duplicate definitions doesn't work. Enable + // this once LocateMacro is fixed. + // R"cpp(// Multiple definitions. + // #define $1[[abc]] 1 + // int func1() { int a = $1[[abc]];} + // #undef $1[[abc]] + + // #define $2[[abc]] 2 + // int func2() { int a = $2[[abc]];} + // #undef $2[[abc]] + // )cpp", + R"cpp( + #ifdef $Unknown[[UNDEFINED]] + #endif + )cpp", + R"cpp( + #ifndef $Unknown[[abc]] + #define $1[[abc]] + #ifdef $1[[abc]] + #endif + #endif + )cpp", + R"cpp( + // Macros from token concatenations not included. + #define $1[[CONCAT]](X) X##A() + #define $2[[PREPEND]](X) MACRO##X() + #define $3[[MACROA]]() 123 + int B = $1[[CONCAT]](MACRO); + int D = $2[[PREPEND]](A) + )cpp", + R"cpp( + // FIXME: Macro names in a definition are not detected. + #define $1[[MACRO_ARGS2]](X, Y) X Y + #define $2[[FOO]] BAR + #define $3[[BAR]] 1 + int A = $2[[FOO]]; + )cpp"}; + for (const char *Test : Tests) { + Annotations T(Test); + auto AST = TestTU::withCode(T.code()).build(); + auto ActualMacroRefs = AST.getMacros(); + auto &SM = AST.getSourceManager(); + auto &PP = AST.getPreprocessor(); + + // Known macros. + for (int I = 1;; I++) { + const auto ExpectedRefs = T.ranges(llvm::to_string(I)); + if (ExpectedRefs.empty()) + break; + + auto Loc = getBeginningOfIdentifier(ExpectedRefs.begin()->start, SM, + AST.getASTContext().getLangOpts()); + auto Macro = locateMacroAt(Loc, PP); + assert(Macro); + auto SID = getSymbolID(Macro->Name, Macro->Info, SM); + + EXPECT_THAT(ExpectedRefs, + UnorderedElementsAreArray(ActualMacroRefs.MacroRefs[*SID])) + << "Annotation=" << I << ", MacroName=" << Macro->Name + << ", Test = " << Test; + } + // Unkown macros. + EXPECT_THAT(AST.getMacros().UnknownMacros, + UnorderedElementsAreArray(T.ranges("Unknown"))) + << "Unknown macros doesn't match in " << Test; + } +} +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp index 04a576769343..d7100980367d 100644 --- a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp +++ b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp @@ -260,6 +260,15 @@ TEST(ParsedASTTest, CollectsMainFileMacroExpansions) { // Includes macro expansions in arguments that are expressions ^assert(0 <= ^BAR); } + + #ifdef ^UNDEFINED + #endif + + #define ^MULTIPLE_DEFINITION 1 + #undef ^MULTIPLE_DEFINITION + + #define ^MULTIPLE_DEFINITION 2 + #undef ^MULTIPLE_DEFINITION )cpp"); auto TU = TestTU::withCode(TestCase.code()); TU.HeaderCode = R"cpp( @@ -274,7 +283,11 @@ TEST(ParsedASTTest, CollectsMainFileMacroExpansions) { )cpp"; ParsedAST AST = TU.build(); std::vector<Position> MacroExpansionPositions; - for (const auto &R : AST.getMacros().Ranges) + for (const auto &SIDToRefs : AST.getMacros().MacroRefs) { + for (const auto &R : SIDToRefs.second) + MacroExpansionPositions.push_back(R.start); + } + for (const auto &R : AST.getMacros().UnknownMacros) MacroExpansionPositions.push_back(R.start); EXPECT_THAT(MacroExpansionPositions, testing::UnorderedElementsAreArray(TestCase.points())); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits