[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:
Sam McCall 2018-04-09 14:28:52 +00:00
parent cc026ebf32
commit b9d57118fb
5 changed files with 35 additions and 34 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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(); }

View File

@ -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);

View File

@ -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;
} }
} }