diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp --- 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 @@ // Usually empty, but sometimes children cover tokens but shouldn't own them. SourceRange earlySourceRange(const DynTypedNode &N) { if (const Decl *D = N.get()) { + // 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(D) || isa(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(D)) - return FD->getNameInfo().getSourceRange(); // int (*[[s]])(); - else if (auto *VD = llvm::dyn_cast(D)) - return VD->getLocation(); + // struct X { int [[hash]] [32]; [[operator]] int();} + if (const auto *DD = llvm::dyn_cast(D)) + return DD->getLocation(); } else if (const auto *CCI = N.get()) { // : [[b_]](42) return CCI->getMemberLocation(); diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -339,7 +339,7 @@ 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 @@ 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 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -375,6 +375,11 @@ 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);