// FIXME(nridge): Reduce duplication between this function and declToSym().
static llvm::Optional<TypeHierarchyItem>
-declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND,
- const syntax::TokenBuffer &TB) {
+declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) {
auto &SM = Ctx.getSourceManager();
SourceLocation NameLoc = nameLocation(ND, Ctx.getSourceManager());
+ SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
+ SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
+ const auto DeclRange =
+ toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc});
+ if (!DeclRange)
+ return llvm::None;
auto FilePath =
getCanonicalPath(SM.getFileEntryForID(SM.getFileID(NameLoc)), SM);
auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
if (!FilePath || !TUPath)
return llvm::None; // Not useful without a uri.
- auto DeclToks = TB.spelledForExpanded(TB.expandedTokens(ND.getSourceRange()));
- if (!DeclToks || DeclToks->empty())
- return llvm::None;
-
- auto NameToks = TB.spelledForExpanded(TB.expandedTokens(NameLoc));
- if (!NameToks || NameToks->empty())
- return llvm::None;
+ Position NameBegin = sourceLocToPosition(SM, NameLoc);
+ Position NameEnd = sourceLocToPosition(
+ SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
// FIXME: this is not classifying constructors, destructors and operators
THI.name = printName(Ctx, ND);
THI.kind = SK;
THI.deprecated = ND.isDeprecated();
- THI.range = halfOpenToRange(
- SM, syntax::Token::range(SM, DeclToks->front(), DeclToks->back())
- .toCharRange(SM));
- THI.selectionRange = halfOpenToRange(
- SM, syntax::Token::range(SM, NameToks->front(), NameToks->back())
- .toCharRange(SM));
+ THI.range = Range{sourceLocToPosition(SM, DeclRange->getBegin()),
+ sourceLocToPosition(SM, DeclRange->getEnd())};
+ THI.selectionRange = Range{NameBegin, NameEnd};
if (!THI.range.contains(THI.selectionRange)) {
// 'selectionRange' must be contained in 'range', so in cases where clang
// reports unrelated ranges we need to reconcile somehow.
static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx,
std::vector<TypeHierarchyItem> &SuperTypes,
- RecursionProtectionSet &RPSet,
- const syntax::TokenBuffer &TB) {
+ 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
for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) {
if (Optional<TypeHierarchyItem> ParentSym =
- declToTypeHierarchyItem(ASTCtx, *ParentDecl, TB)) {
+ declToTypeHierarchyItem(ASTCtx, *ParentDecl)) {
ParentSym->parents.emplace();
- fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet, TB);
+ fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet);
SuperTypes.emplace_back(std::move(*ParentSym));
}
}
return llvm::None;
Optional<TypeHierarchyItem> Result =
- declToTypeHierarchyItem(AST.getASTContext(), *CXXRD, AST.getTokens());
+ declToTypeHierarchyItem(AST.getASTContext(), *CXXRD);
if (!Result)
return Result;
Result->parents.emplace();
RecursionProtectionSet RPSet;
- fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet,
- AST.getTokens());
+ fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet);
}
if ((Direction == TypeHierarchyDirection::Children ||
WithKind(SymbolKind::Struct), Children()))));
}
+TEST(TypeHierarchy, Preamble) {
+ Annotations SourceAnnotations(R"cpp(
+struct Ch^ild : Parent {
+ int b;
+};)cpp");
+
+ Annotations HeaderInPreambleAnnotations(R"cpp(
+struct [[Parent]] {
+ int a;
+};)cpp");
+
+ TestTU TU = TestTU::withCode(SourceAnnotations.code());
+ TU.HeaderCode = HeaderInPreambleAnnotations.code().str();
+ auto AST = TU.build();
+
+ llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy(
+ AST, SourceAnnotations.point(), 1, TypeHierarchyDirection::Parents);
+
+ ASSERT_TRUE(Result);
+ EXPECT_THAT(
+ *Result,
+ AllOf(WithName("Child"),
+ Parents(AllOf(WithName("Parent"),
+ SelectionRangeIs(HeaderInPreambleAnnotations.range()),
+ Parents()))));
+}
+
SymbolID findSymbolIDByName(SymbolIndex *Index, llvm::StringRef Name,
llvm::StringRef TemplateArgs = "") {
SymbolID Result;