Skip to content

Commit 451a889

Browse files
[clangd] Store documentation when indexing standard library
Fixes clangd/clangd#2344
1 parent fff8f03 commit 451a889

File tree

6 files changed

+73
-31
lines changed

6 files changed

+73
-31
lines changed

clang-tools-extra/clangd/ClangdServer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ class ClangdServer {
466466
[[nodiscard]] bool
467467
blockUntilIdleForTest(std::optional<double> TimeoutSeconds = 10);
468468

469+
// Expose the (combined) index for test use.
470+
const SymbolIndex *getIndexForTest() { return Index; }
471+
469472
/// Builds a nested representation of memory used by components.
470473
void profile(MemoryTree &MT) const;
471474

clang-tools-extra/clangd/index/FileIndex.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,12 @@ SlabTuple indexSymbols(ASTContext &AST, Preprocessor &PP,
4848
const MainFileMacros *MacroRefsToIndex,
4949
const include_cleaner::PragmaIncludes &PI,
5050
bool IsIndexMainAST, llvm::StringRef Version,
51-
bool CollectMainFileRefs) {
51+
bool CollectMainFileRefs, SymbolOrigin Origin) {
5252
SymbolCollector::Options CollectorOpts;
5353
CollectorOpts.CollectIncludePath = true;
5454
CollectorOpts.PragmaIncludes = &PI;
5555
CollectorOpts.CountReferences = false;
56-
CollectorOpts.Origin =
57-
IsIndexMainAST ? SymbolOrigin::Open : SymbolOrigin::Preamble;
56+
CollectorOpts.Origin = Origin;
5857
CollectorOpts.CollectMainFileRefs = CollectMainFileRefs;
5958
// We want stdlib implementation details in the index only if we've opened the
6059
// file in question. This does means xrefs won't work, though.
@@ -221,22 +220,24 @@ FileShardedIndex::getShard(llvm::StringRef Uri) const {
221220
}
222221

223222
SlabTuple indexMainDecls(ParsedAST &AST) {
224-
return indexSymbols(
225-
AST.getASTContext(), AST.getPreprocessor(), AST.getLocalTopLevelDecls(),
226-
&AST.getMacros(), AST.getPragmaIncludes(),
227-
/*IsIndexMainAST=*/true, AST.version(), /*CollectMainFileRefs=*/true);
223+
return indexSymbols(AST.getASTContext(), AST.getPreprocessor(),
224+
AST.getLocalTopLevelDecls(), &AST.getMacros(),
225+
AST.getPragmaIncludes(),
226+
/*IsIndexMainAST=*/true, AST.version(),
227+
/*CollectMainFileRefs=*/true, SymbolOrigin::Open);
228228
}
229229

230230
SlabTuple indexHeaderSymbols(llvm::StringRef Version, ASTContext &AST,
231231
Preprocessor &PP,
232-
const include_cleaner::PragmaIncludes &PI) {
232+
const include_cleaner::PragmaIncludes &PI,
233+
SymbolOrigin Origin) {
233234
std::vector<Decl *> DeclsToIndex(
234235
AST.getTranslationUnitDecl()->decls().begin(),
235236
AST.getTranslationUnitDecl()->decls().end());
236237
return indexSymbols(AST, PP, DeclsToIndex,
237238
/*MainFileMacros=*/nullptr, PI,
238239
/*IsIndexMainAST=*/false, Version,
239-
/*CollectMainFileRefs=*/false);
240+
/*CollectMainFileRefs=*/false, Origin);
240241
}
241242

242243
FileSymbols::FileSymbols(IndexContents IdxContents, bool SupportContainedRefs)
@@ -463,7 +464,7 @@ void FileIndex::updatePreamble(PathRef Path, llvm::StringRef Version,
463464
const include_cleaner::PragmaIncludes &PI) {
464465
IndexFileIn IF;
465466
std::tie(IF.Symbols, std::ignore, IF.Relations) =
466-
indexHeaderSymbols(Version, AST, PP, PI);
467+
indexHeaderSymbols(Version, AST, PP, PI, SymbolOrigin::Preamble);
467468
updatePreamble(std::move(IF));
468469
}
469470

clang-tools-extra/clangd/index/FileIndex.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ SlabTuple indexMainDecls(ParsedAST &AST);
164164
/// included headers.
165165
SlabTuple indexHeaderSymbols(llvm::StringRef Version, ASTContext &AST,
166166
Preprocessor &PP,
167-
const include_cleaner::PragmaIncludes &PI);
167+
const include_cleaner::PragmaIncludes &PI,
168+
SymbolOrigin Origin);
168169

169170
/// Takes slabs coming from a TU (multiple files) and shards them per
170171
/// declaration location.

clang-tools-extra/clangd/index/StdLib.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@
1515
#include "Compiler.h"
1616
#include "Config.h"
1717
#include "SymbolCollector.h"
18+
#include "clang-include-cleaner/Record.h"
19+
#include "index/FileIndex.h"
1820
#include "index/IndexAction.h"
1921
#include "support/Logger.h"
2022
#include "support/ThreadsafeFS.h"
2123
#include "support/Trace.h"
2224
#include "clang/Basic/LangOptions.h"
2325
#include "clang/Frontend/CompilerInvocation.h"
26+
#include "clang/Frontend/FrontendActions.h"
2427
#include "clang/Lex/PreprocessorOptions.h"
2528
#include "clang/Tooling/Inclusions/StandardLibrary.h"
2629
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -223,33 +226,29 @@ SymbolSlab indexStandardLibrary(llvm::StringRef HeaderSources,
223226
return Symbols;
224227
}
225228

