[clangd] Change FSProvider::getFileSystem to take CurrentWorkingDirectory
Summary:
We've faced a couple of problems when the returned FS didn't have the
proper working directory. New signature makes the API safer against such
problems.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D81920
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index 3539de0..2007f92 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -183,7 +183,8 @@
Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults();
// FIXME: call tidy options builder on the worker thread, it can do IO.
if (GetClangTidyOptions)
- Opts.ClangTidyOpts = GetClangTidyOptions(*FSProvider.getFileSystem(), File);
+ Opts.ClangTidyOpts = GetClangTidyOptions(
+ *FSProvider.getFileSystem(/*CWD=*/llvm::None), File);
Opts.SuggestMissingIncludes = SuggestMissingIncludes;
// Compile command is set asynchronously during update, as it can be slow.
@@ -317,9 +318,9 @@
llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
if (!CursorPos)
return CursorPos.takeError();
- auto FS = FSProvider.getFileSystem();
- auto Style = format::getStyle(format::DefaultFormatStyle, File,
- format::DefaultFallbackStyle, Code, FS.get());
+ auto Style = format::getStyle(
+ format::DefaultFormatStyle, File, format::DefaultFallbackStyle, Code,
+ FSProvider.getFileSystem(/*CWD=*/llvm::None).get());
if (!Style)
return Style.takeError();
@@ -395,9 +396,8 @@
return CB(Edits.takeError());
if (Opts.WantFormat) {
- auto Style = getFormatStyleForFile(
- File, InpAST->Inputs.Contents,
- InpAST->Inputs.FSProvider->getFileSystem().get());
+ auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
+ *InpAST->Inputs.FSProvider);
llvm::Error Err = llvm::Error::success();
for (auto &E : *Edits)
Err =
@@ -473,38 +473,38 @@
static constexpr trace::Metric TweakAttempt(
"tweak_attempt", trace::Metric::Counter, "tweak_id");
TweakAttempt.record(1, TweakID);
- auto Action =
- [File = File.str(), Sel, TweakID = TweakID.str(), CB = std::move(CB),
- FS = FSProvider.getFileSystem()](Expected<InputsAndAST> InpAST) mutable {
- if (!InpAST)
- return CB(InpAST.takeError());
- auto Selections = tweakSelection(Sel, *InpAST);
- if (!Selections)
- return CB(Selections.takeError());
- llvm::Optional<llvm::Expected<Tweak::Effect>> Effect;
- // Try each selection, take the first one that prepare()s.
- // If they all fail, Effect will hold get the last error.
- for (const auto &Selection : *Selections) {
- auto T = prepareTweak(TweakID, *Selection);
- if (T) {
- Effect = (*T)->apply(*Selection);
- break;
- }
- Effect = T.takeError();
- }
- assert(Effect.hasValue() && "Expected at least one selection");
- if (*Effect) {
- // Tweaks don't apply clang-format, do that centrally here.
- for (auto &It : (*Effect)->ApplyEdits) {
- Edit &E = It.second;
- format::FormatStyle Style =
- getFormatStyleForFile(File, E.InitialCode, FS.get());
- if (llvm::Error Err = reformatEdit(E, Style))
- elog("Failed to format {0}: {1}", It.first(), std::move(Err));
- }
- }
- return CB(std::move(*Effect));
- };
+ auto Action = [File = File.str(), Sel, TweakID = TweakID.str(),
+ CB = std::move(CB),
+ this](Expected<InputsAndAST> InpAST) mutable {
+ if (!InpAST)
+ return CB(InpAST.takeError());
+ auto Selections = tweakSelection(Sel, *InpAST);
+ if (!Selections)
+ return CB(Selections.takeError());
+ llvm::Optional<llvm::Expected<Tweak::Effect>> Effect;
+ // Try each selection, take the first one that prepare()s.
+ // If they all fail, Effect will hold get the last error.
+ for (const auto &Selection : *Selections) {
+ auto T = prepareTweak(TweakID, *Selection);
+ if (T) {
+ Effect = (*T)->apply(*Selection);
+ break;
+ }
+ Effect = T.takeError();
+ }
+ assert(Effect.hasValue() && "Expected at least one selection");
+ if (*Effect) {
+ // Tweaks don't apply clang-format, do that centrally here.
+ for (auto &It : (*Effect)->ApplyEdits) {
+ Edit &E = It.second;
+ format::FormatStyle Style =
+ getFormatStyleForFile(File, E.InitialCode, FSProvider);
+ if (llvm::Error Err = reformatEdit(E, Style))
+ elog("Failed to format {0}: {1}", It.first(), std::move(Err));
+ }
+ }
+ return CB(std::move(*Effect));
+ };
WorkScheduler.runWithAST("ApplyTweak", File, std::move(Action));
}
@@ -549,7 +549,7 @@
// 2) if 1) fails, we use the AST&Index approach, it is slower but supports
// different code layout.
if (auto CorrespondingFile = getCorrespondingHeaderOrSource(
- std::string(Path), FSProvider.getFileSystem()))
+ std::string(Path), FSProvider.getFileSystem(llvm::None)))
return CB(std::move(CorrespondingFile));
auto Action = [Path = Path.str(), CB = std::move(CB),
this](llvm::Expected<InputsAndAST> InpAST) mutable {
@@ -564,8 +564,7 @@
ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
llvm::ArrayRef<tooling::Range> Ranges) {
// Call clang-format.
- format::FormatStyle Style =
- getFormatStyleForFile(File, Code, FSProvider.getFileSystem().get());
+ format::FormatStyle Style = getFormatStyleForFile(File, Code, FSProvider);
tooling::Replacements IncludeReplaces =
format::sortIncludes(Style, Code, Ranges, File);
auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
@@ -597,9 +596,8 @@
this](llvm::Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
return CB(InpAST.takeError());
- format::FormatStyle Style =
- getFormatStyleForFile(File, InpAST->Inputs.Contents,
- InpAST->Inputs.FSProvider->getFileSystem().get());
+ format::FormatStyle Style = getFormatStyleForFile(
+ File, InpAST->Inputs.Contents, *InpAST->Inputs.FSProvider);
CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
};
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index a7a4ede..511bf02 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1113,12 +1113,10 @@
// NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
// the remapped buffers do not get freed.
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
- Input.ParseInput.FSProvider->getFileSystem();
+ Input.ParseInput.FSProvider->getFileSystem(
+ Input.ParseInput.CompileCommand.Directory);
if (Input.Preamble.StatCache)
VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
- if (VFS->setCurrentWorkingDirectory(
- Input.ParseInput.CompileCommand.Directory))
- elog("Couldn't set working directory during code completion");
auto Clang = prepareCompilerInstance(
std::move(CI), !CompletingInPreamble ? &Input.Preamble.Preamble : nullptr,
std::move(ContentsBuffer), std::move(VFS), IgnoreDiags);
@@ -1292,9 +1290,9 @@
assert(Recorder && "Recorder is not set");
CCContextKind = Recorder->CCContext.getKind();
IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();
- auto Style = getFormatStyleForFile(
- SemaCCInput.FileName, SemaCCInput.ParseInput.Contents,
- SemaCCInput.ParseInput.FSProvider->getFileSystem().get());
+ auto Style = getFormatStyleForFile(SemaCCInput.FileName,
+ SemaCCInput.ParseInput.Contents,
+ *SemaCCInput.ParseInput.FSProvider);
const auto NextToken = Lexer::findNextToken(
Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(),
Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts);
@@ -1365,9 +1363,8 @@
// Indexes may choose to impose their own limits even if we don't have one.
}
- CodeCompleteResult
- runWithoutSema(llvm::StringRef Content, size_t Offset,
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) && {
+ CodeCompleteResult runWithoutSema(llvm::StringRef Content, size_t Offset,
+ const FileSystemProvider &FSProvider) && {
trace::Span Tracer("CodeCompleteWithoutSema");
// Fill in fields normally set by runWithSema()
HeuristicPrefix = guessCompletionPrefix(Content, Offset);
@@ -1383,7 +1380,7 @@
ProxSources[FileName].Cost = 0;
FileProximity.emplace(ProxSources);
- auto Style = getFormatStyleForFile(FileName, Content, VFS.get());
+ auto Style = getFormatStyleForFile(FileName, Content, FSProvider);
// This will only insert verbatim headers.
Inserter.emplace(FileName, Content, Style,
/*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr);
@@ -1783,9 +1780,8 @@
FileName, Preamble ? Preamble->Includes : IncludeStructure(),
SpecFuzzyFind, Opts);
return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)
- ? std::move(Flow).runWithoutSema(
- ParseInput.Contents, *Offset,
- ParseInput.FSProvider->getFileSystem())
+ ? std::move(Flow).runWithoutSema(ParseInput.Contents, *Offset,
+ *ParseInput.FSProvider)
: std::move(Flow).run({FileName, *Offset, *Preamble,
// We want to serve code completions with
// low latency, so don't bother patching.
diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp
index 3dfa770..170e803 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -11,6 +11,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/PCHContainerOperations.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
@@ -47,13 +48,7 @@
for (const auto &S : Inputs.CompileCommand.CommandLine)
ArgStrs.push_back(S.c_str());
- auto VFS = Inputs.FSProvider->getFileSystem();
- if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
- log("Couldn't set working directory when creating compiler invocation.");
- // We proceed anyway, our lit-tests rely on results for non-existing working
- // dirs.
- }
-
+ auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
llvm::IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
CompilerInstance::createDiagnostics(new DiagnosticOptions, &D, false);
std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp
index f622ab2..d9a26cb 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -46,6 +46,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <memory>
@@ -248,14 +249,9 @@
trace::Span Tracer("BuildAST");
SPAN_ATTACH(Tracer, "File", Filename);
- auto VFS = Inputs.FSProvider->getFileSystem();
+ auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
if (Preamble && Preamble->StatCache)
VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
- if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
- log("Couldn't set working directory when building the preamble.");
- // We proceed anyway, our lit-tests rely on results for non-existing working
- // dirs.
- }
assert(CI);
// Command-line parsing sets DisableFree to true by default, but we don't want
@@ -359,7 +355,8 @@
auto BuildDir = VFS->getCurrentWorkingDirectory();
if (Inputs.Opts.SuggestMissingIncludes && Inputs.Index &&
!BuildDir.getError()) {
- auto Style = getFormatStyleForFile(Filename, Inputs.Contents, VFS.get());
+ auto Style =
+ getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.FSProvider);
auto Inserter = std::make_shared<IncludeInserter>(
Filename, Inputs.Contents, Style, BuildDir.get(),
&Clang->getPreprocessor().getHeaderSearchInfo());
diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp
index d7a15ff..2788c9c 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -30,6 +30,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -237,7 +239,7 @@
VFSProvider(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
: VFS(std::move(FS)) {}
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getFileSystem() const override {
+ getFileSystem(llvm::NoneType) const override {
return VFS;
}
@@ -356,13 +358,7 @@
CI.getPreprocessorOpts().WriteCommentListToPCH = false;
CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
- auto VFS = Inputs.FSProvider->getFileSystem();
- if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
- log("Couldn't set working directory when building the preamble.");
- // We proceed anyway, our lit-tests rely on results for non-existing working
- // dirs.
- }
-
+ auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
llvm::SmallString<32> AbsFileName(FileName);
VFS->makeAbsolute(AbsFileName);
auto StatCache = std::make_unique<PreambleFileStatusCache>(AbsFileName);
@@ -399,8 +395,7 @@
llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
auto Bounds =
ComputePreambleBounds(*CI.getLangOpts(), ContentsBuffer.get(), 0);
- auto VFS = Inputs.FSProvider->getFileSystem();
- VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory);
+ auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
return compileCommandsAreEqual(Inputs.CompileCommand,
Preamble.CompileCommand) &&
Preamble.Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
@@ -427,8 +422,8 @@
trace::Span Tracer("CreatePreamblePatch");
SPAN_ATTACH(Tracer, "File", FileName);
assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
- auto VFS =
- Baseline.StatCache->getConsumingFS(Modified.FSProvider->getFileSystem());
+ auto VFS = Baseline.StatCache->getConsumingFS(
+ Modified.FSProvider->getFileSystem(/*CWD=*/llvm::None));
// First scan preprocessor directives in Baseline and Modified. These will be
// used to figure out newly added directives in Modified. Scanning can fail,
// the code just bails out and creates an empty patch in such cases, as:
diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp
index c8502c5..1054791 100644
--- a/clang-tools-extra/clangd/SourceCode.cpp
+++ b/clang-tools-extra/clangd/SourceCode.cpp
@@ -12,6 +12,7 @@
#include "Protocol.h"
#include "refactor/Tweak.h"
#include "support/Context.h"
+#include "support/FSProvider.h"
#include "support/Logger.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/LangOptions.h"
@@ -574,11 +575,12 @@
return digest(Content);
}
-format::FormatStyle getFormatStyleForFile(llvm::StringRef File,
- llvm::StringRef Content,
- llvm::vfs::FileSystem *FS) {
- auto Style = format::getStyle(format::DefaultFormatStyle, File,
- format::DefaultFallbackStyle, Content, FS);
+format::FormatStyle
+getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content,
+ const FileSystemProvider &FSProvider) {
+ auto Style = format::getStyle(
+ format::DefaultFormatStyle, File, format::DefaultFallbackStyle, Content,
+ FSProvider.getFileSystem(/*CWD=*/llvm::None).get());
if (!Style) {
log("getStyle() failed for file {0}: {1}. Fallback is LLVM style.", File,
Style.takeError());
diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h
index 73fd939..6f36069 100644
--- a/clang-tools-extra/clangd/SourceCode.h
+++ b/clang-tools-extra/clangd/SourceCode.h
@@ -15,6 +15,7 @@
#include "Protocol.h"
#include "support/Context.h"
+#include "support/FSProvider.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
@@ -167,7 +168,7 @@
/// though the latter may have been overridden in main()!
format::FormatStyle getFormatStyleForFile(llvm::StringRef File,
llvm::StringRef Content,
- llvm::vfs::FileSystem *FS);
+ const FileSystemProvider &FSProvider);
/// Cleanup and format the given replacements.
llvm::Expected<tooling::Replacements>
diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp
index de6dd9c..6490cfc 100644
--- a/clang-tools-extra/clangd/index/Background.cpp
+++ b/clang-tools-extra/clangd/index/Background.cpp
@@ -244,8 +244,7 @@
SPAN_ATTACH(Tracer, "file", Cmd.Filename);
auto AbsolutePath = getAbsolutePath(Cmd);
- auto FS = FSProvider.getFileSystem();
- FS->setCurrentWorkingDirectory(Cmd.Directory);
+ auto FS = FSProvider.getFileSystem(Cmd.Directory);
auto Buf = FS->getBufferForFile(AbsolutePath);
if (!Buf)
return llvm::errorCodeToError(Buf.getError());
@@ -382,7 +381,7 @@
Rebuilder.loadedShard(LoadedShards);
Rebuilder.doneLoading();
- auto FS = FSProvider.getFileSystem();
+ auto FS = FSProvider.getFileSystem(/*CWD=*/llvm::None);
llvm::DenseSet<PathRef> TUsToIndex;
// We'll accept data from stale shards, but ensure the files get reindexed
// soon.
diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
index 63a5ba6..d37d377 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
@@ -424,10 +424,8 @@
return llvm::createStringError(Buffer.getError(),
Buffer.getError().message());
auto Contents = Buffer->get()->getBuffer();
- auto LangOpts = format::getFormattingLangOpts(
- getFormatStyleForFile(*CCFile, Contents, &FS));
auto InsertionPoint = getInsertionPoint(
- Contents, Source->getQualifiedNameAsString(), LangOpts);
+ Contents, Source->getQualifiedNameAsString(), Sel.AST->getLangOpts());
if (!InsertionPoint)
return InsertionPoint.takeError();
diff --git a/clang-tools-extra/clangd/support/FSProvider.cpp b/clang-tools-extra/clangd/support/FSProvider.cpp
index 6474a3c..080bd06 100644
--- a/clang-tools-extra/clangd/support/FSProvider.cpp
+++ b/clang-tools-extra/clangd/support/FSProvider.cpp
@@ -7,6 +7,9 @@
//===----------------------------------------------------------------------===//
#include "support/FSProvider.h"
+#include "Logger.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@@ -72,7 +75,15 @@
} // namespace
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
-clang::clangd::RealFileSystemProvider::getFileSystem() const {
+FileSystemProvider::getFileSystem(PathRef CWD) const {
+ auto FS = getFileSystem(/*CWD=*/llvm::None);
+ if (auto EC = FS->setCurrentWorkingDirectory(CWD))
+ elog("VFS: failed to set CWD to {0}: {1}", CWD, EC.message());
+ return FS;
+}
+
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+clang::clangd::RealFileSystemProvider::getFileSystem(llvm::NoneType) const {
// Avoid using memory-mapped files.
// FIXME: Try to use a similar approach in Sema instead of relying on
// propagation of the 'isVolatile' flag through all layers.
diff --git a/clang-tools-extra/clangd/support/FSProvider.h b/clang-tools-extra/clangd/support/FSProvider.h
index 2686e3e..8c6b8c8 100644
--- a/clang-tools-extra/clangd/support/FSProvider.h
+++ b/clang-tools-extra/clangd/support/FSProvider.h
@@ -9,7 +9,10 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FSPROVIDER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FSPROVIDER_H
+#include "Path.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <memory>
@@ -25,14 +28,21 @@
/// Context::current() will be the context passed to the clang entrypoint,
/// such as addDocument(), and will also be propagated to result callbacks.
/// Embedders may use this to isolate filesystem accesses.
+ /// Initial working directory is arbitrary.
virtual llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getFileSystem() const = 0;
+ getFileSystem(llvm::NoneType CWD) const = 0;
+
+ /// As above, except it will try to set current working directory to \p CWD.
+ /// This is an overload instead of an optional to make implicit string ->
+ /// StringRef conversion possible.
+ virtual llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ getFileSystem(PathRef CWD) const;
};
class RealFileSystemProvider : public FileSystemProvider {
public:
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getFileSystem() const override;
+ getFileSystem(llvm::NoneType) const override;
};
} // namespace clangd
diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index 34d72a97..50398374 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -21,6 +21,7 @@
#include "clang/Basic/Version.h"
#include "clang/Format/Format.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
@@ -717,7 +718,8 @@
ClangTidyOptProvider = std::make_unique<tidy::FileOptionsProvider>(
tidy::ClangTidyGlobalOptions(),
/* Default */ EmptyDefaults,
- /* Override */ OverrideClangTidyOptions, FSProvider.getFileSystem());
+ /* Override */ OverrideClangTidyOptions,
+ FSProvider.getFileSystem(/*CWD=*/llvm::None));
Opts.GetClangTidyOptions = [&](llvm::vfs::FileSystem &,
llvm::StringRef File) {
// This function must be thread-safe and tidy option providers are not.
diff --git a/clang-tools-extra/clangd/unittests/ClangdTests.cpp b/clang-tools-extra/clangd/unittests/ClangdTests.cpp
index 4616401..6cfdeaff 100644
--- a/clang-tools-extra/clangd/unittests/ClangdTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ClangdTests.cpp
@@ -15,9 +15,12 @@
#include "SyncAPI.h"
#include "TestFS.h"
#include "URI.h"
+#include "support/Path.h"
#include "support/Threading.h"
#include "clang/Config/config.h"
#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Errc.h"
@@ -270,7 +273,8 @@
TEST_F(ClangdVFSTest, PropagatesContexts) {
static Key<int> Secret;
struct FSProvider : public FileSystemProvider {
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const override {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ getFileSystem(llvm::NoneType) const override {
Got = Context::current().getExisting(Secret);
return buildTestFS({});
}
@@ -925,7 +929,8 @@
ListenStatsFSProvider(llvm::StringMap<unsigned> &CountStats)
: CountStats(CountStats) {}
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const override {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ getFileSystem(llvm::NoneType) const override {
class ListenStatVFS : public llvm::vfs::ProxyFileSystem {
public:
ListenStatVFS(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
diff --git a/clang-tools-extra/clangd/unittests/FSTests.cpp b/clang-tools-extra/clangd/unittests/FSTests.cpp
index 4887b0a..575111e 100644
--- a/clang-tools-extra/clangd/unittests/FSTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FSTests.cpp
@@ -21,7 +21,6 @@
Files["y"] = "";
Files["main"] = "";
auto FS = buildTestFS(Files);
- FS->setCurrentWorkingDirectory(testRoot());
PreambleFileStatusCache StatCache(testPath("main"));
auto ProduceFS = StatCache.getProducingFS(FS);
diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
index 4e81b79..f243bfc 100644
--- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -16,6 +16,7 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "gmock/gmock.h"
@@ -52,8 +53,7 @@
EXPECT_TRUE(static_cast<bool>(CI));
// The diagnostic options must be set before creating a CompilerInstance.
CI->getDiagnosticOpts().IgnoreWarnings = true;
- auto VFS = FS.getFileSystem();
- VFS->setCurrentWorkingDirectory(Cmd->Directory);
+ auto VFS = PI.FSProvider->getFileSystem(Cmd->Directory);
auto Clang = prepareCompilerInstance(
std::move(CI), /*Preamble=*/nullptr,
llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile),
diff --git a/clang-tools-extra/clangd/unittests/PreambleTests.cpp b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
index 0b662d7..ee63953 100644
--- a/clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -70,11 +70,11 @@
// We don't run PP directly over the patch cotents to test production
// behaviour.
auto Bounds = Lexer::ComputePreamble(ModifiedContents, *CI->getLangOpts());
- auto Clang =
- prepareCompilerInstance(std::move(CI), &BaselinePreamble->Preamble,
- llvm::MemoryBuffer::getMemBufferCopy(
- ModifiedContents.slice(0, Bounds.Size).str()),
- PI.FSProvider->getFileSystem(), Diags);
+ auto Clang = prepareCompilerInstance(
+ std::move(CI), &BaselinePreamble->Preamble,
+ llvm::MemoryBuffer::getMemBufferCopy(
+ ModifiedContents.slice(0, Bounds.Size).str()),
+ PI.FSProvider->getFileSystem(PI.CompileCommand.Directory), Diags);
PreprocessOnlyAction Action;
if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
ADD_FAILURE() << "failed begin source file";
diff --git a/clang-tools-extra/clangd/unittests/TestFS.h b/clang-tools-extra/clangd/unittests/TestFS.h
index 0472380..5b541d2 100644
--- a/clang-tools-extra/clangd/unittests/TestFS.h
+++ b/clang-tools-extra/clangd/unittests/TestFS.h
@@ -13,8 +13,11 @@
#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTFS_H
#include "ClangdServer.h"
#include "GlobalCompilationDatabase.h"
+#include "support/FSProvider.h"
#include "support/Path.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
@@ -30,10 +33,18 @@
// A VFS provider that returns TestFSes containing a provided set of files.
class MockFSProvider : public FileSystemProvider {
public:
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const override {
+ // Prevent name hiding caused by the overload below.
+ using FileSystemProvider::getFileSystem;
+
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const {
return buildTestFS(Files, Timestamps);
}
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ getFileSystem(llvm::NoneType) const override {
+ return getFileSystem();
+ }
+
// If relative paths are used, they are resolved with testPath().
llvm::StringMap<std::string> Files;
llvm::StringMap<time_t> Timestamps;