Skip to content

Commit f693ce4

Browse files
committed
[clangd] Change ParseInputs to store FSProvider rather than VFS
Summary: This ensures ParseInputs provides a read-only access to FS. Reviewers: sammccall Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D81173
1 parent 3ebbe35 commit f693ce4

18 files changed

+148
-110
lines changed

clang-tools-extra/clangd/ClangdServer.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,18 +179,16 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
179179
void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
180180
llvm::StringRef Version,
181181
WantDiagnostics WantDiags, bool ForceRebuild) {
182-
auto FS = FSProvider.getFileSystem();
183-
184182
ParseOptions Opts;
185183
Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults();
186184
// FIXME: call tidy options builder on the worker thread, it can do IO.
187185
if (GetClangTidyOptions)
188-
Opts.ClangTidyOpts = GetClangTidyOptions(*FS, File);
186+
Opts.ClangTidyOpts = GetClangTidyOptions(*FSProvider.getFileSystem(), File);
189187
Opts.SuggestMissingIncludes = SuggestMissingIncludes;
190188

191189
// Compile command is set asynchronously during update, as it can be slow.
192190
ParseInputs Inputs;
193-
Inputs.FS = FS;
191+
Inputs.FSProvider = &FSProvider;
194192
Inputs.Contents = std::string(Contents);
195193
Inputs.Version = Version.str();
196194
Inputs.ForceRebuild = ForceRebuild;
@@ -214,8 +212,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
214212
if (!CodeCompleteOpts.Index) // Respect overridden index.
215213
CodeCompleteOpts.Index = Index;
216214

217-
auto Task = [Pos, FS = FSProvider.getFileSystem(), CodeCompleteOpts,
218-
File = File.str(), CB = std::move(CB),
215+
auto Task = [Pos, CodeCompleteOpts, File = File.str(), CB = std::move(CB),
219216
this](llvm::Expected<InputsAndPreamble> IP) mutable {
220217
if (!IP)
221218
return CB(IP.takeError());
@@ -238,7 +235,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
238235
}
239236
}
240237
}
241-
ParseInputs ParseInput{IP->Command, FS, IP->Contents.str()};
238+
ParseInputs ParseInput{IP->Command, &FSProvider, IP->Contents.str()};
242239
ParseInput.Index = Index;
243240
ParseInput.Opts.BuildRecoveryAST = BuildRecoveryAST;
244241
ParseInput.Opts.PreserveRecoveryASTType = PreserveRecoveryASTType;
@@ -275,8 +272,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
275272
void ClangdServer::signatureHelp(PathRef File, Position Pos,
276273
Callback<SignatureHelp> CB) {
277274

278-
auto Action = [Pos, FS = FSProvider.getFileSystem(), File = File.str(),
279-
CB = std::move(CB),
275+
auto Action = [Pos, File = File.str(), CB = std::move(CB),
280276
this](llvm::Expected<InputsAndPreamble> IP) mutable {
281277
if (!IP)
282278
return CB(IP.takeError());
@@ -286,7 +282,7 @@ void ClangdServer::signatureHelp(PathRef File, Position Pos,
286282
return CB(llvm::createStringError(llvm::inconvertibleErrorCode(),
287283
"Failed to parse includes"));
288284

289-
ParseInputs ParseInput{IP->Command, FS, IP->Contents.str()};
285+
ParseInputs ParseInput{IP->Command, &FSProvider, IP->Contents.str()};
290286
ParseInput.Index = Index;
291287
ParseInput.Opts.BuildRecoveryAST = BuildRecoveryAST;
292288
ParseInput.Opts.PreserveRecoveryASTType = PreserveRecoveryASTType;
@@ -399,8 +395,9 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
399395
return CB(Edits.takeError());
400396

401397
if (Opts.WantFormat) {
402-
auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
403-
InpAST->Inputs.FS.get());
398+
auto Style = getFormatStyleForFile(
399+
File, InpAST->Inputs.Contents,
400+
InpAST->Inputs.FSProvider->getFileSystem().get());
404401
llvm::Error Err = llvm::Error::success();
405402
for (auto &E : *Edits)
406403
Err =
@@ -600,8 +597,9 @@ void ClangdServer::findHover(PathRef File, Position Pos,
600597
this](llvm::Expected<InputsAndAST> InpAST) mutable {
601598
if (!InpAST)
602599
return CB(InpAST.takeError());
603-
format::FormatStyle Style = getFormatStyleForFile(
604-
File, InpAST->Inputs.Contents, InpAST->Inputs.FS.get());
600+
format::FormatStyle Style =
601+
getFormatStyleForFile(File, InpAST->Inputs.Contents,
602+
InpAST->Inputs.FSProvider->getFileSystem().get());
605603
CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
606604
};
607605

clang-tools-extra/clangd/CodeComplete.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "index/Index.h"
3737
#include "index/Symbol.h"
3838
#include "index/SymbolOrigin.h"
39+
#include "support/FSProvider.h"
3940
#include "support/Logger.h"
4041
#include "support/Threading.h"
4142
#include "support/Trace.h"
@@ -1060,9 +1061,6 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
10601061
const SemaCompleteInput &Input,
10611062
IncludeStructure *Includes = nullptr) {
10621063
trace::Span Tracer("Sema completion");
1063-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = Input.ParseInput.FS;
1064-
if (Input.Preamble.StatCache)
1065-
VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
10661064

10671065
IgnoreDiagnostics IgnoreDiags;
10681066
auto CI = buildCompilerInvocation(Input.ParseInput, IgnoreDiags);
@@ -1103,6 +1101,10 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
11031101
Input.Patch->apply(*CI);
11041102
// NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
11051103
// the remapped buffers do not get freed.
1104+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
1105+
Input.ParseInput.FSProvider->getFileSystem();
1106+
if (Input.Preamble.StatCache)
1107+
VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
11061108
auto Clang = prepareCompilerInstance(
11071109
std::move(CI), !CompletingInPreamble ? &Input.Preamble.Preamble : nullptr,
11081110
std::move(ContentsBuffer), std::move(VFS), IgnoreDiags);
@@ -1272,9 +1274,9 @@ class CodeCompleteFlow {
12721274
assert(Recorder && "Recorder is not set");
12731275
CCContextKind = Recorder->CCContext.getKind();
12741276
IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();
1275-
auto Style = getFormatStyleForFile(SemaCCInput.FileName,
1276-
SemaCCInput.ParseInput.Contents,
1277-
SemaCCInput.ParseInput.FS.get());
1277+
auto Style = getFormatStyleForFile(
1278+
SemaCCInput.FileName, SemaCCInput.ParseInput.Contents,
1279+
SemaCCInput.ParseInput.FSProvider->getFileSystem().get());
12781280
// If preprocessor was run, inclusions from preprocessor callback should
12791281
// already be added to Includes.
12801282
Inserter.emplace(
@@ -1759,8 +1761,9 @@ CodeCompleteResult codeComplete(PathRef FileName, Position Pos,
17591761
FileName, Preamble ? Preamble->Includes : IncludeStructure(),
17601762
SpecFuzzyFind, Opts);
17611763
return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)
1762-
? std::move(Flow).runWithoutSema(ParseInput.Contents, *Offset,
1763-
ParseInput.FS)
1764+
? std::move(Flow).runWithoutSema(
1765+
ParseInput.Contents, *Offset,
1766+
ParseInput.FSProvider->getFileSystem())
17641767
: std::move(Flow).run({FileName, *Offset, *Preamble,
17651768
// We want to serve code completions with
17661769
// low latency, so don't bother patching.

clang-tools-extra/clangd/Compiler.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D,
4747
for (const auto &S : Inputs.CompileCommand.CommandLine)
4848
ArgStrs.push_back(S.c_str());
4949

50-
if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
50+
auto VFS = Inputs.FSProvider->getFileSystem();
51+
if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
5152
log("Couldn't set working directory when creating compiler invocation.");
5253
// We proceed anyway, our lit-tests rely on results for non-existing working
5354
// dirs.
@@ -56,7 +57,7 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D,
5657
llvm::IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
5758
CompilerInstance::createDiagnostics(new DiagnosticOptions, &D, false);
5859
std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
59-
ArgStrs, CommandLineDiagsEngine, Inputs.FS,
60+
ArgStrs, CommandLineDiagsEngine, std::move(VFS),
6061
/*ShouldRecoverOnErrors=*/true, CC1Args);
6162
if (!CI)
6263
return nullptr;

clang-tools-extra/clangd/Compiler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "../clang-tidy/ClangTidyOptions.h"
1919
#include "GlobalCompilationDatabase.h"
2020
#include "index/Index.h"
21+
#include "support/FSProvider.h"
2122
#include "clang/Frontend/CompilerInstance.h"
2223
#include "clang/Frontend/PrecompiledPreamble.h"
2324
#include "clang/Tooling/CompilationDatabase.h"
@@ -45,7 +46,7 @@ struct ParseOptions {
4546
/// Information required to run clang, e.g. to parse AST or do code completion.
4647
struct ParseInputs {
4748
tooling::CompileCommand CompileCommand;
48-
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
49+
const FileSystemProvider *FSProvider;
4950
std::string Contents;
5051
// Version identifier for Contents, provided by the client and opaque to us.
5152
std::string Version = "null";

clang-tools-extra/clangd/ParsedAST.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
248248
trace::Span Tracer("BuildAST");
249249
SPAN_ATTACH(Tracer, "File", Filename);
250250

251-
auto VFS = Inputs.FS;
251+
auto VFS = Inputs.FSProvider->getFileSystem();
252252
if (Preamble && Preamble->StatCache)
253253
VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
254254
if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {

clang-tools-extra/clangd/Preamble.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "Compiler.h"
1111
#include "Headers.h"
1212
#include "SourceCode.h"
13+
#include "support/FSProvider.h"
1314
#include "support/Logger.h"
1415
#include "support/Trace.h"
1516
#include "clang/Basic/Diagnostic.h"
@@ -212,10 +213,29 @@ llvm::Expected<ScannedPreamble>
212213
scanPreamble(llvm::StringRef Contents,
213214
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
214215
const tooling::CompileCommand &Cmd) {
216+
// FIXME: Change PreambleStatCache to operate on FileSystemProvider rather
217+
// than vfs::FileSystem, that way we can just use ParseInputs without this
218+
// hack.
219+
auto GetFSProvider = [](llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
220+
class VFSProvider : public FileSystemProvider {
221+
public:
222+
VFSProvider(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
223+
: VFS(std::move(FS)) {}
224+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
225+
getFileSystem() const override {
226+
return VFS;
227+
}
228+
229+
private:
230+
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
231+
};
232+
return std::make_unique<VFSProvider>(std::move(FS));
233+
};
234+
auto FSProvider = GetFSProvider(std::move(VFS));
215235
// Build and run Preprocessor over the preamble.
216236
ParseInputs PI;
217237
PI.Contents = Contents.str();
218-
PI.FS = std::move(VFS);
238+
PI.FSProvider = FSProvider.get();
219239
PI.CompileCommand = Cmd;
220240
IgnoringDiagConsumer IgnoreDiags;
221241
auto CI = buildCompilerInvocation(PI, IgnoreDiags);
@@ -320,18 +340,19 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
320340
CI.getPreprocessorOpts().WriteCommentListToPCH = false;
321341

322342
CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
323-
if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
343+
auto VFS = Inputs.FSProvider->getFileSystem();
344+
if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
324345
log("Couldn't set working directory when building the preamble.");
325346
// We proceed anyway, our lit-tests rely on results for non-existing working
326347
// dirs.
327348
}
328349

329350
llvm::SmallString<32> AbsFileName(FileName);
330-
Inputs.FS->makeAbsolute(AbsFileName);
351+
VFS->makeAbsolute(AbsFileName);
331352
auto StatCache = std::make_unique<PreambleFileStatusCache>(AbsFileName);
332353
auto BuiltPreamble = PrecompiledPreamble::Build(
333354
CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
334-
StatCache->getProducingFS(Inputs.FS),
355+
StatCache->getProducingFS(VFS),
335356
std::make_shared<PCHContainerOperations>(), StoreInMemory,
336357
SerializedDeclsCollector);
337358

@@ -365,7 +386,7 @@ bool isPreambleCompatible(const PreambleData &Preamble,
365386
return compileCommandsAreEqual(Inputs.CompileCommand,
366387
Preamble.CompileCommand) &&
367388
Preamble.Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
368-
Inputs.FS.get());
389+
Inputs.FSProvider->getFileSystem().get());
369390
}
370391

371392
void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS) {
@@ -388,6 +409,8 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
388409
trace::Span Tracer("CreatePreamblePatch");
389410
SPAN_ATTACH(Tracer, "File", FileName);
390411
assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
412+
auto VFS =
413+
Baseline.StatCache->getConsumingFS(Modified.FSProvider->getFileSystem());
391414
// First scan preprocessor directives in Baseline and Modified. These will be
392415
// used to figure out newly added directives in Modified. Scanning can fail,
393416
// the code just bails out and creates an empty patch in such cases, as:
@@ -398,16 +421,14 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
398421
// there's nothing to do but generate an empty patch.
399422
auto BaselineScan = scanPreamble(
400423
// Contents needs to be null-terminated.
401-
Baseline.Preamble.getContents().str(),
402-
Baseline.StatCache->getConsumingFS(Modified.FS), Modified.CompileCommand);
424+
Baseline.Preamble.getContents().str(), VFS, Modified.CompileCommand);
403425
if (!BaselineScan) {
404426
elog("Failed to scan baseline of {0}: {1}", FileName,
405427
BaselineScan.takeError());
406428
return PreamblePatch::unmodified(Baseline);
407429
}
408-
auto ModifiedScan = scanPreamble(
409-
Modified.Contents, Baseline.StatCache->getConsumingFS(Modified.FS),
410-
Modified.CompileCommand);
430+
auto ModifiedScan =
431+
scanPreamble(Modified.Contents, std::move(VFS), Modified.CompileCommand);
411432
if (!ModifiedScan) {
412433
elog("Failed to scan modified contents of {0}: {1}", FileName,
413434
ModifiedScan.takeError());

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
245245
auto AbsolutePath = getAbsolutePath(Cmd);
246246

247247
auto FS = FSProvider.getFileSystem();
248+
FS->setCurrentWorkingDirectory(Cmd.Directory);
248249
auto Buf = FS->getBufferForFile(AbsolutePath);
249250
if (!Buf)
250251
return llvm::errorCodeToError(Buf.getError());
@@ -259,16 +260,17 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
259260

260261
vlog("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
261262
ParseInputs Inputs;
262-
Inputs.FS = std::move(FS);
263-
Inputs.FS->setCurrentWorkingDirectory(Cmd.Directory);
263+
Inputs.FSProvider = &FSProvider;
264264
Inputs.CompileCommand = std::move(Cmd);
265265
IgnoreDiagnostics IgnoreDiags;
266266
auto CI = buildCompilerInvocation(Inputs, IgnoreDiags);
267267
if (!CI)
268268
return llvm::createStringError(llvm::inconvertibleErrorCode(),
269269
"Couldn't build compiler invocation");
270-
auto Clang = prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
271-
std::move(*Buf), Inputs.FS, IgnoreDiags);
270+
271+
auto Clang =
272+
prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
273+
std::move(*Buf), std::move(FS), IgnoreDiags);
272274
if (!Clang)
273275
return llvm::createStringError(llvm::inconvertibleErrorCode(),
274276
"Couldn't build compiler instance");

clang-tools-extra/clangd/support/FSProvider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "llvm/ADT/IntrusiveRefCntPtr.h"
1313
#include "llvm/Support/VirtualFileSystem.h"
14+
#include <memory>
1415

1516
namespace clang {
1617
namespace clangd {

0 commit comments

Comments
 (0)