usaxena95 updated this revision to Diff 228870.
usaxena95 added a comment.

Fixed typos.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70008/new/

https://reviews.llvm.org/D70008

Files:
  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/CollectMacrosTests.cpp
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -2050,6 +2050,32 @@
         } // namespace ns
         int main() { [[^ns]]::Foo foo; }
       )cpp",
+
+      R"cpp(// Macros
+        #define [[FOO]](x,y) (x + y)
+        // FIXME: No references for nested macros.
+        #define BAR(x,y,z) (FOO(x, y) * FOO(y, z))
+        int main() {
+          int x = [[FOO]](1, 2);
+          int y = [[FOO]]([[FO^O]](x, 1), [[FOO]](1, 1));
+          int z = BAR(1, 2, 3);
+        }
+        #define FOO(x) (x + 1)
+      )cpp",
+
+      R"cpp(// Macros: Cursor on definition.
+        #define [[F^OO]](x,y) (x + y)
+        int main() { int x = [[FOO]](1, 2); }
+      )cpp",
+
+      R"cpp( // Choose correct definiton in case of multiple definitions.
+        #define abc 1
+        #undef abc
+
+        #define [[abc]] 2
+        int main() { int a = [[abc]];}
+        #undef [[ab^c]]
+      )cpp",
   };
   for (const char *Test : Tests) {
     Annotations T(Test);
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -260,6 +260,15 @@
       // 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 @@
   )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()));
Index: clang-tools-extra/clangd/unittests/CollectMacrosTests.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clangd/unittests/CollectMacrosTests.cpp
@@ -0,0 +1,86 @@
+#include "Annotations.h"
+#include "CollectMacros.h"
+#include "Matchers.h"
+#include "TestTU.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using testing::UnorderedElementsAreArray;
+
+// Assumes that the ranges are named from 1 to N for some N.
+Matcher<std::vector<std::vector<Range>>>
+AreMacroRefsFrom(const Annotations &Test) {
+  std::vector<Matcher<std::vector<Range>>> Expected;
+  for (int I = 1;; I++) {
+    const auto Refs = Test.ranges(llvm::to_string(I));
+    if (Refs.empty())
+      break;
+    Expected.push_back(UnorderedElementsAreArray(Refs));
+  }
+  return UnorderedElementsAreArray(Expected);
+}
+
+std::vector<std::vector<Range>> collectKnownReferences(MainFileMacros M) {
+  std::vector<std::vector<Range>> Result;
+  for (const auto &SIDToRef : M.MacroRefs) {
+    Result.emplace_back(SIDToRef.second.begin(), SIDToRef.second.end());
+  }
+  return Result;
+}
+
+TEST(CollectMainFileMacros, SelectedMacros) {
+  // References of the same symbol must have the ranges with the same
+  // name(integer). If there are N different 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(// 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(
+        // 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();
+    EXPECT_THAT(AST.getMacros().UnknownMacros,
+                UnorderedElementsAreArray(T.ranges("Unknown")))
+        << Test;
+    EXPECT_THAT(collectKnownReferences(AST.getMacros()), AreMacroRefsFrom(T))
+        << Test;
+  }
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/CMakeLists.txt
===================================================================
--- clang-tools-extra/clangd/unittests/CMakeLists.txt
+++ clang-tools-extra/clangd/unittests/CMakeLists.txt
@@ -30,6 +30,7 @@
   ClangdTests.cpp
   CodeCompleteTests.cpp
   CodeCompletionStringsTests.cpp
+  CollectMacrosTests.cpp
   ContextTests.cpp
   DexTests.cpp
   DiagnosticsTests.cpp
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -21,6 +21,7 @@
 #include "index/Merge.h"
 #include "index/Relation.h"
 #include "index/SymbolCollector.h"
+#include "index/SymbolID.h"
 #include "index/SymbolLocation.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
@@ -47,6 +48,7 @@
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
+#include <set>
 
 namespace clang {
 namespace clangd {
@@ -891,7 +893,28 @@
   }
   auto Loc = SM.getMacroArgExpandedLocation(
       getBeginningOfIdentifier(Pos, SM, AST.getASTContext().getLangOpts()));
-  // TODO: should we handle macros, too?
+
+  // Handle macros.
+  if (auto Macro = locateMacroAt(Loc, AST.getPreprocessor())) {
+    if (auto MacroSID = getSymbolID(Macro->Name, Macro->Info, SM)) {
+      const auto &IDToRefs = AST.getMacros().MacroRefs;
+      auto Refs = IDToRefs.find(*MacroSID);
+      if (Refs != IDToRefs.end()) {
+        auto URIMainFile =
+            URIForFile::canonicalize(*MainFilePath, *MainFilePath);
+        for (const auto Ref : Refs->second) {
+          Location Loc;
+          Loc.uri = URIMainFile;
+          Loc.range = Ref;
+          Results.push_back(Loc);
+        }
+      }
+    }
+    if (Results.size() > Limit)
+      Results.resize(Limit);
+    return Results;
+  }
+
   // We also show references to the targets of using-decls, so we include
   // DeclRelation::Underlying.
   DeclRelationSet Relations = DeclRelation::TemplatePattern |
@@ -911,8 +934,7 @@
                      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);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -312,8 +312,13 @@
       Builder.addToken(R.NameLoc, *Kind);
   });
   // Add highlightings for macro expansions.
-  for (const auto &M : AST.getMacros().Ranges)
+  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();
 }
 
Index: clang-tools-extra/clangd/CollectMacros.h
===================================================================
--- clang-tools-extra/clangd/CollectMacros.h
+++ 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 @@
   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::set<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.
@@ -81,7 +88,11 @@
 
     if (auto Range = getTokenRange(SM, LangOpts, Loc)) {
       Out.Names.insert(MacroNameTok.getIdentifierInfo()->getName());
-      Out.Ranges.push_back(*Range);
+      if (auto SID =
+               getSymbolID(MacroNameTok.getIdentifierInfo()->getName(), MI, SM))
+        Out.MacroRefs[*SID].insert(*Range);
+      else
+        Out.UnknownMacros.push_back(*Range);
     }
   }
   const SourceManager &SM;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to