#include "clang/Index/IndexingAction.h"
#include "clang/Index/IndexingOptions.h"
#include "clang/Index/USRGeneration.h"
+#include "clang/Tooling/Syntax/Tokens.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
// FIXME(nridge): Reduce duplication between this function and declToSym().
static llvm::Optional<TypeHierarchyItem>
-declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) {
+declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND,
+ const syntax::TokenBuffer &TB) {
auto &SM = Ctx.getSourceManager();
-
SourceLocation NameLoc = nameLocation(ND, Ctx.getSourceManager());
- // getFileLoc is a good choice for us, but we also need to make sure
- // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of
- // that to make sure it does not switch files.
- // FIXME: sourceLocToPosition should not switch files!
- SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
- SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
- if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid())
+ 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;
- Position NameBegin = sourceLocToPosition(SM, NameLoc);
- Position NameEnd = sourceLocToPosition(
- SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
+ auto NameToks = TB.spelledForExpanded(TB.expandedTokens(NameLoc));
+ if (!NameToks || NameToks->empty())
+ return llvm::None;
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 =
- Range{sourceLocToPosition(SM, BeginLoc), sourceLocToPosition(SM, EndLoc)};
- THI.selectionRange = Range{NameBegin, NameEnd};
+ 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));
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.
THI.range = THI.selectionRange;
}
- auto FilePath =
- getCanonicalPath(SM.getFileEntryForID(SM.getFileID(BeginLoc)), SM);
- auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
- if (!FilePath || !TUPath)
- return llvm::None; // Not useful without a uri.
THI.uri = URIForFile::canonicalize(*FilePath, *TUPath);
return THI;
static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx,
std::vector<TypeHierarchyItem> &SuperTypes,
- RecursionProtectionSet &RPSet) {
+ RecursionProtectionSet &RPSet,
+ const syntax::TokenBuffer &TB) {
// 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)) {
+ declToTypeHierarchyItem(ASTCtx, *ParentDecl, TB)) {
ParentSym->parents.emplace();
- fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet);
+ fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet, TB);
SuperTypes.emplace_back(std::move(*ParentSym));
}
}
return llvm::None;
Optional<TypeHierarchyItem> Result =
- declToTypeHierarchyItem(AST.getASTContext(), *CXXRD);
+ declToTypeHierarchyItem(AST.getASTContext(), *CXXRD, AST.getTokens());
if (!Result)
return Result;
Result->parents.emplace();
RecursionProtectionSet RPSet;
- fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet);
+ fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet,
+ AST.getTokens());
}
if ((Direction == TypeHierarchyDirection::Children ||