[clang-tools-extra] 4bc085f - [clangd] Add OverridenBy Relation to index.
Utkarsh Saxena via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 17 22:11:28 PST 2020
Author: Utkarsh Saxena
Date: 2020-11-18T06:59:49+01:00
New Revision: 4bc085f5b3eda5273721fd787ffa65e2f155fc45
URL: https://github.com/llvm/llvm-project/commit/4bc085f5b3eda5273721fd787ffa65e2f155fc45
DIFF: https://github.com/llvm/llvm-project/commit/4bc085f5b3eda5273721fd787ffa65e2f155fc45.diff
LOG: [clangd] Add OverridenBy Relation to index.
This was previously explored in reviews.llvm.org/D69094.
Differential Revision: https://reviews.llvm.org/D91610
Added:
Modified:
clang-tools-extra/clangd/index/Relation.cpp
clang-tools-extra/clangd/index/Relation.h
clang-tools-extra/clangd/index/Serialization.cpp
clang-tools-extra/clangd/index/SymbolCollector.cpp
clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp
clang-tools-extra/clangd/test/index-serialization/Inputs/sample.h
clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/index/Relation.cpp b/clang-tools-extra/clangd/index/Relation.cpp
index 6daa10a6f95e..2e5ae33939b0 100644
--- a/clang-tools-extra/clangd/index/Relation.cpp
+++ b/clang-tools-extra/clangd/index/Relation.cpp
@@ -13,6 +13,20 @@
namespace clang {
namespace clangd {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const RelationKind R) {
+ switch (R) {
+ case RelationKind::BaseOf:
+ return OS << "BaseOf";
+ case RelationKind::OverriddenBy:
+ return OS << "OverriddenBy";
+ }
+ llvm_unreachable("Unhandled RelationKind enum.");
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Relation &R) {
+ return OS << R.Subject << " " << R.Predicate << " " << R.Object;
+}
+
llvm::iterator_range<RelationSlab::iterator>
RelationSlab::lookup(const SymbolID &Subject, RelationKind Predicate) const {
auto IterPair = std::equal_range(Relations.begin(), Relations.end(),
diff --git a/clang-tools-extra/clangd/index/Relation.h b/clang-tools-extra/clangd/index/Relation.h
index 363000019e70..b0326ac6eae0 100644
--- a/clang-tools-extra/clangd/index/Relation.h
+++ b/clang-tools-extra/clangd/index/Relation.h
@@ -21,11 +21,16 @@ namespace clangd {
enum class RelationKind : uint8_t {
BaseOf,
+ OverriddenBy,
};
/// Represents a relation between two symbols.
-/// For an example "A is a base class of B" may be represented
-/// as { Subject = A, Predicate = BaseOf, Object = B }.
+/// For an example:
+/// - "A is a base class of B" is represented as
+/// { Subject = A, Predicate = BaseOf, Object = B }.
+/// - "Derived::Foo overrides Base::Foo" is represented as
+/// { Subject = Base::Foo, Predicate = OverriddenBy, Object = Derived::Foo
+/// }.
struct Relation {
SymbolID Subject;
RelationKind Predicate;
@@ -41,6 +46,8 @@ struct Relation {
std::tie(Other.Subject, Other.Predicate, Other.Object);
}
};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const RelationKind R);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Relation &R);
class RelationSlab {
public:
diff --git a/clang-tools-extra/clangd/index/Serialization.cpp b/clang-tools-extra/clangd/index/Serialization.cpp
index 8b0ae3925a2f..5d48edf81343 100644
--- a/clang-tools-extra/clangd/index/Serialization.cpp
+++ b/clang-tools-extra/clangd/index/Serialization.cpp
@@ -443,7 +443,7 @@ readCompileCommand(Reader CmdReader, llvm::ArrayRef<llvm::StringRef> Strings) {
// The current versioning scheme is simple - non-current versions are rejected.
// If you make a breaking change, bump this version number to invalidate stored
// data. Later we may want to support some backward compatibility.
-constexpr static uint32_t Version = 14;
+constexpr static uint32_t Version = 15;
llvm::Expected<IndexFileIn> readRIFF(llvm::StringRef Data) {
auto RIFF = riff::readFile(Data);
diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp
index a7a6bd992f8b..94ab54be54b0 100644
--- a/clang-tools-extra/clangd/index/SymbolCollector.cpp
+++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -15,6 +15,7 @@
#include "SourceCode.h"
#include "SymbolLocation.h"
#include "URI.h"
+#include "index/Relation.h"
#include "index/SymbolID.h"
#include "support/Logger.h"
#include "clang/AST/Decl.h"
@@ -187,9 +188,12 @@ RefKind toRefKind(index::SymbolRoleSet Roles, bool Spelled = false) {
return Result;
}
-bool shouldIndexRelation(const index::SymbolRelation &R) {
- // We currently only index BaseOf relations, for type hierarchy subtypes.
- return R.Roles & static_cast<unsigned>(index::SymbolRole::RelationBaseOf);
+llvm::Optional<RelationKind> indexableRelation(const index::SymbolRelation &R) {
+ if (R.Roles & static_cast<unsigned>(index::SymbolRole::RelationBaseOf))
+ return RelationKind::BaseOf;
+ if (R.Roles & static_cast<unsigned>(index::SymbolRole::RelationOverrideOf))
+ return RelationKind::OverriddenBy;
+ return None;
}
} // namespace
@@ -486,14 +490,10 @@ bool SymbolCollector::handleMacroOccurrence(const IdentifierInfo *Name,
void SymbolCollector::processRelations(
const NamedDecl &ND, const SymbolID &ID,
ArrayRef<index::SymbolRelation> Relations) {
- // Store subtype relations.
- if (!dyn_cast<TagDecl>(&ND))
- return;
-
for (const auto &R : Relations) {
- if (!shouldIndexRelation(R))
+ auto RKind = indexableRelation(R);
+ if (!RKind)
continue;
-
const Decl *Object = R.RelatedSymbol;
auto ObjectID = getSymbolID(Object);
@@ -509,7 +509,10 @@ void SymbolCollector::processRelations(
// in the index and find nothing, but that's a situation they
// probably need to handle for other reasons anyways.
// We currently do (B) because it's simpler.
- this->Relations.insert(Relation{ID, RelationKind::BaseOf, ObjectID});
+ if (*RKind == RelationKind::BaseOf)
+ this->Relations.insert({ID, *RKind, ObjectID});
+ else if (*RKind == RelationKind::OverriddenBy)
+ this->Relations.insert({ObjectID, *RKind, ID});
}
}
diff --git a/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp b/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp
index 7fe4e80f0477..f9f13b930d62 100644
--- a/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp
+++ b/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp
@@ -2,4 +2,7 @@
#include "sample.h"
// This introduces a symbol, a reference and a relation.
-struct Bar : public Foo {};
+struct Bar : public Foo {
+ // This introduces an OverriddenBy relation by implementing Foo::Func.
+ void Func() override {}
+};
diff --git a/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.h b/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.h
index 7cf73b9c43ab..ef57ae7f025a 100644
--- a/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.h
+++ b/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.h
@@ -1,4 +1,6 @@
#pragma once
// Introduce a symbol.
-struct Foo {};
+struct Foo {
+ virtual void Func() {}
+};
diff --git a/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx b/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
index 5ecb294f3191..11ee69bd2dd2 100644
Binary files a/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx and b/clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
diff er
diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index d0c4dd4497fa..93ed33eeb6b0 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -97,6 +97,9 @@ MATCHER(RefRange, "") {
const Range &Range = ::testing::get<1>(arg);
return rangesMatch(Pos.Location, Range);
}
+MATCHER_P2(OverriddenBy, Subject, Object, "") {
+ return arg == Relation{Subject.ID, RelationKind::OverriddenBy, Object.ID};
+}
::testing::Matcher<const std::vector<Ref> &>
HaveRanges(const std::vector<Range> Ranges) {
return ::testing::UnorderedPointwise(RefRange(), Ranges);
@@ -1031,7 +1034,7 @@ TEST_F(SymbolCollectorTest, RefsInHeaders) {
HaveRanges(Header.ranges("macro")))));
}
-TEST_F(SymbolCollectorTest, Relations) {
+TEST_F(SymbolCollectorTest, BaseOfRelations) {
std::string Header = R"(
class Base {};
class Derived : public Base {};
@@ -1043,6 +1046,77 @@ TEST_F(SymbolCollectorTest, Relations) {
Contains(Relation{Base.ID, RelationKind::BaseOf, Derived.ID}));
}
+TEST_F(SymbolCollectorTest, OverrideRelationsSimpleInheritance) {
+ std::string Header = R"cpp(
+ class A {
+ virtual void foo();
+ };
+ class B : public A {
+ void foo() override; // A::foo
+ virtual void bar();
+ };
+ class C : public B {
+ void bar() override; // B::bar
+ };
+ class D: public C {
+ void foo() override; // B::foo
+ void bar() override; // C::bar
+ };
+ )cpp";
+ runSymbolCollector(Header, /*Main=*/"");
+ const Symbol &AFoo = findSymbol(Symbols, "A::foo");
+ const Symbol &BFoo = findSymbol(Symbols, "B::foo");
+ const Symbol &DFoo = findSymbol(Symbols, "D::foo");
+
+ const Symbol &BBar = findSymbol(Symbols, "B::bar");
+ const Symbol &CBar = findSymbol(Symbols, "C::bar");
+ const Symbol &DBar = findSymbol(Symbols, "D::bar");
+
+ std::vector<Relation> Result;
+ for (const Relation &R : Relations)
+ if (R.Predicate == RelationKind::OverriddenBy)
+ Result.push_back(R);
+ EXPECT_THAT(Result, UnorderedElementsAre(
+ OverriddenBy(AFoo, BFoo), OverriddenBy(BBar, CBar),
+ OverriddenBy(BFoo, DFoo), OverriddenBy(CBar, DBar)));
+}
+
+TEST_F(SymbolCollectorTest, OverrideRelationsMultipleInheritance) {
+ std::string Header = R"cpp(
+ class A {
+ virtual void foo();
+ };
+ class B {
+ virtual void bar();
+ };
+ class C : public B {
+ void bar() override; // B::bar
+ virtual void baz();
+ }
+ class D : public A, C {
+ void foo() override; // A::foo
+ void bar() override; // C::bar
+ void baz() override; // C::baz
+ };
+ )cpp";
+ runSymbolCollector(Header, /*Main=*/"");
+ const Symbol &AFoo = findSymbol(Symbols, "A::foo");
+ const Symbol &BBar = findSymbol(Symbols, "B::bar");
+ const Symbol &CBar = findSymbol(Symbols, "C::bar");
+ const Symbol &CBaz = findSymbol(Symbols, "C::baz");
+ const Symbol &DFoo = findSymbol(Symbols, "D::foo");
+ const Symbol &DBar = findSymbol(Symbols, "D::bar");
+ const Symbol &DBaz = findSymbol(Symbols, "D::baz");
+
+ std::vector<Relation> Result;
+ for (const Relation &R : Relations)
+ if (R.Predicate == RelationKind::OverriddenBy)
+ Result.push_back(R);
+ EXPECT_THAT(Result, UnorderedElementsAre(
+ OverriddenBy(BBar, CBar), OverriddenBy(AFoo, DFoo),
+ OverriddenBy(CBar, DBar), OverriddenBy(CBaz, DBaz)));
+}
+
TEST_F(SymbolCollectorTest, CountReferences) {
const std::string Header = R"(
class W;
More information about the cfe-commits
mailing list