kadircet created this revision.
kadircet added a reviewer: sammccall.
Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous, MaskRay, 
javed.absar, ilya-biryukov.
Herald added a project: clang.

This ensures ParseInputs provides a read-only access to FS.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D81173

Files:
  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.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

Index: clang-tools-extra/clangd/unittests/TestTU.h
===================================================================
--- clang-tools-extra/clangd/unittests/TestTU.h
+++ 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 @@
   // 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;
Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ 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 @@
   // 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 @@
   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 @@
 }
 
 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 @@
 }
 
 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.");
Index: clang-tools-extra/clangd/unittests/TestFS.h
===================================================================
--- clang-tools-extra/clangd/unittests/TestFS.h
+++ clang-tools-extra/clangd/unittests/TestFS.h
@@ -31,11 +31,12 @@
 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.
Index: clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ 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 @@
   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 @@
                            std::move(CB));
   }
 
-  llvm::StringMap<std::string> Files;
-  llvm::StringMap<time_t> Timestamps;
+  MockFSProvider FSProvider;
   MockCompilationDatabase CDB;
 };
 
@@ -161,10 +161,10 @@
   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 @@
     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 @@
                 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 @@
   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 @@
   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 @@
   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 @@
                                 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
Index: clang-tools-extra/clangd/unittests/PreambleTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -50,6 +50,7 @@
 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 @@
   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 @@
       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, PatchesPreambleIncludes) {
+  MockFSProvider FS;
   IgnoreDiagnostics Diags;
   auto TU = TestTU::withCode(R"cpp(
     #include "a.h"
@@ -172,7 +174,7 @@
   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 @@
     #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 @@
   }
 
   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 @@
     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();
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -249,9 +249,11 @@
 }
 
 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 @@
   // 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 @@
   // 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 @@
 
   // 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 @@
   // 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 @@
   // 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);
Index: clang-tools-extra/clangd/unittests/HeadersTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -44,20 +44,20 @@
   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;
Index: clang-tools-extra/clangd/unittests/FileIndexTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FileIndexTests.cpp
+++ clang-tools-extra/clangd/unittests/FileIndexTests.cpp
@@ -272,14 +272,14 @@
   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"
Index: clang-tools-extra/clangd/unittests/CompilerTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CompilerTests.cpp
+++ clang-tools-extra/clangd/unittests/CompilerTests.cpp
@@ -19,19 +19,20 @@
 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 @@
   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());
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -108,7 +108,8 @@
     Opts.Index = OverrideIndex.get();
   }
 
-  auto Inputs = TU.inputs();
+  MockFSProvider FS;
+  auto Inputs = TU.inputs(FS);
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
@@ -118,7 +119,8 @@
   auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
                                 /*InMemory=*/true, /*Callback=*/nullptr);
   return codeComplete(testPath(TU.Filename), Inputs.CompileCommand,
-                      Preamble.get(), TU.Code, Point, Inputs.FS, Opts);
+                      Preamble.get(), TU.Code, Point,
+                      Inputs.FSProvider->getFileSystem(), Opts);
 }
 
 // Runs code completion.
@@ -1054,7 +1056,8 @@
     Index = memIndex(IndexSymbols);
 
   auto TU = TestTU::withCode(Text);
-  auto Inputs = TU.inputs();
+  MockFSProvider FS;
+  auto Inputs = TU.inputs(FS);
   IgnoreDiagnostics Diags;
   auto CI = buildCompilerInvocation(Inputs, Diags);
   if (!CI) {
@@ -1068,7 +1071,8 @@
     return {};
   }
   return signatureHelp(testPath(TU.Filename), Inputs.CompileCommand, *Preamble,
-                       Text, Point, Inputs.FS, Index.get());
+                       Text, Point, Inputs.FSProvider->getFileSystem(),
+                       Index.get());
 }
 
 SignatureHelp signatures(llvm::StringRef Text,
@@ -1206,7 +1210,8 @@
   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,
@@ -1218,10 +1223,10 @@
     #include "a.h"
     void bar() { foo(^2); })cpp");
   TU.Code = Test.code().str();
-  Inputs = TU.inputs();
-  auto Results =
-      signatureHelp(testPath(TU.Filename), Inputs.CompileCommand,
-                    *EmptyPreamble, TU.Code, Test.point(), Inputs.FS, nullptr);
+  Inputs = TU.inputs(FS);
+  auto Results = signatureHelp(testPath(TU.Filename), Inputs.CompileCommand,
+                               *EmptyPreamble, TU.Code, Test.point(),
+                               Inputs.FSProvider->getFileSystem(), nullptr);
   EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo([[int x]]) -> int")));
   EXPECT_EQ(0, Results.activeSignature);
   EXPECT_EQ(0, Results.activeParameter);
