Skip to content

Commit b764edc

Browse files
[clangd] Try harder to get accurate ranges for documentSymbols in macros
Fixes clangd/clangd#500 Differential Revision: https://reviews.llvm.org/D88463
1 parent 360ab00 commit b764edc

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

clang-tools-extra/clangd/FindSymbols.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,18 +171,13 @@ namespace {
171171
llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const NamedDecl &ND) {
172172
auto &SM = Ctx.getSourceManager();
173173

174-
SourceLocation NameLoc = nameLocation(ND, SM);
175174
SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
176175
SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
177176
const auto SymbolRange =
178177
toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc});
179178
if (!SymbolRange)
180179
return llvm::None;
181180

182-
Position NameBegin = sourceLocToPosition(SM, NameLoc);
183-
Position NameEnd = sourceLocToPosition(
184-
SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
185-
186181
index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
187182
// FIXME: this is not classifying constructors, destructors and operators
188183
// correctly (they're all "methods").
@@ -194,10 +189,35 @@ llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const NamedDecl &ND) {
194189
SI.deprecated = ND.isDeprecated();
195190
SI.range = Range{sourceLocToPosition(SM, SymbolRange->getBegin()),
196191
sourceLocToPosition(SM, SymbolRange->getEnd())};
197-
SI.selectionRange = Range{NameBegin, NameEnd};
192+
193+
SourceLocation NameLoc = ND.getLocation();
194+
SourceLocation FallbackNameLoc;
195+
if (NameLoc.isMacroID()) {
196+
if (isSpelledInSource(NameLoc, SM)) {
197+
// Prefer the spelling loc, but save the expansion loc as a fallback.
198+
FallbackNameLoc = SM.getExpansionLoc(NameLoc);
199+
NameLoc = SM.getSpellingLoc(NameLoc);
200+
} else {
201+
NameLoc = SM.getExpansionLoc(NameLoc);
202+
}
203+
}
204+
auto ComputeSelectionRange = [&](SourceLocation L) -> Range {
205+
Position NameBegin = sourceLocToPosition(SM, L);
206+
Position NameEnd = sourceLocToPosition(
207+
SM, Lexer::getLocForEndOfToken(L, 0, SM, Ctx.getLangOpts()));
208+
return Range{NameBegin, NameEnd};
209+
};
210+
211+
SI.selectionRange = ComputeSelectionRange(NameLoc);
212+
if (!SI.range.contains(SI.selectionRange) && FallbackNameLoc.isValid()) {
213+
// 'selectionRange' must be contained in 'range'. In cases where clang
214+
// reports unrelated ranges, we first try falling back to the expansion
215+
// loc for the selection range.
216+
SI.selectionRange = ComputeSelectionRange(FallbackNameLoc);
217+
}
198218
if (!SI.range.contains(SI.selectionRange)) {
199-
// 'selectionRange' must be contained in 'range', so in cases where clang
200-
// reports unrelated ranges we need to reconcile somehow.
219+
// If the containment relationship still doesn't hold, throw away
220+
// 'range' and use 'selectionRange' for both.
201221
SI.range = SI.selectionRange;
202222
}
203223
return SI;

clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -639,19 +639,27 @@ TEST(DocumentSymbols, FromMacro) {
639639
#define FF(name) \
640640
class name##_Test {};
641641
642-
$expansion[[FF]](abc);
642+
$expansion1[[FF]](abc);
643643
644644
#define FF2() \
645-
class $spelling[[Test]] {};
645+
class Test {};
646646
647-
FF2();
647+
$expansion2[[FF2]]();
648+
649+
#define FF3() \
650+
void waldo()
651+
652+
$fullDef[[FF3() {
653+
int var = 42;
654+
}]]
648655
)");
649656
TU.Code = Main.code().str();
650657
EXPECT_THAT(
651658
getSymbols(TU.build()),
652659
ElementsAre(
653-
AllOf(WithName("abc_Test"), SymNameRange(Main.range("expansion"))),
654-
AllOf(WithName("Test"), SymNameRange(Main.range("spelling")))));
660+
AllOf(WithName("abc_Test"), SymNameRange(Main.range("expansion1"))),
661+
AllOf(WithName("Test"), SymNameRange(Main.range("expansion2"))),
662+
AllOf(WithName("waldo"), SymRange(Main.range("fullDef")))));
655663
}
656664

657665
TEST(DocumentSymbols, FuncTemplates) {

0 commit comments

Comments
 (0)