Skip to content

Commit 8ef7454

Browse files
feat: Support code nav for data members and globals (#131)
1 parent 0384339 commit 8ef7454

16 files changed

+233
-11
lines changed

indexer/Indexer.cc

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,25 @@ void TuIndexer::saveEnumTypeLoc(const clang::EnumTypeLoc &enumTypeLoc) {
297297
this->saveTagTypeLoc(enumTypeLoc);
298298
}
299299

300+
void TuIndexer::saveFieldDecl(const clang::FieldDecl &fieldDecl) {
301+
auto optSymbol = this->symbolFormatter.getFieldSymbol(fieldDecl);
302+
if (!optSymbol.has_value()) {
303+
return;
304+
}
305+
scip::SymbolInformation symbolInfo{};
306+
for (auto &docComment : this->tryGetDocComment(fieldDecl)) {
307+
*symbolInfo.add_documentation() = std::move(docComment.Text);
308+
}
309+
this->saveDefinition(optSymbol.value(), fieldDecl.getLocation(), symbolInfo);
310+
}
311+
312+
void TuIndexer::saveFieldReference(const clang::FieldDecl &fieldDecl,
313+
clang::SourceLocation loc) {
314+
if (auto optSymbol = this->symbolFormatter.getFieldSymbol(fieldDecl)) {
315+
this->saveReference(*optSymbol, loc);
316+
}
317+
}
318+
300319
void TuIndexer::saveFunctionDecl(const clang::FunctionDecl &functionDecl) {
301320
auto optSymbol = this->symbolFormatter.getFunctionSymbol(functionDecl);
302321
if (!optSymbol.has_value()) {
@@ -518,7 +537,18 @@ void TuIndexer::saveVarDecl(const clang::VarDecl &varDecl) {
518537
this->saveDefinition(optSymbol.value(), varDecl.getLocation(),
519538
std::nullopt);
520539
}
521-
// TODO: Add support for static and non-static data members.
540+
if (varDecl.isStaticDataMember() || varDecl.isFileVarDecl()) {
541+
// Non-static data members are handled by saveFieldDecl
542+
auto optSymbol = this->symbolFormatter.getVarSymbol(varDecl);
543+
if (!optSymbol.has_value()) {
544+
return;
545+
}
546+
scip::SymbolInformation symbolInfo{};
547+
for (auto &docComment : this->tryGetDocComment(varDecl)) {
548+
*symbolInfo.add_documentation() = std::move(docComment.Text);
549+
}
550+
this->saveDefinition(optSymbol.value(), varDecl.getLocation(), symbolInfo);
551+
}
522552
}
523553

524554
void TuIndexer::saveDeclRefExpr(const clang::DeclRefExpr &declRefExpr) {

indexer/Indexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ class TuIndexer final {
217217
FOR_EACH_DECL_TO_BE_INDEXED(SAVE_DECL)
218218
#undef SAVE_DECL
219219

220+
void saveFieldReference(const clang::FieldDecl &, clang::SourceLocation);
220221
void saveTagDecl(const clang::TagDecl &);
221222
void saveTagTypeLoc(const clang::TagTypeLoc &);
222223

indexer/SymbolFormatter.cc

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,25 @@ SymbolFormatter::getFunctionSymbol(const clang::FunctionDecl &functionDecl) {
395395
});
396396
}
397397

398+
std::optional<std::string_view>
399+
SymbolFormatter::getFieldSymbol(const clang::FieldDecl &fieldDecl) {
400+
if (fieldDecl.getDeclName().isEmpty()) {
401+
return {};
402+
}
403+
return this->getSymbolCached(fieldDecl, [&]() -> std::optional<std::string> {
404+
auto optContextSymbol = this->getContextSymbol(*fieldDecl.getDeclContext());
405+
if (!optContextSymbol.has_value()) {
406+
return {};
407+
}
408+
return SymbolBuilder::formatContextual(
409+
optContextSymbol.value(),
410+
DescriptorBuilder{
411+
.name = llvm_ext::toStringView(fieldDecl.getName()),
412+
.suffix = scip::Descriptor::Term,
413+
});
414+
});
415+
}
416+
398417
std::optional<std::string_view>
399418
SymbolFormatter::getNamedDeclSymbol(const clang::NamedDecl &namedDecl) {
400419
#define HANDLE(kind_) \
@@ -459,6 +478,9 @@ SymbolFormatter::getVarSymbol(const clang::VarDecl &varDecl) {
459478
if (varDecl.isLocalVarDeclOrParm()) {
460479
return this->getLocalVarOrParmSymbol(varDecl);
461480
}
481+
if (varDecl.getDeclName().isEmpty()) {
482+
return {};
483+
}
462484
return this->getSymbolCached(varDecl, [&]() -> std::optional<std::string> {
463485
using Kind = clang::Decl::Kind;
464486
// Based on
@@ -470,12 +492,20 @@ SymbolFormatter::getVarSymbol(const clang::VarDecl &varDecl) {
470492
" they should be handled in TuIndexer");
471493
case Kind::ParmVar:
472494
ENFORCE(false, "already handled parameter case earlier");
473-
// TODO: Add support for template specializations and OMP captured exprs.
474495
case Kind::VarTemplatePartialSpecialization:
475496
case Kind::VarTemplateSpecialization:
497+
case Kind::Var: {
498+
if (auto optContextSymbol =
499+
this->getContextSymbol(*varDecl.getDeclContext())) {
500+
auto descriptor = DescriptorBuilder{
501+
.name = llvm_ext::toStringView(varDecl.getName()),
502+
.suffix = scip::Descriptor::Term,
503+
};
504+
return SymbolBuilder::formatContextual(*optContextSymbol, descriptor);
505+
}
506+
return {};
507+
}
476508
case Kind::OMPCapturedExpr:
477-
case Kind::Var:
478-
// TODO: Add support for static and non-static data members
479509
return {};
480510
default: {
481511
spdlog::warn("unhandled kind {} of VarDecl: {}",

indexer/SymbolFormatter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
F(Binding) \
2121
F(EnumConstant) \
2222
F(Enum) \
23+
F(Field) \
2324
F(Function) \
2425
F(Namespace) \
2526
F(Record) \

indexer/Worker.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "spdlog/fmt/fmt.h"
2121
#include "spdlog/spdlog.h"
2222

23+
#include "clang/AST/DeclCXX.h"
2324
#include "clang/AST/RecursiveASTVisitor.h"
2425
#include "clang/AST/TypeLoc.h"
2526
#include "clang/Frontend/CompilerInstance.h"
@@ -732,6 +733,34 @@ class IndexerAstVisitor : public clang::RecursiveASTVisitor<IndexerAstVisitor> {
732733
return true;
733734
}
734735

736+
#define TRY_TO(CALL_EXPR) \
737+
do { \
738+
if (!this->getDerived().CALL_EXPR) \
739+
return false; \
740+
} while (false)
741+
742+
/// Replace the default implementation of the Traverse* method as there
743+
/// is no matching Visit* method, and the default implementation
744+
/// does not visit member field references.
745+
/// See https://github.com/llvm/llvm-project/issues/61602
746+
bool TraverseConstructorInitializer(
747+
const clang::CXXCtorInitializer *cxxCtorInitializer) {
748+
if (clang::TypeSourceInfo *TInfo =
749+
cxxCtorInitializer->getTypeSourceInfo()) {
750+
TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
751+
}
752+
if (clang::FieldDecl *fieldDecl = cxxCtorInitializer->getAnyMember()) {
753+
this->tuIndexer.saveFieldReference(
754+
*fieldDecl, cxxCtorInitializer->getSourceLocation());
755+
}
756+
if (cxxCtorInitializer->isWritten()
757+
|| this->getDerived().shouldVisitImplicitCode()) {
758+
TRY_TO(TraverseStmt(cxxCtorInitializer->getInit()));
759+
}
760+
return true;
761+
}
762+
#undef TRY_TO
763+
735764
void writeIndex(SymbolFormatter &&symbolFormatter, MacroIndexer &&macroIndex,
736765
scip::Index &scipIndex) {
737766
std::vector<std::pair<RootRelativePathRef, clang::FileID>> relativePaths;

test/index/functions/ctors_dtors.snapshot.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@
1818
struct C {
1919
// ^ definition [..] C#
2020
int x;
21+
// ^ definition [..] C#x.
2122
int y;
23+
// ^ definition [..] C#y.
2224
};
2325

2426
struct D {
2527
// ^ definition [..] D#
2628
int x;
29+
// ^ definition [..] D#x.
2730
int y;
31+
// ^ definition [..] D#y.
2832

2933
D() = default;
3034
// ^ definition [..] D#D(ced63f7c635d850d).

test/index/functions/operators.snapshot.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@
2020

2121
struct Int { int val; };
2222
// ^^^ definition [..] Int#
23+
// ^^^ definition [..] Int#val.
2324
struct IntPair { Int x; Int y; };
2425
// ^^^^^^^ definition [..] IntPair#
2526
// ^^^ reference [..] Int#
27+
// ^ definition [..] IntPair#x.
2628
// ^^^ reference [..] Int#
29+
// ^ definition [..] IntPair#y.
2730

2831
IntPair operator,(Int x, Int y) {
2932
//^^^^^^^ reference [..] IntPair#
@@ -46,6 +49,7 @@
4649
return Int{i.val+1};
4750
// ^^^ reference [..] Int#
4851
// ^ reference local 4
52+
// ^^^ reference [..] Int#val.
4953
}
5054

5155
struct FnLike {
@@ -57,21 +61,25 @@
5761
struct Table {
5862
// ^^^^^ definition [..] Table#
5963
int value;
64+
// ^^^^^ definition [..] Table#value.
6065
int &operator[](int i, int j) { // since C++23
6166
// ^^^^^^^^ definition [..] Table#`operator[]`(77cf9b7ed2f5124c).
6267
// ^ definition local 5
6368
// ^ definition local 6
6469
return this->value;
70+
// ^^^^^ reference [..] Table#value.
6571
}
6672
};
6773

6874
struct TablePtr {
6975
// ^^^^^^^^ definition [..] TablePtr#
7076
Table *t;
7177
// ^^^^^ reference [..] Table#
78+
// ^ definition [..] TablePtr#t.
7279
Table *operator->() { return t; }
7380
// ^^^^^ reference [..] Table#
7481
// ^^^^^^^^ definition [..] TablePtr#`operator->`(ed921902444779f1).
82+
// ^ reference [..] TablePtr#t.
7583
};
7684

7785
void test_overloaded_operators() {
@@ -97,6 +105,7 @@
97105
// ^ reference local 9
98106
p.x++;
99107
// ^ reference local 10
108+
// ^ reference [..] IntPair#x.
100109
// ^^ reference [..] operator++(be31e3af2b2ba0e).
101110

102111
FnLike()();
@@ -108,6 +117,7 @@
108117
TablePtr{}->value;
109118
// ^^^^^^^^ reference [..] TablePtr#
110119
// ^^ reference [..] TablePtr#`operator->`(ed921902444779f1).
120+
// ^^^^^ reference [..] Table#value.
111121
}
112122

113123
// User-defined conversion function

test/index/macros/macros.snapshot.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "macros.h"
44

55
int a = MY_MACRO + MY_MACRO_ALIAS;
6+
// ^ definition [..] a.
67
// ^^^^^^^^ reference [..] `macros.h:1:9`!
78
// ^^^^^^^^^^^^^^ reference [..] `macros.h:9:9`!
89

@@ -16,6 +17,7 @@
1617
// ^^^^^^^^ definition [..] `macros.cc:12:9`!
1718

1819
int b = MY_MACRO;
20+
// ^ definition [..] b.
1921
// ^^^^^^^^ reference [..] `macros.cc:12:9`!
2022

2123
#if defined(MY_MACRO)
@@ -44,6 +46,7 @@
4446
// ^^^^^^^^^^^^^^ definition [..] `macros.cc:32:9`!
4547

4648
int c = IDENTITY_MACRO(10);
49+
// ^ definition [..] c.
4750
// ^^^^^^^^^^^^^^ reference [..] `macros.cc:32:9`!
4851

4952
#define MACRO_USING_MACRO \
@@ -53,5 +56,6 @@
5356

5457
// two uses of a macro that expands to another macro
5558
int d = MACRO_USING_MACRO + MACRO_USING_MACRO;
59+
// ^ definition [..] d.
5660
// ^^^^^^^^^^^^^^^^^ reference [..] `macros.cc:36:9`!
5761
// ^^^^^^^^^^^^^^^^^ reference [..] `macros.cc:36:9`!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "system_header.h"
22

33
const int total = SYSTEM_INT + OTHER_SYSTEM_INT;
4+
// ^^^^^ definition [..] total.
45
// ^^^^^^^^^^ reference [..] `system_header.h:3:9`!
56
// ^^^^^^^^^^^^^^^^ reference [..] `system_header.h:5:9`!

test/index/types/bad_tagdecl.snapshot.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@
2626
template <class T>
2727
struct ShouldEnable { static bool const value = false; };
2828
// ^^^^^^^^^^^^ definition [..] ShouldEnable#
29+
// ^^^^^ definition [..] ShouldEnable#value.
2930

3031
struct MyTemplate<Undeclared, enable_if_t<ShouldEnable<int8_t>::value>> { };

0 commit comments

Comments
 (0)