[clangd] Adapt index interfaces to D45014, and fix the old bugs.
Summary: Fix bugs: - don't count occurrences of decls where we don't spell the name - findDefinitions at MACRO(^X) goes to the definition of MACRO Subscribers: klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits Differential Revision: https://reviews.llvm.org/D45356 llvm-svn: 329571
This commit is contained in:
parent
cc026ebf32
commit
b9d57118fb
|
@ -79,10 +79,10 @@ public:
|
||||||
|
|
||||||
bool
|
bool
|
||||||
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
|
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
|
||||||
ArrayRef<index::SymbolRelation> Relations, FileID FID,
|
ArrayRef<index::SymbolRelation> Relations,
|
||||||
unsigned Offset,
|
SourceLocation Loc,
|
||||||
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
|
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
|
||||||
if (isSearchedLocation(FID, Offset)) {
|
if (Loc == SearchedLocation) {
|
||||||
// Find and add definition declarations (for GoToDefinition).
|
// Find and add definition declarations (for GoToDefinition).
|
||||||
// We don't use parameter `D`, as Parameter `D` is the canonical
|
// We don't use parameter `D`, as Parameter `D` is the canonical
|
||||||
// declaration, which is the first declaration of a redeclarable
|
// declaration, which is the first declaration of a redeclarable
|
||||||
|
@ -98,18 +98,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isSearchedLocation(FileID FID, unsigned Offset) const {
|
|
||||||
const SourceManager &SourceMgr = AST.getSourceManager();
|
|
||||||
return SourceMgr.getFileOffset(SearchedLocation) == Offset &&
|
|
||||||
SourceMgr.getFileID(SearchedLocation) == FID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void finish() override {
|
void finish() override {
|
||||||
// Also handle possible macro at the searched location.
|
// Also handle possible macro at the searched location.
|
||||||
Token Result;
|
Token Result;
|
||||||
auto &Mgr = AST.getSourceManager();
|
auto &Mgr = AST.getSourceManager();
|
||||||
if (!Lexer::getRawToken(SearchedLocation, Result, Mgr, AST.getLangOpts(),
|
if (!Lexer::getRawToken(Mgr.getSpellingLoc(SearchedLocation), Result, Mgr,
|
||||||
false)) {
|
AST.getLangOpts(), false)) {
|
||||||
if (Result.is(tok::raw_identifier)) {
|
if (Result.is(tok::raw_identifier)) {
|
||||||
PP.LookUpIdentifierInfo(Result);
|
PP.LookUpIdentifierInfo(Result);
|
||||||
}
|
}
|
||||||
|
@ -127,16 +121,7 @@ private:
|
||||||
MacroInfo *MacroInf = MacroDef.getMacroInfo();
|
MacroInfo *MacroInf = MacroDef.getMacroInfo();
|
||||||
if (MacroInf) {
|
if (MacroInf) {
|
||||||
MacroInfos.push_back(MacroDecl{IdentifierInfo->getName(), MacroInf});
|
MacroInfos.push_back(MacroDecl{IdentifierInfo->getName(), MacroInf});
|
||||||
// Clear all collected delcarations if this is a macro search.
|
assert(Decls.empty());
|
||||||
//
|
|
||||||
// In theory, there should be no declarataions being collected when we
|
|
||||||
// search a source location that refers to a macro.
|
|
||||||
// The occurrence location returned by `handleDeclOccurence` is
|
|
||||||
// limited (FID, Offset are from expansion location), we will collect
|
|
||||||
// all declarations inside the macro.
|
|
||||||
//
|
|
||||||
// FIXME: Avoid adding decls from inside macros in handlDeclOccurence.
|
|
||||||
Decls.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,21 +237,19 @@ public:
|
||||||
|
|
||||||
bool
|
bool
|
||||||
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
|
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
|
||||||
ArrayRef<index::SymbolRelation> Relations, FileID FID,
|
ArrayRef<index::SymbolRelation> Relations,
|
||||||
unsigned Offset,
|
SourceLocation Loc,
|
||||||
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
|
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
|
||||||
const SourceManager &SourceMgr = AST.getSourceManager();
|
const SourceManager &SourceMgr = AST.getSourceManager();
|
||||||
if (SourceMgr.getMainFileID() != FID ||
|
SourceLocation HighlightStartLoc = SourceMgr.getFileLoc(Loc);
|
||||||
|
if (SourceMgr.getMainFileID() != SourceMgr.getFileID(HighlightStartLoc) ||
|
||||||
std::find(Decls.begin(), Decls.end(), D) == Decls.end()) {
|
std::find(Decls.begin(), Decls.end(), D) == Decls.end()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
SourceLocation End;
|
SourceLocation End;
|
||||||
const LangOptions &LangOpts = AST.getLangOpts();
|
const LangOptions &LangOpts = AST.getLangOpts();
|
||||||
SourceLocation StartOfFileLoc = SourceMgr.getLocForStartOfFile(FID);
|
End = Lexer::getLocForEndOfToken(HighlightStartLoc, 0, SourceMgr, LangOpts);
|
||||||
SourceLocation HightlightStartLoc = StartOfFileLoc.getLocWithOffset(Offset);
|
SourceRange SR(HighlightStartLoc, End);
|
||||||
End =
|
|
||||||
Lexer::getLocForEndOfToken(HightlightStartLoc, 0, SourceMgr, LangOpts);
|
|
||||||
SourceRange SR(HightlightStartLoc, End);
|
|
||||||
|
|
||||||
DocumentHighlightKind Kind = DocumentHighlightKind::Text;
|
DocumentHighlightKind Kind = DocumentHighlightKind::Text;
|
||||||
if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Write) & Roles)
|
if (static_cast<index::SymbolRoleSet>(index::SymbolRole::Write) & Roles)
|
||||||
|
|
|
@ -225,7 +225,7 @@ void SymbolCollector::initialize(ASTContext &Ctx) {
|
||||||
// Always return true to continue indexing.
|
// Always return true to continue indexing.
|
||||||
bool SymbolCollector::handleDeclOccurence(
|
bool SymbolCollector::handleDeclOccurence(
|
||||||
const Decl *D, index::SymbolRoleSet Roles,
|
const Decl *D, index::SymbolRoleSet Roles,
|
||||||
ArrayRef<index::SymbolRelation> Relations, FileID FID, unsigned Offset,
|
ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
|
||||||
index::IndexDataConsumer::ASTNodeInfo ASTNode) {
|
index::IndexDataConsumer::ASTNodeInfo ASTNode) {
|
||||||
assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
|
assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
|
||||||
assert(CompletionAllocator && CompletionTUInfo);
|
assert(CompletionAllocator && CompletionTUInfo);
|
||||||
|
@ -235,9 +235,10 @@ bool SymbolCollector::handleDeclOccurence(
|
||||||
|
|
||||||
// Mark D as referenced if this is a reference coming from the main file.
|
// Mark D as referenced if this is a reference coming from the main file.
|
||||||
// D may not be an interesting symbol, but it's cheaper to check at the end.
|
// D may not be an interesting symbol, but it's cheaper to check at the end.
|
||||||
|
auto &SM = ASTCtx->getSourceManager();
|
||||||
if (Opts.CountReferences &&
|
if (Opts.CountReferences &&
|
||||||
(Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
|
(Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
|
||||||
ASTCtx->getSourceManager().getMainFileID() == FID)
|
SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
|
||||||
ReferencedDecls.insert(ND);
|
ReferencedDecls.insert(ND);
|
||||||
|
|
||||||
// Don't continue indexing if this is a mere reference.
|
// Don't continue indexing if this is a mere reference.
|
||||||
|
|
|
@ -59,8 +59,8 @@ public:
|
||||||
|
|
||||||
bool
|
bool
|
||||||
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
|
handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
|
||||||
ArrayRef<index::SymbolRelation> Relations, FileID FID,
|
ArrayRef<index::SymbolRelation> Relations,
|
||||||
unsigned Offset,
|
SourceLocation Loc,
|
||||||
index::IndexDataConsumer::ASTNodeInfo ASTNode) override;
|
index::IndexDataConsumer::ASTNodeInfo ASTNode) override;
|
||||||
|
|
||||||
SymbolSlab takeSymbols() { return std::move(Symbols).build(); }
|
SymbolSlab takeSymbols() { return std::move(Symbols).build(); }
|
||||||
|
|
|
@ -250,6 +250,7 @@ TEST_F(SymbolCollectorTest, References) {
|
||||||
class Y;
|
class Y;
|
||||||
class Z {}; // not used anywhere
|
class Z {}; // not used anywhere
|
||||||
Y* y = nullptr; // used in header doesn't count
|
Y* y = nullptr; // used in header doesn't count
|
||||||
|
#define GLOBAL_Z(name) Z name;
|
||||||
)";
|
)";
|
||||||
const std::string Main = R"(
|
const std::string Main = R"(
|
||||||
W* w = nullptr;
|
W* w = nullptr;
|
||||||
|
@ -258,6 +259,7 @@ TEST_F(SymbolCollectorTest, References) {
|
||||||
class V;
|
class V;
|
||||||
V* v = nullptr; // Used, but not eligible for indexing.
|
V* v = nullptr; // Used, but not eligible for indexing.
|
||||||
class Y{}; // definition doesn't count as a reference
|
class Y{}; // definition doesn't count as a reference
|
||||||
|
GLOBAL_Z(z); // Not a reference to Z, we don't spell the type.
|
||||||
)";
|
)";
|
||||||
CollectorOpts.CountReferences = true;
|
CollectorOpts.CountReferences = true;
|
||||||
runSymbolCollector(Header, Main);
|
runSymbolCollector(Header, Main);
|
||||||
|
|
|
@ -222,6 +222,18 @@ TEST(GoToDefinition, All) {
|
||||||
}
|
}
|
||||||
)cpp",
|
)cpp",
|
||||||
|
|
||||||
|
R"cpp(// Macro argument
|
||||||
|
int [[i]];
|
||||||
|
#define ADDRESSOF(X) &X;
|
||||||
|
int *j = ADDRESSOF(^i);
|
||||||
|
)cpp",
|
||||||
|
|
||||||
|
R"cpp(// Symbol concatenated inside macro (not supported)
|
||||||
|
int *pi;
|
||||||
|
#define POINTER(X) p # X;
|
||||||
|
int i = *POINTER(^i);
|
||||||
|
)cpp",
|
||||||
|
|
||||||
R"cpp(// Forward class declaration
|
R"cpp(// Forward class declaration
|
||||||
class Foo;
|
class Foo;
|
||||||
class [[Foo]] {};
|
class [[Foo]] {};
|
||||||
|
@ -249,8 +261,11 @@ TEST(GoToDefinition, All) {
|
||||||
for (const char *Test : Tests) {
|
for (const char *Test : Tests) {
|
||||||
Annotations T(Test);
|
Annotations T(Test);
|
||||||
auto AST = build(T.code());
|
auto AST = build(T.code());
|
||||||
|
std::vector<Matcher<Location>> ExpectedLocations;
|
||||||
|
for (const auto &R : T.ranges())
|
||||||
|
ExpectedLocations.push_back(RangeIs(R));
|
||||||
EXPECT_THAT(findDefinitions(AST, T.point()),
|
EXPECT_THAT(findDefinitions(AST, T.point()),
|
||||||
ElementsAre(RangeIs(T.range())))
|
ElementsAreArray(ExpectedLocations))
|
||||||
<< Test;
|
<< Test;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue