Skip to content

Commit e09754c

Browse files
committed
[clangd] Migrate Lexer usages in TypeHierarchy to TokenBuffers
Summary: Also fixes a bug, resulting from directly using ND.getEndLoc() for end location of the range. As ND.getEndLoc() points to the begining of the last token, whereas it should point one past the end, since LSP ranges are half open (exclusive on the end). Reviewers: sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D74850
1 parent dc383f0 commit e09754c

File tree

2 files changed

+30
-28
lines changed

2 files changed

+30
-28
lines changed

clang-tools-extra/clangd/XRefs.cpp

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
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().
595596
static 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

686686
static 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 ||

clang-tools-extra/clangd/test/type-hierarchy.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
# CHECK-NEXT: "parents": [],
4949
# CHECK-NEXT: "range": {
5050
# CHECK-NEXT: "end": {
51-
# CHECK-NEXT: "character": 15,
51+
# CHECK-NEXT: "character": 16,
5252
# CHECK-NEXT: "line": 0
5353
# CHECK-NEXT: },
5454
# CHECK-NEXT: "start": {
@@ -71,7 +71,7 @@
7171
# CHECK-NEXT: ],
7272
# CHECK-NEXT: "range": {
7373
# CHECK-NEXT: "end": {
74-
# CHECK-NEXT: "character": 24,
74+
# CHECK-NEXT: "character": 25,
7575
# CHECK-NEXT: "line": 1
7676
# CHECK-NEXT: },
7777
# CHECK-NEXT: "start": {
@@ -94,7 +94,7 @@
9494
# CHECK-NEXT: ],
9595
# CHECK-NEXT: "range": {
9696
# CHECK-NEXT: "end": {
97-
# CHECK-NEXT: "character": 24,
97+
# CHECK-NEXT: "character": 25,
9898
# CHECK-NEXT: "line": 2
9999
# CHECK-NEXT: },
100100
# CHECK-NEXT: "start": {

0 commit comments

Comments
 (0)