3636#include " clang/Index/IndexingAction.h"
3737#include " clang/Index/IndexingOptions.h"
3838#include " clang/Index/USRGeneration.h"
39+ #include " clang/Tooling/Syntax/Tokens.h"
3940#include " llvm/ADT/ArrayRef.h"
4041#include " llvm/ADT/None.h"
4142#include " llvm/ADT/STLExtras.h"
@@ -593,22 +594,23 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) {
593594
594595// FIXME(nridge): Reduce duplication between this function and declToSym().
595596static llvm::Optional<TypeHierarchyItem>
596- declToTypeHierarchyItem (ASTContext &Ctx, const NamedDecl &ND) {
597+ declToTypeHierarchyItem (ASTContext &Ctx, const NamedDecl &ND,
598+ const syntax::TokenBuffer &TB) {
597599 auto &SM = Ctx.getSourceManager ();
598-
599600 SourceLocation NameLoc = nameLocation (ND, Ctx.getSourceManager ());
600- // getFileLoc is a good choice for us, but we also need to make sure
601- // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of
602- // that to make sure it does not switch files.
603- // FIXME: sourceLocToPosition should not switch files!
604- SourceLocation BeginLoc = SM.getSpellingLoc (SM.getFileLoc (ND.getBeginLoc ()));
605- SourceLocation EndLoc = SM.getSpellingLoc (SM.getFileLoc (ND.getEndLoc ()));
606- if (NameLoc.isInvalid () || BeginLoc.isInvalid () || EndLoc.isInvalid ())
601+ auto FilePath =
602+ getCanonicalPath (SM.getFileEntryForID (SM.getFileID (NameLoc)), SM);
603+ auto TUPath = getCanonicalPath (SM.getFileEntryForID (SM.getMainFileID ()), SM);
604+ if (!FilePath || !TUPath)
605+ return llvm::None; // Not useful without a uri.
606+
607+ auto DeclToks = TB.spelledForExpanded (TB.expandedTokens (ND.getSourceRange ()));
608+ if (!DeclToks || DeclToks->empty ())
607609 return llvm::None;
608610
609- Position NameBegin = sourceLocToPosition (SM, NameLoc);
610- Position NameEnd = sourceLocToPosition (
611- SM, Lexer::getLocForEndOfToken (NameLoc, 0 , SM, Ctx. getLangOpts ())) ;
611+ auto NameToks = TB. spelledForExpanded (TB. expandedTokens ( NameLoc) );
612+ if (!NameToks || NameToks-> empty ())
613+ return llvm::None ;
612614
613615 index::SymbolInfo SymInfo = index::getSymbolInfo (&ND);
614616 // FIXME: this is not classifying constructors, destructors and operators
@@ -619,20 +621,18 @@ declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) {
619621 THI.name = printName (Ctx, ND);
620622 THI.kind = SK;
621623 THI.deprecated = ND.isDeprecated ();
622- THI.range =
623- Range{sourceLocToPosition (SM, BeginLoc), sourceLocToPosition (SM, EndLoc)};
624- THI.selectionRange = Range{NameBegin, NameEnd};
624+ THI.range = halfOpenToRange (
625+ SM, syntax::Token::range (SM, DeclToks->front (), DeclToks->back ())
626+ .toCharRange (SM));
627+ THI.selectionRange = halfOpenToRange (
628+ SM, syntax::Token::range (SM, NameToks->front (), NameToks->back ())
629+ .toCharRange (SM));
625630 if (!THI.range .contains (THI.selectionRange )) {
626631 // 'selectionRange' must be contained in 'range', so in cases where clang
627632 // reports unrelated ranges we need to reconcile somehow.
628633 THI.range = THI.selectionRange ;
629634 }
630635
631- auto FilePath =
632- getCanonicalPath (SM.getFileEntryForID (SM.getFileID (BeginLoc)), SM);
633- auto TUPath = getCanonicalPath (SM.getFileEntryForID (SM.getMainFileID ()), SM);
634- if (!FilePath || !TUPath)
635- return llvm::None; // Not useful without a uri.
636636 THI.uri = URIForFile::canonicalize (*FilePath, *TUPath);
637637
638638 return THI;
@@ -685,7 +685,8 @@ using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>;
685685
686686static void fillSuperTypes (const CXXRecordDecl &CXXRD, ASTContext &ASTCtx,
687687 std::vector<TypeHierarchyItem> &SuperTypes,
688- RecursionProtectionSet &RPSet) {
688+ RecursionProtectionSet &RPSet,
689+ const syntax::TokenBuffer &TB) {
689690 // typeParents() will replace dependent template specializations
690691 // with their class template, so to avoid infinite recursion for
691692 // certain types of hierarchies, keep the templates encountered
@@ -700,9 +701,9 @@ static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx,
700701
701702 for (const CXXRecordDecl *ParentDecl : typeParents (&CXXRD)) {
702703 if (Optional<TypeHierarchyItem> ParentSym =
703- declToTypeHierarchyItem (ASTCtx, *ParentDecl)) {
704+ declToTypeHierarchyItem (ASTCtx, *ParentDecl, TB )) {
704705 ParentSym->parents .emplace ();
705- fillSuperTypes (*ParentDecl, ASTCtx, *ParentSym->parents , RPSet);
706+ fillSuperTypes (*ParentDecl, ASTCtx, *ParentSym->parents , RPSet, TB );
706707 SuperTypes.emplace_back (std::move (*ParentSym));
707708 }
708709 }
@@ -805,7 +806,7 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
805806 return llvm::None;
806807
807808 Optional<TypeHierarchyItem> Result =
808- declToTypeHierarchyItem (AST.getASTContext (), *CXXRD);
809+ declToTypeHierarchyItem (AST.getASTContext (), *CXXRD, AST. getTokens () );
809810 if (!Result)
810811 return Result;
811812
@@ -814,7 +815,8 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
814815 Result->parents .emplace ();
815816
816817 RecursionProtectionSet RPSet;
817- fillSuperTypes (*CXXRD, AST.getASTContext (), *Result->parents , RPSet);
818+ fillSuperTypes (*CXXRD, AST.getASTContext (), *Result->parents , RPSet,
819+ AST.getTokens ());
818820 }
819821
820822 if ((Direction == TypeHierarchyDirection::Children ||
0 commit comments