226-
SymbolCollector::Options IndexOpts;
227-
IndexOpts.Origin = SymbolOrigin::StdLib;
228-
IndexOpts.CollectMainFileSymbols = false;
229-
IndexOpts.CollectMainFileRefs = false;
230-
IndexOpts.CollectMacro = true;
231-
IndexOpts.StoreAllDocumentation = true;
232-
// Sadly we can't use IndexOpts.FileFilter to restrict indexing scope.
233-
// Files from outside the StdLibLocation may define true std symbols anyway.
234-
// We end up "blessing" such headers, and can only do that by indexing
235-
// everything first.
236-
237-
// Refs, relations, include graph in the stdlib mostly aren't useful.
238-
auto Action = createStaticIndexingAction(
239-
IndexOpts, [&](SymbolSlab S) { Symbols = std::move(S); }, nullptr,
240-
nullptr, nullptr);
241-
242-
if (!Action->BeginSourceFile(*Clang, Input)) {
229+
SyntaxOnlyAction Action;
230+
231+
if (!Action.BeginSourceFile(*Clang, Input)) {
243232
elog("Standard Library Index: BeginSourceFile() failed");
244233
return Symbols;
245234
}
246235

247-
if (llvm::Error Err = Action->Execute()) {
236+
if (llvm::Error Err = Action.Execute()) {
248237
elog("Standard Library Index: Execute failed: {0}", std::move(Err));
249238
return Symbols;
250239
}
251240

252-
Action->EndSourceFile();
241+
// We don't care about include graph for stdlib headers, so provide a no-op
242+
// PI.
243+
include_cleaner::PragmaIncludes PI;
244+
auto Slabs =
245+
indexHeaderSymbols("", Clang->getASTContext(), Clang->getPreprocessor(),
246+
PI, SymbolOrigin::StdLib);
247+
Symbols = std::move(std::get<0>(Slabs));
248+
249+
// Run EndSourceFile() after indexing completes, so ensure the AST and
250+
// preprocessor state is alive during indexing.
251+
Action.EndSourceFile();
253252

254253
unsigned SymbolsBeforeFilter = Symbols.size();
255254
Symbols = filter(std::move(Symbols), Loc);

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "Config.h"
1414
#include "SyncAPI.h"
1515
#include "TestFS.h"
16+
#include "index/Index.h"
1617
#include "index/StdLib.h"
1718
#include "clang/Basic/LangOptions.h"
1819
#include "clang/Basic/SourceManager.h"
@@ -158,6 +159,42 @@ TEST(StdLibTests, EndToEnd) {
158159
UnorderedElementsAre(StdlibSymbol("list"), StdlibSymbol("vector")));
159160
}
160161

162+
TEST(StdLibTests, StdLibDocComments) {
163+
Config Cfg;
164+
Cfg.Index.StandardLibrary = true;
165+
WithContextValue Enabled(Config::Key, std::move(Cfg));
166+
167+
MockFS FS;
168+
FS.Files["stdlib/vector"] = R"cpp(
169+
namespace std {
170+
struct vector {
171+
/**doc comment*/
172+
struct inner {};
173+
};
174+
}
175+
)cpp";
176+
MockCompilationDatabase CDB;
177+
CDB.ExtraClangFlags.push_back("-isystem" + testPath("stdlib"));
178+
ClangdServer::Options Opts = ClangdServer::optsForTest();
179+
Opts.BuildDynamicSymbolIndex = true; // also used for stdlib index
180+
ClangdServer Server(CDB, FS, Opts);
181+
182+
// Open an empty file. <vector> will not be part of the preamble index,
183+
// but it will be part of the stdlib index.
184+
Server.addDocument(testPath("foo.cc"), "");
185+
186+
// Wait for the stdlib index to be built.
187+
ASSERT_TRUE(Server.blockUntilIdleForTest());
188+
189+
// Check that the index contains the doc comment.
190+
FuzzyFindRequest Req;
191+
Req.Query = "inner";
192+
Req.Scopes = {"std::vector::"};
193+
SymbolSlab Result = runFuzzyFind(*Server.getIndexForTest(), Req);
194+
ASSERT_EQ(Result.size(), 1u);
195+
EXPECT_EQ(Result.begin()->Documentation, "doc comment");
196+
}
197+
161198
} // namespace
162199
} // namespace clangd
163200
} // namespace clang

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "Diagnostics.h"
1313
#include "TestFS.h"
1414
#include "index/FileIndex.h"
15+
#include "index/SymbolOrigin.h"
1516
#include "clang/AST/RecursiveASTVisitor.h"
1617
#include "clang/Basic/Diagnostic.h"
1718
#include "clang/Frontend/CompilerInvocation.h"
@@ -164,7 +165,7 @@ SymbolSlab TestTU::headerSymbols() const {
164165
auto AST = build();
165166
return std::get<0>(indexHeaderSymbols(
166167
/*Version=*/"null", AST.getASTContext(), AST.getPreprocessor(),
167-
AST.getPragmaIncludes()));
168+
AST.getPragmaIncludes(), SymbolOrigin::Preamble));
168169
}
169170

170171
RefSlab TestTU::headerRefs() const {

0 commit comments

Comments
 (0)