diff options
-rw-r--r-- | clang-tools-extra/clangd/XRefs.cpp | 33 | ||||
-rw-r--r-- | clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp | 3 |
2 files changed, 19 insertions, 17 deletions
diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 59f07ee405e..6339f8643f7 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -1132,15 +1132,9 @@ static void fillSubTypes(const SymbolID &ID, using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>; -static Optional<TypeHierarchyItem> -getTypeAncestors(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, - RecursionProtectionSet &RPSet) { - Optional<TypeHierarchyItem> Result = declToTypeHierarchyItem(ASTCtx, CXXRD); - if (!Result) - return Result; - - Result->parents.emplace(); - +static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, + std::vector<TypeHierarchyItem> &SuperTypes, + RecursionProtectionSet &RPSet) { // typeParents() will replace dependent template specializations // with their class template, so to avoid infinite recursion for // certain types of hierarchies, keep the templates encountered @@ -1149,22 +1143,22 @@ getTypeAncestors(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr; if (Pattern) { if (!RPSet.insert(Pattern).second) { - return Result; + return; } } for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) { if (Optional<TypeHierarchyItem> ParentSym = - getTypeAncestors(*ParentDecl, ASTCtx, RPSet)) { - Result->parents->emplace_back(std::move(*ParentSym)); + declToTypeHierarchyItem(ASTCtx, *ParentDecl)) { + ParentSym->parents.emplace(); + fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet); + SuperTypes.emplace_back(std::move(*ParentSym)); } } if (Pattern) { RPSet.erase(Pattern); } - - return Result; } const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { @@ -1231,12 +1225,19 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, if (!CXXRD) return llvm::None; - RecursionProtectionSet RPSet; Optional<TypeHierarchyItem> Result = - getTypeAncestors(*CXXRD, AST.getASTContext(), RPSet); + declToTypeHierarchyItem(AST.getASTContext(), *CXXRD); if (!Result) return Result; + if (Direction == TypeHierarchyDirection::Parents || + Direction == TypeHierarchyDirection::Both) { + Result->parents.emplace(); + + RecursionProtectionSet RPSet; + fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet); + } + if ((Direction == TypeHierarchyDirection::Children || Direction == TypeHierarchyDirection::Both) && ResolveLevels > 0) { diff --git a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp index 633a25fe3b4..cebfa8dfbeb 100644 --- a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp +++ b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp @@ -630,7 +630,8 @@ struct Child2b : Child1 {}; ASSERT_TRUE(bool(Result)); EXPECT_THAT( *Result, - AllOf(WithName("Parent"), WithKind(SymbolKind::Struct), Parents(), + AllOf(WithName("Parent"), WithKind(SymbolKind::Struct), + ParentsNotResolved(), Children(AllOf(WithName("Child1"), WithKind(SymbolKind::Struct), ParentsNotResolved(), ChildrenNotResolved())))); |