[clangd] Don't navigate to forward class declaration when go to definition.

Summary:
For some cases, GoToDefinition will navigate to the forward class
declaration, we should always navigate to the class definition.

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: klimek, ilya-biryukov, cfe-commits

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

llvm-svn: 322370
This commit is contained in:
Haojian Wu 2018-01-12 14:21:10 +00:00
parent 70bfe66111
commit f4374f087f
2 changed files with 38 additions and 2 deletions

View File

@ -14,6 +14,20 @@ namespace clangd {
using namespace llvm; using namespace llvm;
namespace { namespace {
// Get the definition from a given declaration `D`.
// Return nullptr if no definition is found, or the declaration type of `D` is
// not supported.
const Decl* GetDefinition(const Decl* D) {
assert(D);
if (const auto *TD = dyn_cast<TagDecl>(D))
return TD->getDefinition();
else if (const auto *VD = dyn_cast<VarDecl>(D))
return VD->getDefinition();
else if (const auto *FD = dyn_cast<FunctionDecl>(D))
return FD->getDefinition();
return nullptr;
}
/// Finds declarations locations that a given source location refers to. /// Finds declarations locations that a given source location refers to.
class DeclarationAndMacrosFinder : public index::IndexDataConsumer { class DeclarationAndMacrosFinder : public index::IndexDataConsumer {
std::vector<const Decl *> Decls; std::vector<const Decl *> Decls;
@ -50,8 +64,18 @@ public:
ArrayRef<index::SymbolRelation> Relations, FileID FID, ArrayRef<index::SymbolRelation> Relations, FileID FID,
unsigned Offset, unsigned Offset,
index::IndexDataConsumer::ASTNodeInfo ASTNode) override { index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
if (isSearchedLocation(FID, Offset)) if (isSearchedLocation(FID, Offset)) {
Decls.push_back(D); // Find and add definition declarations (for GoToDefinition).
// We don't use parameter `D`, as Parameter `D` is the canonical
// declaration, which is the first declaration of a redeclarable
// declaration, and it could be a forward declaration.
if (const auto* Def = GetDefinition(D)) {
Decls.push_back(Def);
} else {
// Couldn't find a definition, fall back to use `D`.
Decls.push_back(D);
}
}
return true; return true;
} }

View File

@ -203,6 +203,18 @@ TEST(GoToDefinition, All) {
#define MACRO 2 #define MACRO 2
#undef macro #undef macro
)cpp", )cpp",
R"cpp(// Forward class declaration
class Foo;
[[class Foo {}]];
F^oo* foo();
)cpp",
R"cpp(// Function declaration
void foo();
void g() { f^oo(); }
[[void foo() {}]]
)cpp",
}; };
for (const char *Test : Tests) { for (const char *Test : Tests) {
Annotations T(Test); Annotations T(Test);