[clang-tools-extra] e6b8181 - [clangd] Fix early selection for non-vardecl declarators

Kadir Cetinkaya via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 4 02:01:48 PST 2020


Author: Kadir Cetinkaya
Date: 2020-03-04T11:01:35+01:00
New Revision: e6b8181895b96740dbe54aca036aa237e0a8363d

URL: https://github.com/llvm/llvm-project/commit/e6b8181895b96740dbe54aca036aa237e0a8363d
DIFF: https://github.com/llvm/llvm-project/commit/e6b8181895b96740dbe54aca036aa237e0a8363d.diff

LOG: [clangd] Fix early selection for non-vardecl declarators

Summary:
Selection tree was performing an early claim only for VarDecls, but
there are other cases where we can have declarators, e.g. FieldDecls. This patch
extends the early claim logic to all types of declarators.

Fixes https://github.com/clangd/clangd/issues/292

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D75106

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp
index db96357083f6..b4565446c8ec 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -10,6 +10,7 @@
 #include "Logger.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -634,12 +635,22 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
   // Usually empty, but sometimes children cover tokens but shouldn't own them.
   SourceRange earlySourceRange(const DynTypedNode &N) {
     if (const Decl *D = N.get<Decl>()) {
+      // We want constructor name to be claimed by TypeLoc not the constructor
+      // itself. Similar for deduction guides, we rather want to select the
+      // underlying TypeLoc.
+      // FIXME: Unfortunately this doesn't work, even though RecursiveASTVisitor
+      // traverses the underlying TypeLoc inside DeclarationName, it is null for
+      // constructors.
+      if (isa<CXXConstructorDecl>(D) || isa<CXXDeductionGuideDecl>(D))
+        return SourceRange();
+      // This will capture Field, Function, MSProperty, NonTypeTemplateParm and
+      // VarDecls. We want the name in the declarator to be claimed by the decl
+      // and not by any children. For example:
       // void [[foo]]();
-      if (auto *FD = llvm::dyn_cast<FunctionDecl>(D))
-        return FD->getNameInfo().getSourceRange();
       // int (*[[s]])();
-      else if (auto *VD = llvm::dyn_cast<VarDecl>(D))
-        return VD->getLocation();
+      // struct X { int [[hash]] [32]; [[operator]] int();}
+      if (const auto *DD = llvm::dyn_cast<DeclaratorDecl>(D))
+        return DD->getLocation();
     } else if (const auto *CCI = N.get<CXXCtorInitializer>()) {
       // : [[b_]](42)
       return CCI->getMemberLocation();

diff  --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index e4de8af93e9e..51f8eac1bfb4 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -339,7 +339,7 @@ class Foo {})cpp";
          HI.Definition = "~X()";
          HI.Parameters.emplace();
        }},
-      {"class X { operator [[in^t]](); };",
+      {"class X { [[op^erator]] int(); };",
        [](HoverInfo &HI) {
          HI.NamespaceScope = "";
          HI.Name = "operator int";
@@ -348,6 +348,13 @@ class Foo {})cpp";
          HI.Definition = "operator int()";
          HI.Parameters.emplace();
        }},
+      {"class X { operator [[^X]](); };",
+       [](HoverInfo &HI) {
+         HI.NamespaceScope = "";
+         HI.Name = "X";
+         HI.Kind = index::SymbolKind::Class;
+         HI.Definition = "class X {}";
+       }},
 
       // auto on lambda
       {R"cpp(

diff  --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
index 781a04942fb4..7316dea42bd2 100644
--- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -375,6 +375,11 @@ TEST(SelectionTest, CommonAncestor) {
             int test(I *f) { return 42 + [[f.^foo]]; }
           )cpp",
           "ObjCPropertyRefExpr"},
+      {"struct foo { [[int has^h<:32:>]]; };", "FieldDecl"},
+      {"struct foo { [[op^erator int()]]; };", "CXXConversionDecl"},
+      {"struct foo { [[^~foo()]]; };", "CXXDestructorDecl"},
+      // FIXME: The following to should be class itself instead.
+      {"struct foo { [[fo^o(){}]] };", "CXXConstructorDecl"},
   };
   for (const Case &C : Cases) {
     Annotations Test(C.Code);


        


More information about the cfe-commits mailing list