Index: clang-tools-extra/clangd/support/FSProvider.h
===================================================================
--- clang-tools-extra/clangd/support/FSProvider.h
+++ 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 {
@@ -34,6 +35,9 @@
   getFileSystem() const override;
 };
 
+std::unique_ptr<FileSystemProvider>
+getFSProvider(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/support/FSProvider.cpp
===================================================================
--- clang-tools-extra/clangd/support/FSProvider.cpp
+++ clang-tools-extra/clangd/support/FSProvider.cpp
@@ -79,5 +79,22 @@
   return new VolatileFileSystem(
       llvm::vfs::createPhysicalFileSystem().release());
 }
+
+std::unique_ptr<FileSystemProvider>
+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));
+}
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/index/Background.cpp
===================================================================
--- clang-tools-extra/clangd/index/Background.cpp
+++ clang-tools-extra/clangd/index/Background.cpp
@@ -245,6 +245,7 @@
   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 @@
 
   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");
Index: clang-tools-extra/clangd/Preamble.cpp
===================================================================
--- clang-tools-extra/clangd/Preamble.cpp
+++ 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,11 @@
 scanPreamble(llvm::StringRef Contents,
              llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
              const tooling::CompileCommand &Cmd) {
+  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 +322,19 @@
   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 +368,7 @@
   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 +391,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());
   // 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 +403,14 @@
   //   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());
Index: clang-tools-extra/clangd/ParsedAST.cpp
===================================================================
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -248,7 +248,7 @@
   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)) {
Index: clang-tools-extra/clangd/Compiler.h
===================================================================
--- clang-tools-extra/clangd/Compiler.h
+++ 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 @@
 /// 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";
Index: clang-tools-extra/clangd/Compiler.cpp
===================================================================
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -47,7 +47,8 @@
   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 @@
   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;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===================================================================
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ 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"
@@ -1065,9 +1066,10 @@
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = Input.VFS;
   if (Input.Preamble.StatCache)
     VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
+  auto FSProvider = getFSProvider(VFS);
   ParseInputs ParseInput;
   ParseInput.CompileCommand = Input.Command;
-  ParseInput.FS = VFS;
+  ParseInput.FSProvider = FSProvider.get();
   ParseInput.Contents = std::string(Input.Contents);
   // FIXME: setup the recoveryAST and recoveryASTType in ParseInput properly.
 
@@ -1793,12 +1795,13 @@
   ParseInputs PI;
   PI.CompileCommand = Command;
   PI.Contents = Contents.str();
-  PI.FS = std::move(VFS);
+  auto FSProvider = getFSProvider(std::move(VFS));
+  PI.FSProvider = FSProvider.get();
   semaCodeComplete(
       std::make_unique<SignatureHelpCollector>(Options, Index, Result), Options,
       {FileName, Command, Preamble,
        PreamblePatch::create(FileName, PI, Preamble), Contents, *Offset,
-       std::move(PI.FS)});
+       FSProvider->getFileSystem()});
   return Result;
 }
 
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -179,18 +179,17 @@
 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();
+  auto VFS = FSProvider.getFileSystem();
   // FIXME: call tidy options builder on the worker thread, it can do IO.
   if (GetClangTidyOptions)
-    Opts.ClangTidyOpts = GetClangTidyOptions(*FS, File);
+    Opts.ClangTidyOpts = GetClangTidyOptions(*VFS, 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;
@@ -391,8 +390,9 @@
       return CB(Edits.takeError());
 
     if (Opts.WantFormat) {
-      auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
-                                         InpAST->Inputs.FS.get());
+      auto VFS = InpAST->Inputs.FSProvider->getFileSystem();
+      auto Style =
+          getFormatStyleForFile(File, InpAST->Inputs.Contents, VFS.get());
       llvm::Error Err = llvm::Error::success();
       for (auto &E : *Edits)
         Err =
@@ -592,8 +592,9 @@
                  this](llvm::Expected<InputsAndAST> InpAST) mutable {
     if (!InpAST)
       return CB(InpAST.takeError());
-    format::FormatStyle Style = getFormatStyleForFile(
-        File, InpAST->Inputs.Contents, InpAST->Inputs.FS.get());
+    auto VFS = InpAST->Inputs.FSProvider->getFileSystem();
+    format::FormatStyle Style =
+        getFormatStyleForFile(File, InpAST->Inputs.Contents, VFS.get());
     CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
   };
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to