[clang-tools-extra] f693ce4 - [clangd] Change ParseInputs to store FSProvider rather than VFS
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 8 04:27:41 PDT 2020
Author: Kadir Cetinkaya
Date: 2020-06-08T13:23:55+02:00
New Revision: f693ce4aa97e7afe34a3f41609ffbbaf32b571de
URL: https://github.com/llvm/llvm-project/commit/f693ce4aa97e7afe34a3f41609ffbbaf32b571de
DIFF: https://github.com/llvm/llvm-project/commit/f693ce4aa97e7afe34a3f41609ffbbaf32b571de.diff
LOG: [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
Added:
Modified:
clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/Compiler.cpp
clang-tools-extra/clangd/Compiler.h
clang-tools-extra/clangd/ParsedAST.cpp
clang-tools-extra/clangd/Preamble.cpp
clang-tools-extra/clangd/index/Background.cpp
clang-tools-extra/clangd/support/FSProvider.h
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
clang-tools-extra/clangd/unittests/CompilerTests.cpp
clang-tools-extra/clangd/unittests/FileIndexTests.cpp
clang-tools-extra/clangd/unittests/HeadersTests.cpp
clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
clang-tools-extra/clangd/unittests/PreambleTests.cpp
clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
clang-tools-extra/clangd/unittests/TestFS.h
clang-tools-extra/clangd/unittests/TestTU.cpp
clang-tools-extra/clangd/unittests/TestTU.h
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index 0721c8ddaf73..3539de0e561e 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -179,18 +179,16 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
llvm::StringRef Version,
WantDiagnostics WantDiags, bool ForceRebuild) {
- auto FS = FSProvider.getFileSystem();
-
ParseOptions Opts;
Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults();
// FIXME: call tidy options builder on the worker thread, it can do IO.
if (GetClangTidyOptions)
- Opts.ClangTidyOpts = GetClangTidyOptions(*FS, File);
+ Opts.ClangTidyOpts = GetClangTidyOptions(*FSProvider.getFileSystem(), File);
Opts.SuggestMissingIncludes = SuggestMissingIncludes;
// Compile command is set asynchronously during update, as it can be slow.
ParseInputs Inputs;
- Inputs.FS = FS;
+ Inputs.FSProvider = &FSProvider;
Inputs.Contents = std::string(Contents);
Inputs.Version = Version.str();
Inputs.ForceRebuild = ForceRebuild;
@@ -214,8 +212,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
if (!CodeCompleteOpts.Index) // Respect overridden index.
CodeCompleteOpts.Index = Index;
- auto Task = [Pos, FS = FSProvider.getFileSystem(), CodeCompleteOpts,
- File = File.str(), CB = std::move(CB),
+ auto Task = [Pos, CodeCompleteOpts, File = File.str(), CB = std::move(CB),
this](llvm::Expected<InputsAndPreamble> IP) mutable {
if (!IP)
return CB(IP.takeError());
@@ -238,7 +235,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
}
}
}
- ParseInputs ParseInput{IP->Command, FS, IP->Contents.str()};
+ ParseInputs ParseInput{IP->Command, &FSProvider, IP->Contents.str()};
ParseInput.Index = Index;
ParseInput.Opts.BuildRecoveryAST = BuildRecoveryAST;
ParseInput.Opts.PreserveRecoveryASTType = PreserveRecoveryASTType;
@@ -275,8 +272,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
void ClangdServer::signatureHelp(PathRef File, Position Pos,
Callback<SignatureHelp> CB) {
- auto Action = [Pos, FS = FSProvider.getFileSystem(), File = File.str(),
- CB = std::move(CB),
+ auto Action = [Pos, File = File.str(), CB = std::move(CB),
this](llvm::Expected<InputsAndPreamble> IP) mutable {
if (!IP)
return CB(IP.takeError());
@@ -286,7 +282,7 @@ void ClangdServer::signatureHelp(PathRef File, Position Pos,
return CB(llvm::createStringError(llvm::inconvertibleErrorCode(),
"Failed to parse includes"));
- ParseInputs ParseInput{IP->Command, FS, IP->Contents.str()};
+ ParseInputs ParseInput{IP->Command, &FSProvider, IP->Contents.str()};
ParseInput.Index = Index;
ParseInput.Opts.BuildRecoveryAST = BuildRecoveryAST;
ParseInput.Opts.PreserveRecoveryASTType = PreserveRecoveryASTType;
@@ -399,8 +395,9 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
return CB(Edits.takeError());
if (Opts.WantFormat) {
- auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
- InpAST->Inputs.FS.get());
+ auto Style = getFormatStyleForFile(
+ File, InpAST->Inputs.Contents,
+ InpAST->Inputs.FSProvider->getFileSystem().get());
llvm::Error Err = llvm::Error::success();
for (auto &E : *Edits)
Err =
@@ -600,8 +597,9 @@ void ClangdServer::findHover(PathRef File, Position Pos,
this](llvm::Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
return CB(InpAST.takeError());
- format::FormatStyle Style = getFormatStyleForFile(
- File, InpAST->Inputs.Contents, InpAST->Inputs.FS.get());
+ format::FormatStyle Style =
+ getFormatStyleForFile(File, InpAST->Inputs.Contents,
+ InpAST->Inputs.FSProvider->getFileSystem().get());
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 4c05daac61bf..3cfdac1c3bc8 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -36,6 +36,7 @@
#include "index/Index.h"
#include "index/Symbol.h"
#include "index/SymbolOrigin.h"
+#include "support/FSProvider.h"
#include "support/Logger.h"
#include "support/Threading.h"
#include "support/Trace.h"
@@ -1060,9 +1061,6 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
const SemaCompleteInput &Input,
IncludeStructure *Includes = nullptr) {
trace::Span Tracer("Sema completion");
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = Input.ParseInput.FS;
- if (Input.Preamble.StatCache)
- VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
IgnoreDiagnostics IgnoreDiags;
auto CI = buildCompilerInvocation(Input.ParseInput, IgnoreDiags);
@@ -1103,6 +1101,10 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
Input.Patch->apply(*CI);
// 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();
+ if (Input.Preamble.StatCache)
+ VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
auto Clang = prepareCompilerInstance(
std::move(CI), !CompletingInPreamble ? &Input.Preamble.Preamble : nullptr,
std::move(ContentsBuffer), std::move(VFS), IgnoreDiags);
@@ -1272,9 +1274,9 @@ class CodeCompleteFlow {
assert(Recorder && "Recorder is not set");
CCContextKind = Recorder->CCContext.getKind();
IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();
- auto Style = getFormatStyleForFile(SemaCCInput.FileName,
- SemaCCInput.ParseInput.Contents,
- SemaCCInput.ParseInput.FS.get());
+ auto Style = getFormatStyleForFile(
+ SemaCCInput.FileName, SemaCCInput.ParseInput.Contents,
+ SemaCCInput.ParseInput.FSProvider->getFileSystem().get());
// If preprocessor was run, inclusions from preprocessor callback should
// already be added to Includes.
Inserter.emplace(
@@ -1759,8 +1761,9 @@ CodeCompleteResult codeComplete(PathRef FileName, Position Pos,
FileName, Preamble ? Preamble->Includes : IncludeStructure(),
SpecFuzzyFind, Opts);
return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)
- ? std::move(Flow).runWithoutSema(ParseInput.Contents, *Offset,
- ParseInput.FS)
+ ? std::move(Flow).runWithoutSema(
+ ParseInput.Contents, *Offset,
+ ParseInput.FSProvider->getFileSystem())
: 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 9eb86a4265b4..3dfa77057e9f 100644
--- a/clang-tools-extra/clangd/Compiler.cpp
+++ b/clang-tools-extra/clangd/Compiler.cpp
@@ -47,7 +47,8 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D,
for (const auto &S : Inputs.CompileCommand.CommandLine)
ArgStrs.push_back(S.c_str());
- if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+ 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.
@@ -56,7 +57,7 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D,
llvm::IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
CompilerInstance::createDiagnostics(new DiagnosticOptions, &D, false);
std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
- ArgStrs, CommandLineDiagsEngine, Inputs.FS,
+ ArgStrs, CommandLineDiagsEngine, std::move(VFS),
/*ShouldRecoverOnErrors=*/true, CC1Args);
if (!CI)
return nullptr;
diff --git a/clang-tools-extra/clangd/Compiler.h b/clang-tools-extra/clangd/Compiler.h
index 4b507f34adc4..a4edf957549e 100644
--- a/clang-tools-extra/clangd/Compiler.h
+++ b/clang-tools-extra/clangd/Compiler.h
@@ -18,6 +18,7 @@
#include "../clang-tidy/ClangTidyOptions.h"
#include "GlobalCompilationDatabase.h"
#include "index/Index.h"
+#include "support/FSProvider.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Tooling/CompilationDatabase.h"
@@ -45,7 +46,7 @@ struct ParseOptions {
/// Information required to run clang, e.g. to parse AST or do code completion.
struct ParseInputs {
tooling::CompileCommand CompileCommand;
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
+ const FileSystemProvider *FSProvider;
std::string Contents;
// Version identifier for Contents, provided by the client and opaque to us.
std::string Version = "null";
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp
index f3568c34f99a..e85f1b30cd3a 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -248,7 +248,7 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
trace::Span Tracer("BuildAST");
SPAN_ATTACH(Tracer, "File", Filename);
- auto VFS = Inputs.FS;
+ auto VFS = Inputs.FSProvider->getFileSystem();
if (Preamble && Preamble->StatCache)
VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp
index d02685f4bf46..af7229ecb888 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -10,6 +10,7 @@
#include "Compiler.h"
#include "Headers.h"
#include "SourceCode.h"
+#include "support/FSProvider.h"
#include "support/Logger.h"
#include "support/Trace.h"
#include "clang/Basic/Diagnostic.h"
@@ -212,10 +213,29 @@ llvm::Expected<ScannedPreamble>
scanPreamble(llvm::StringRef Contents,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const tooling::CompileCommand &Cmd) {
+ // FIXME: Change PreambleStatCache to operate on FileSystemProvider rather
+ // than vfs::FileSystem, that way we can just use ParseInputs without this
+ // hack.
+ auto GetFSProvider = [](llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
+ class VFSProvider : public FileSystemProvider {
+ public:
+ VFSProvider(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
+ : VFS(std::move(FS)) {}
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+ getFileSystem() const override {
+ return VFS;
+ }
+
+ private:
+ const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
+ };
+ return std::make_unique<VFSProvider>(std::move(FS));
+ };
+ auto FSProvider = GetFSProvider(std::move(VFS));
// Build and run Preprocessor over the preamble.
ParseInputs PI;
PI.Contents = Contents.str();
- PI.FS = std::move(VFS);
+ PI.FSProvider = FSProvider.get();
PI.CompileCommand = Cmd;
IgnoringDiagConsumer IgnoreDiags;
auto CI = buildCompilerInvocation(PI, IgnoreDiags);
@@ -320,18 +340,19 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
CI.getPreprocessorOpts().WriteCommentListToPCH = false;
CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
- if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
+ 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.
}
llvm::SmallString<32> AbsFileName(FileName);
- Inputs.FS->makeAbsolute(AbsFileName);
+ VFS->makeAbsolute(AbsFileName);
auto StatCache = std::make_unique<PreambleFileStatusCache>(AbsFileName);
auto BuiltPreamble = PrecompiledPreamble::Build(
CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
- StatCache->getProducingFS(Inputs.FS),
+ StatCache->getProducingFS(VFS),
std::make_shared<PCHContainerOperations>(), StoreInMemory,
SerializedDeclsCollector);
@@ -365,7 +386,7 @@ bool isPreambleCompatible(const PreambleData &Preamble,
return compileCommandsAreEqual(Inputs.CompileCommand,
Preamble.CompileCommand) &&
Preamble.Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
- Inputs.FS.get());
+ Inputs.FSProvider->getFileSystem().get());
}
void escapeBackslashAndQuotes(llvm::StringRef Text, llvm::raw_ostream &OS) {
@@ -388,6 +409,8 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
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());
// 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:
@@ -398,16 +421,14 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
// there's nothing to do but generate an empty patch.
auto BaselineScan = scanPreamble(
// Contents needs to be null-terminated.
- Baseline.Preamble.getContents().str(),
- Baseline.StatCache->getConsumingFS(Modified.FS), Modified.CompileCommand);
+ Baseline.Preamble.getContents().str(), VFS, Modified.CompileCommand);
if (!BaselineScan) {
elog("Failed to scan baseline of {0}: {1}", FileName,
BaselineScan.takeError());
return PreamblePatch::unmodified(Baseline);
}
- auto ModifiedScan = scanPreamble(
- Modified.Contents, Baseline.StatCache->getConsumingFS(Modified.FS),
- Modified.CompileCommand);
+ auto ModifiedScan =
+ scanPreamble(Modified.Contents, std::move(VFS), Modified.CompileCommand);
if (!ModifiedScan) {
elog("Failed to scan modified contents of {0}: {1}", FileName,
ModifiedScan.takeError());
diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp
index cc2c288c090e..de6dd9c60113 100644
--- a/clang-tools-extra/clangd/index/Background.cpp
+++ b/clang-tools-extra/clangd/index/Background.cpp
@@ -245,6 +245,7 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
auto AbsolutePath = getAbsolutePath(Cmd);
auto FS = FSProvider.getFileSystem();
+ FS->setCurrentWorkingDirectory(Cmd.Directory);
auto Buf = FS->getBufferForFile(AbsolutePath);
if (!Buf)
return llvm::errorCodeToError(Buf.getError());
@@ -259,16 +260,17 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
vlog("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
ParseInputs Inputs;
- Inputs.FS = std::move(FS);
- Inputs.FS->setCurrentWorkingDirectory(Cmd.Directory);
+ Inputs.FSProvider = &FSProvider;
Inputs.CompileCommand = std::move(Cmd);
IgnoreDiagnostics IgnoreDiags;
auto CI = buildCompilerInvocation(Inputs, IgnoreDiags);
if (!CI)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Couldn't build compiler invocation");
- auto Clang = prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
- std::move(*Buf), Inputs.FS, IgnoreDiags);
+
+ auto Clang =
+ prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
+ std::move(*Buf), std::move(FS), IgnoreDiags);
if (!Clang)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Couldn't build compiler instance");
diff --git a/clang-tools-extra/clangd/support/FSProvider.h b/clang-tools-extra/clangd/support/FSProvider.h
index a53a4149a47b..2686e3ec4c43 100644
--- a/clang-tools-extra/clangd/support/FSProvider.h
+++ b/clang-tools-extra/clangd/support/FSProvider.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
namespace clang {
namespace clangd {
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index ab1947844bbe..6114fac2dace 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -108,7 +108,10 @@ CodeCompleteResult completions(const TestTU &TU, Position Point,
Opts.Index = OverrideIndex.get();
}
- auto Inputs = TU.inputs();
+ MockFSProvider FS;
+ auto Inputs = TU.inputs(FS);
+ Inputs.Opts.BuildRecoveryAST = true;
+ Inputs.Opts.PreserveRecoveryASTType = true;
IgnoreDiagnostics Diags;
auto CI = buildCompilerInvocation(Inputs, Diags);
if (!CI) {
@@ -117,10 +120,7 @@ CodeCompleteResult completions(const TestTU &TU, Position Point,
}
auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
/*InMemory=*/true, /*Callback=*/nullptr);
- ParseInputs ParseInput{Inputs.CompileCommand, Inputs.FS, TU.Code};
- ParseInput.Opts.BuildRecoveryAST = true;
- ParseInput.Opts.PreserveRecoveryASTType = true;
- return codeComplete(testPath(TU.Filename), Point, Preamble.get(), ParseInput,
+ return codeComplete(testPath(TU.Filename), Point, Preamble.get(), Inputs,
Opts);
}
@@ -151,8 +151,7 @@ CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
MockFSProvider FS;
Annotations Test(Text);
- ParseInputs ParseInput{tooling::CompileCommand(), FS.getFileSystem(),
- Test.code().str()};
+ ParseInputs ParseInput{tooling::CompileCommand(), &FS, Test.code().str()};
return codeComplete(FilePath, Test.point(), /*Preamble=*/nullptr, ParseInput,
Opts);
}
@@ -1058,7 +1057,11 @@ SignatureHelp signatures(llvm::StringRef Text, Position Point,
Index = memIndex(IndexSymbols);
auto TU = TestTU::withCode(Text);
- auto Inputs = TU.inputs();
+ MockFSProvider FS;
+ auto Inputs = TU.inputs(FS);
+ Inputs.Index = Index.get();
+ Inputs.Opts.BuildRecoveryAST = true;
+ Inputs.Opts.PreserveRecoveryASTType = true;
IgnoreDiagnostics Diags;
auto CI = buildCompilerInvocation(Inputs, Diags);
if (!CI) {
@@ -1071,11 +1074,7 @@ SignatureHelp signatures(llvm::StringRef Text, Position Point,
ADD_FAILURE() << "Couldn't build Preamble";
return {};
}
- ParseInputs ParseInput{Inputs.CompileCommand, Inputs.FS, Text.str()};
- ParseInput.Index = Index.get();
- ParseInput.Opts.BuildRecoveryAST = true;
- ParseInput.Opts.PreserveRecoveryASTType = true;
- return signatureHelp(testPath(TU.Filename), Point, *Preamble, ParseInput);
+ return signatureHelp(testPath(TU.Filename), Point, *Preamble, Inputs);
}
SignatureHelp signatures(llvm::StringRef Text,
@@ -1213,7 +1212,8 @@ TEST(SignatureHelpTest, StalePreamble) {
TestTU TU;
TU.Code = "";
IgnoreDiagnostics Diags;
- auto Inputs = TU.inputs();
+ MockFSProvider FS;
+ auto Inputs = TU.inputs(FS);
auto CI = buildCompilerInvocation(Inputs, Diags);
ASSERT_TRUE(CI);
auto EmptyPreamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
@@ -1225,11 +1225,8 @@ TEST(SignatureHelpTest, StalePreamble) {
#include "a.h"
void bar() { foo(^2); })cpp");
TU.Code = Test.code().str();
- Inputs = TU.inputs();
-
- ParseInputs ParseInput{Inputs.CompileCommand, Inputs.FS, TU.Code};
auto Results = signatureHelp(testPath(TU.Filename), Test.point(),
- *EmptyPreamble, ParseInput);
+ *EmptyPreamble, TU.inputs(FS));
EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo([[int x]]) -> int")));
EXPECT_EQ(0, Results.activeSignature);
EXPECT_EQ(0, Results.activeParameter);
diff --git a/clang-tools-extra/clangd/unittests/CompilerTests.cpp b/clang-tools-extra/clangd/unittests/CompilerTests.cpp
index a12a7b9ce9af..58210a95df3c 100644
--- a/clang-tools-extra/clangd/unittests/CompilerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CompilerTests.cpp
@@ -19,19 +19,20 @@ namespace {
using testing::IsEmpty;
TEST(BuildCompilerInvocation, DropsPCH) {
+ MockFSProvider FS;
IgnoreDiagnostics Diags;
TestTU TU;
TU.AdditionalFiles["test.h.pch"] = "";
TU.ExtraArgs = {"-include-pch", "test.h.pch"};
- EXPECT_THAT(buildCompilerInvocation(TU.inputs(), Diags)
+ EXPECT_THAT(buildCompilerInvocation(TU.inputs(FS), Diags)
->getPreprocessorOpts()
.ImplicitPCHInclude,
IsEmpty());
// Transparent include translation
TU.ExtraArgs = {"-include", "test.h"};
- EXPECT_THAT(buildCompilerInvocation(TU.inputs(), Diags)
+ EXPECT_THAT(buildCompilerInvocation(TU.inputs(FS), Diags)
->getPreprocessorOpts()
.ImplicitPCHInclude,
IsEmpty());
@@ -40,11 +41,11 @@ TEST(BuildCompilerInvocation, DropsPCH) {
TU.AdditionalFiles["test.pch"] = "";
TU.ExtraArgs = {"--driver-mode=cl"};
TU.ExtraArgs.push_back("/Yutest.h");
- EXPECT_THAT(buildCompilerInvocation(TU.inputs(), Diags)
+ EXPECT_THAT(buildCompilerInvocation(TU.inputs(FS), Diags)
->getPreprocessorOpts()
.ImplicitPCHInclude,
IsEmpty());
- EXPECT_THAT(buildCompilerInvocation(TU.inputs(), Diags)
+ EXPECT_THAT(buildCompilerInvocation(TU.inputs(FS), Diags)
->getPreprocessorOpts()
.PCHThroughHeader,
IsEmpty());
diff --git a/clang-tools-extra/clangd/unittests/FileIndexTests.cpp b/clang-tools-extra/clangd/unittests/FileIndexTests.cpp
index 371388ef8e22..bd8a089df238 100644
--- a/clang-tools-extra/clangd/unittests/FileIndexTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FileIndexTests.cpp
@@ -272,14 +272,14 @@ TEST(FileIndexTest, RebuildWithPreamble) {
PI.CompileCommand.Filename = FooCpp;
PI.CompileCommand.CommandLine = {"clang", "-xc++", FooCpp};
- llvm::StringMap<std::string> Files;
- Files[FooCpp] = "";
- Files[FooH] = R"cpp(
+ MockFSProvider FSProvider;
+ FSProvider.Files[FooCpp] = "";
+ FSProvider.Files[FooH] = R"cpp(
namespace ns_in_header {
int func_in_header();
}
)cpp";
- PI.FS = buildTestFS(std::move(Files));
+ PI.FSProvider = &FSProvider;
PI.Contents = R"cpp(
#include "foo.h"
diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
index 07ab835bdb67..4e81b799f19f 100644
--- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -44,20 +44,20 @@ class HeadersTest : public ::testing::Test {
std::unique_ptr<CompilerInstance> setupClang() {
auto Cmd = CDB.getCompileCommand(MainFile);
assert(static_cast<bool>(Cmd));
- auto VFS = FS.getFileSystem();
- VFS->setCurrentWorkingDirectory(Cmd->Directory);
ParseInputs PI;
PI.CompileCommand = *Cmd;
- PI.FS = VFS;
+ PI.FSProvider = &FS;
auto CI = buildCompilerInvocation(PI, IgnoreDiags);
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 Clang = prepareCompilerInstance(
std::move(CI), /*Preamble=*/nullptr,
- llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile), VFS,
- IgnoreDiags);
+ llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile),
+ std::move(VFS), IgnoreDiags);
EXPECT_FALSE(Clang->getFrontendOpts().Inputs.empty());
return Clang;
diff --git a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
index 0ad4a9f20ccb..810bb28a7d13 100644
--- a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -249,9 +249,11 @@ TEST(ParsedASTTest, NoCrashOnTokensWithTidyCheck) {
}
TEST(ParsedASTTest, CanBuildInvocationWithUnknownArgs) {
+ MockFSProvider FSProvider;
+ FSProvider.Files = {{testPath("foo.cpp"), "void test() {}"}};
// Unknown flags should not prevent a build of compiler invocation.
ParseInputs Inputs;
- Inputs.FS = buildTestFS({{testPath("foo.cpp"), "void test() {}"}});
+ Inputs.FSProvider = &FSProvider;
Inputs.CompileCommand.CommandLine = {"clang", "-fsome-unknown-flag",
testPath("foo.cpp")};
IgnoreDiagnostics IgnoreDiags;
@@ -445,14 +447,15 @@ TEST(ParsedASTTest, ReplayPreambleForTidyCheckers) {
// Make sure replay logic works with patched preambles.
TU.Code = "";
StoreDiags Diags;
- auto Inputs = TU.inputs();
+ MockFSProvider FS;
+ auto Inputs = TU.inputs(FS);
auto CI = buildCompilerInvocation(Inputs, Diags);
auto EmptyPreamble =
buildPreamble(testPath(TU.Filename), *CI, Inputs, true, nullptr);
ASSERT_TRUE(EmptyPreamble);
TU.Code = "#include <a.h>";
Includes.clear();
- auto PatchedAST = ParsedAST::build(testPath(TU.Filename), TU.inputs(),
+ auto PatchedAST = ParsedAST::build(testPath(TU.Filename), TU.inputs(FS),
std::move(CI), {}, EmptyPreamble);
ASSERT_TRUE(PatchedAST);
// Make sure includes were seen only once.
@@ -484,7 +487,8 @@ TEST(ParsedASTTest, PatchesAdditionalIncludes) {
// Build preamble with no includes.
TU.Code = "";
StoreDiags Diags;
- auto Inputs = TU.inputs();
+ MockFSProvider FS;
+ auto Inputs = TU.inputs(FS);
auto CI = buildCompilerInvocation(Inputs, Diags);
auto EmptyPreamble =
buildPreamble(testPath("foo.cpp"), *CI, Inputs, true, nullptr);
@@ -493,7 +497,7 @@ TEST(ParsedASTTest, PatchesAdditionalIncludes) {
// Now build an AST using empty preamble and ensure patched includes worked.
TU.Code = ModifiedContents.str();
- Inputs = TU.inputs();
+ Inputs = TU.inputs(FS);
auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
{}, EmptyPreamble);
ASSERT_TRUE(PatchedAST);
@@ -526,7 +530,8 @@ TEST(ParsedASTTest, PatchesDeletedIncludes) {
// Build preamble with no includes.
TU.Code = R"cpp(#include <foo.h>)cpp";
StoreDiags Diags;
- auto Inputs = TU.inputs();
+ MockFSProvider FS;
+ auto Inputs = TU.inputs(FS);
auto CI = buildCompilerInvocation(Inputs, Diags);
auto BaselinePreamble =
buildPreamble(testPath("foo.cpp"), *CI, Inputs, true, nullptr);
@@ -537,7 +542,7 @@ TEST(ParsedASTTest, PatchesDeletedIncludes) {
// Now build an AST using additional includes and check that locations are
// correctly parsed.
TU.Code = "";
- Inputs = TU.inputs();
+ Inputs = TU.inputs(FS);
auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
{}, BaselinePreamble);
ASSERT_TRUE(PatchedAST);
diff --git a/clang-tools-extra/clangd/unittests/PreambleTests.cpp b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
index 87a68ceea048..8d00fa0b2ee7 100644
--- a/clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -50,6 +50,7 @@ IncludeStructure
collectPatchedIncludes(llvm::StringRef ModifiedContents,
llvm::StringRef BaselineContents,
llvm::StringRef MainFileName = "main.cpp") {
+ MockFSProvider FS;
auto TU = TestTU::withCode(BaselineContents);
TU.Filename = MainFileName.str();
// ms-compatibility changes meaning of #import, make sure it is turned off.
@@ -57,7 +58,7 @@ collectPatchedIncludes(llvm::StringRef ModifiedContents,
auto BaselinePreamble = TU.preamble();
// Create the patch.
TU.Code = ModifiedContents.str();
- auto PI = TU.inputs();
+ auto PI = TU.inputs(FS);
auto PP = PreamblePatch::create(testPath(TU.Filename), PI, *BaselinePreamble);
// Collect patch contents.
IgnoreDiagnostics Diags;
@@ -73,7 +74,7 @@ collectPatchedIncludes(llvm::StringRef ModifiedContents,
prepareCompilerInstance(std::move(CI), &BaselinePreamble->Preamble,
llvm::MemoryBuffer::getMemBufferCopy(
ModifiedContents.slice(0, Bounds.Size).str()),
- PI.FS, Diags);
+ PI.FSProvider->getFileSystem(), Diags);
PreprocessOnlyAction Action;
if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
ADD_FAILURE() << "failed begin source file";
@@ -164,6 +165,7 @@ TEST(PreamblePatchTest, MainFileIsEscaped) {
}
TEST(PreamblePatchTest, PatchesPreambleIncludes) {
+ MockFSProvider FS;
IgnoreDiagnostics Diags;
auto TU = TestTU::withCode(R"cpp(
#include "a.h"
@@ -172,7 +174,7 @@ TEST(PreamblePatchTest, PatchesPreambleIncludes) {
TU.AdditionalFiles["a.h"] = "#include \"b.h\"";
TU.AdditionalFiles["b.h"] = "";
TU.AdditionalFiles["c.h"] = "";
- auto PI = TU.inputs();
+ auto PI = TU.inputs(FS);
auto BaselinePreamble = buildPreamble(
TU.Filename, *buildCompilerInvocation(PI, Diags), PI, true, nullptr);
// We drop c.h from modified and add a new header. Since the latter is patched
@@ -181,7 +183,7 @@ TEST(PreamblePatchTest, PatchesPreambleIncludes) {
#include "a.h"
#include "b.h"
)cpp";
- auto PP = PreamblePatch::create(testPath(TU.Filename), TU.inputs(),
+ auto PP = PreamblePatch::create(testPath(TU.Filename), TU.inputs(FS),
*BaselinePreamble);
// Only a.h should exists in the preamble, as c.h has been dropped and b.h was
// newly introduced.
@@ -199,14 +201,15 @@ llvm::Optional<ParsedAST> createPatchedAST(llvm::StringRef Baseline,
}
IgnoreDiagnostics Diags;
+ MockFSProvider FS;
auto TU = TestTU::withCode(Modified);
- auto CI = buildCompilerInvocation(TU.inputs(), Diags);
+ auto CI = buildCompilerInvocation(TU.inputs(FS), Diags);
if (!CI) {
ADD_FAILURE() << "Failed to build compiler invocation";
return llvm::None;
}
- return ParsedAST::build(testPath(TU.Filename), TU.inputs(), std::move(CI), {},
- BaselinePreamble);
+ return ParsedAST::build(testPath(TU.Filename), TU.inputs(FS), std::move(CI),
+ {}, BaselinePreamble);
}
std::string getPreamblePatch(llvm::StringRef Baseline,
@@ -216,8 +219,9 @@ std::string getPreamblePatch(llvm::StringRef Baseline,
ADD_FAILURE() << "Failed to build baseline preamble";
return "";
}
+ MockFSProvider FS;
auto TU = TestTU::withCode(Modified);
- return PreamblePatch::create(testPath("main.cpp"), TU.inputs(),
+ return PreamblePatch::create(testPath("main.cpp"), TU.inputs(FS),
*BaselinePreamble)
.text()
.str();
diff --git a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
index 8c8520aae620..ee54a2f71e10 100644
--- a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -16,6 +16,7 @@
#include "TestFS.h"
#include "support/Cancellation.h"
#include "support/Context.h"
+#include "support/FSProvider.h"
#include "support/Path.h"
#include "support/TestTracer.h"
#include "support/Threading.h"
@@ -73,7 +74,7 @@ class TUSchedulerTests : public ::testing::Test {
ParseInputs getInputs(PathRef File, std::string Contents) {
ParseInputs Inputs;
Inputs.CompileCommand = *CDB.getCompileCommand(File);
- Inputs.FS = buildTestFS(Files, Timestamps);
+ Inputs.FSProvider = &FSProvider;
Inputs.Contents = std::move(Contents);
Inputs.Opts = ParseOptions();
return Inputs;
@@ -149,8 +150,7 @@ class TUSchedulerTests : public ::testing::Test {
std::move(CB));
}
- llvm::StringMap<std::string> Files;
- llvm::StringMap<time_t> Timestamps;
+ MockFSProvider FSProvider;
MockCompilationDatabase CDB;
};
@@ -161,10 +161,10 @@ TEST_F(TUSchedulerTests, MissingFiles) {
TUScheduler S(CDB, optsForTest());
auto Added = testPath("added.cpp");
- Files[Added] = "x";
+ FSProvider.Files[Added] = "x";
auto Missing = testPath("missing.cpp");
- Files[Missing] = "";
+ FSProvider.Files[Missing] = "";
S.update(Added, getInputs(Added, "x"), WantDiagnostics::No);
@@ -425,7 +425,7 @@ TEST_F(TUSchedulerTests, ManyUpdates) {
for (int I = 0; I < FilesCount; ++I) {
std::string Name = "foo" + std::to_string(I) + ".cpp";
Files.push_back(testPath(Name));
- this->Files[Files.back()] = "";
+ this->FSProvider.Files[Files.back()] = "";
}
StringRef Contents1 = R"cpp(int a;)cpp";
@@ -476,7 +476,6 @@ TEST_F(TUSchedulerTests, ManyUpdates) {
EXPECT_THAT(Context::current().get(NonceKey), Pointee(Nonce));
ASSERT_TRUE((bool)AST);
- EXPECT_EQ(AST->Inputs.FS, Inputs.FS);
EXPECT_EQ(AST->Inputs.Contents, Inputs.Contents);
EXPECT_EQ(AST->Inputs.Version, Inputs.Version);
EXPECT_EQ(AST->AST.version(), Inputs.Version);
@@ -617,8 +616,8 @@ TEST_F(TUSchedulerTests, EmptyPreamble) {
auto Foo = testPath("foo.cpp");
auto Header = testPath("foo.h");
- Files[Header] = "void foo()";
- Timestamps[Header] = time_t(0);
+ FSProvider.Files[Header] = "void foo()";
+ FSProvider.Timestamps[Header] = time_t(0);
auto WithPreamble = R"cpp(
#include "foo.h"
int main() {}
@@ -686,8 +685,8 @@ TEST_F(TUSchedulerTests, NoopOnEmptyChanges) {
auto Source = testPath("foo.cpp");
auto Header = testPath("foo.h");
- Files[Header] = "int a;";
- Timestamps[Header] = time_t(0);
+ FSProvider.Files[Header] = "int a;";
+ FSProvider.Timestamps[Header] = time_t(0);
std::string SourceContents = R"cpp(
#include "foo.h"
@@ -715,7 +714,7 @@ TEST_F(TUSchedulerTests, NoopOnEmptyChanges) {
ASSERT_EQ(S.fileStats().lookup(Source).PreambleBuilds, 1u);
// Update to a header should cause a rebuild, though.
- Timestamps[Header] = time_t(1);
+ FSProvider.Timestamps[Header] = time_t(1);
ASSERT_TRUE(DoUpdate(SourceContents));
ASSERT_FALSE(DoUpdate(SourceContents));
ASSERT_EQ(S.fileStats().lookup(Source).ASTBuilds, 2u);
@@ -761,11 +760,12 @@ TEST_F(TUSchedulerTests, ForceRebuild) {
Field(&Diag::Message,
"use of undeclared identifier 'a'")));
});
+ S.blockUntilIdle(timeoutSeconds(10));
// Add the header file. We need to recreate the inputs since we changed a
// file from underneath the test FS.
- Files[Header] = "int a;";
- Timestamps[Header] = time_t(1);
+ FSProvider.Files[Header] = "int a;";
+ FSProvider.Timestamps[Header] = time_t(1);
Inputs = getInputs(Source, SourceContents);
// The addition of the missing header file shouldn't trigger a rebuild since
diff --git a/clang-tools-extra/clangd/unittests/TestFS.h b/clang-tools-extra/clangd/unittests/TestFS.h
index 7dde78d9c157..0472380f7a58 100644
--- a/clang-tools-extra/clangd/unittests/TestFS.h
+++ b/clang-tools-extra/clangd/unittests/TestFS.h
@@ -31,11 +31,12 @@ buildTestFS(llvm::StringMap<std::string> const &Files,
class MockFSProvider : public FileSystemProvider {
public:
IntrusiveRefCntPtr<llvm::vfs::FileSystem> getFileSystem() const override {
- return buildTestFS(Files);
+ return buildTestFS(Files, Timestamps);
}
// If relative paths are used, they are resolved with testPath().
llvm::StringMap<std::string> Files;
+ llvm::StringMap<time_t> Timestamps;
};
// A Compilation database that returns a fixed set of compile flags.
diff --git a/clang-tools-extra/clangd/unittests/TestTU.cpp b/clang-tools-extra/clangd/unittests/TestTU.cpp
index b4781425943c..9c812298742e 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.cpp
+++ b/clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -20,7 +20,7 @@
namespace clang {
namespace clangd {
-ParseInputs TestTU::inputs() const {
+ParseInputs TestTU::inputs(MockFSProvider &FSProvider) const {
std::string FullFilename = testPath(Filename),
FullHeaderName = testPath(HeaderFilename),
ImportThunk = testPath("import_thunk.h");
@@ -29,10 +29,10 @@ ParseInputs TestTU::inputs() const {
// guard without messing up offsets). In this case, use an intermediate file.
std::string ThunkContents = "#import \"" + FullHeaderName + "\"\n";
- llvm::StringMap<std::string> Files(AdditionalFiles);
- Files[FullFilename] = Code;
- Files[FullHeaderName] = HeaderCode;
- Files[ImportThunk] = ThunkContents;
+ FSProvider.Files = AdditionalFiles;
+ FSProvider.Files[FullFilename] = Code;
+ FSProvider.Files[FullHeaderName] = HeaderCode;
+ FSProvider.Files[ImportThunk] = ThunkContents;
ParseInputs Inputs;
auto &Argv = Inputs.CompileCommand.CommandLine;
@@ -54,7 +54,7 @@ ParseInputs TestTU::inputs() const {
Inputs.CompileCommand.Filename = FullFilename;
Inputs.CompileCommand.Directory = testRoot();
Inputs.Contents = Code;
- Inputs.FS = buildTestFS(Files);
+ Inputs.FSProvider = &FSProvider;
Inputs.Opts = ParseOptions();
Inputs.Opts.BuildRecoveryAST = true;
Inputs.Opts.PreserveRecoveryASTType = true;
@@ -67,7 +67,8 @@ ParseInputs TestTU::inputs() const {
}
std::shared_ptr<const PreambleData> TestTU::preamble() const {
- auto Inputs = inputs();
+ MockFSProvider FSProvider;
+ auto Inputs = inputs(FSProvider);
IgnoreDiagnostics Diags;
auto CI = buildCompilerInvocation(Inputs, Diags);
assert(CI && "Failed to build compilation invocation.");
@@ -77,7 +78,8 @@ std::shared_ptr<const PreambleData> TestTU::preamble() const {
}
ParsedAST TestTU::build() const {
- auto Inputs = inputs();
+ MockFSProvider FSProvider;
+ auto Inputs = inputs(FSProvider);
StoreDiags Diags;
auto CI = buildCompilerInvocation(Inputs, Diags);
assert(CI && "Failed to build compilation invocation.");
diff --git a/clang-tools-extra/clangd/unittests/TestTU.h b/clang-tools-extra/clangd/unittests/TestTU.h
index 57017f4a9175..05629a891bef 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.h
+++ b/clang-tools-extra/clangd/unittests/TestTU.h
@@ -19,6 +19,7 @@
#include "Compiler.h"
#include "ParsedAST.h"
+#include "TestFS.h"
#include "index/Index.h"
#include "support/Path.h"
#include "llvm/ADT/StringMap.h"
@@ -69,7 +70,7 @@ struct TestTU {
// Suppress this behavior by adding an 'error-ok' comment to the code.
ParsedAST build() const;
std::shared_ptr<const PreambleData> preamble() const;
- ParseInputs inputs() const;
+ ParseInputs inputs(MockFSProvider &FSProvider) const;
SymbolSlab headerSymbols() const;
RefSlab headerRefs() const;
std::unique_ptr<SymbolIndex> index() const;
More information about the cfe-commits
mailing list