[PATCH] D84012: [clangd] Exclude preprocessed-to-nothing tokens from selectionThis prevents selection of empty preprocessor entities (like #define directives,or text in disabled sections) creating a selection in the parent element.

Sam McCall via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 17 03:16:54 PDT 2020


sammccall created this revision.
sammccall added reviewers: ArcsinX, kadircet.
Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous, MaskRay, ilya-biryukov.
Herald added a project: clang.

Based on D83508 <https://reviews.llvm.org/D83508> by Aleksandr Platonov.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D84012

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/unittests/SelectionTests.cpp


Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -182,6 +182,14 @@
           )cpp",
           nullptr,
       },
+      {
+          R"cpp(
+            void foo();
+            #define CALL_FUNCTION(X) X()
+            void bar() { CALL_FUNCTION(foo^)^; }
+          )cpp",
+          nullptr,
+      },
       {
           R"cpp(
             struct S { S(const char*); };
@@ -388,7 +396,8 @@
         void test(S2 s2) {
           s2[[-^>]]f();
         }
-      )cpp", "DeclRefExpr"} // DeclRefExpr to the "operator->" method.
+      )cpp",
+       "DeclRefExpr"} // DeclRefExpr to the "operator->" method.
   };
   for (const Case &C : Cases) {
     trace::TestTracer Tracer;
@@ -538,7 +547,33 @@
   auto AST = TU.build();
   auto T = makeSelectionTree(Case, AST);
 
-  EXPECT_EQ("WhileStmt", T.commonAncestor()->kind());
+  EXPECT_EQ(nullptr, T.commonAncestor());
+}
+
+TEST(SelectionTest, DisabledPreprocessor) {
+  const char *Case = R"cpp(
+    namespace ns {
+    #define FOO B^AR
+    }
+  )cpp";
+  Annotations Test(Case);
+  auto TU = TestTU::withCode(Test.code());
+  auto AST = TU.build();
+  auto T = makeSelectionTree(Case, AST);
+  EXPECT_EQ(T.commonAncestor(), nullptr);
+
+  Case = R"cpp(
+    namespace ns {
+    #if 0
+    void fu^nc();
+    #endif
+    }
+  )cpp";
+  Test = Annotations(Case);
+  TU = TestTU::withCode(Test.code());
+  AST = TU.build();
+  T = makeSelectionTree(Case, AST);
+  EXPECT_EQ(T.commonAncestor(), nullptr);
 }
 
 TEST(SelectionTest, MacroArgExpansion) {
Index: clang-tools-extra/clangd/Selection.cpp
===================================================================
--- clang-tools-extra/clangd/Selection.cpp
+++ clang-tools-extra/clangd/Selection.cpp
@@ -220,14 +220,26 @@
         SelFirst, AllSpelledTokens.end(), [&](const syntax::Token &Tok) {
           return SM.getFileOffset(Tok.location()) < SelEnd;
         });
+    auto Sel = llvm::makeArrayRef(SelFirst, SelLimit);
+    // Find which of these are preprocessed to nothing and should be ignored.
+    std::vector<bool> PPIgnored(Sel.size(), false);
+    for (const syntax::TokenBuffer::Expansion &X :
+         Buf.expansionsAffecting(Sel)) {
+      if (X.Expanded.empty()) {
+        for (const syntax::Token &Tok : X.Spelled) {
+          if (&Tok >= SelFirst && &Tok < SelLimit)
+            PPIgnored[&Tok - SelFirst] = true;
+        }
+      }
+    }
     // Precompute selectedness and offset for selected spelled tokens.
-    for (const syntax::Token *T = SelFirst; T < SelLimit; ++T) {
-      if (shouldIgnore(*T))
+    for (unsigned I = 0; I < Sel.size(); ++I) {
+      if (shouldIgnore(Sel[I]) || PPIgnored[I])
         continue;
       SpelledTokens.emplace_back();
       Tok &S = SpelledTokens.back();
-      S.Offset = SM.getFileOffset(T->location());
-      if (S.Offset >= SelBegin && S.Offset + T->length() <= SelEnd)
+      S.Offset = SM.getFileOffset(Sel[I].location());
+      if (S.Offset >= SelBegin && S.Offset + Sel[I].length() <= SelEnd)
         S.Selected = SelectionTree::Complete;
       else
         S.Selected = SelectionTree::Partial;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D84012.278706.patch
Type: text/x-patch
Size: 3284 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200717/8c8a0544/attachment-0001.bin>


More information about the cfe-commits mailing list