[clangd][NFC] Rename FSProvider and getFileSystem
Summary: Clangd uses FSProvider to get threadsafe views into file systems. This patch changes naming to make that more explicit. Depends on D81920 Reviewers: sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D81998
This commit is contained in:
@@ -1340,7 +1340,7 @@ void ClangdLSPServer::onSemanticTokensEdits(
|
||||
}
|
||||
|
||||
ClangdLSPServer::ClangdLSPServer(
|
||||
class Transport &Transp, const FileSystemProvider &FSProvider,
|
||||
class Transport &Transp, const ThreadsafeFS &FSProvider,
|
||||
const clangd::CodeCompleteOptions &CCOpts,
|
||||
const clangd::RenameOptions &RenameOpts,
|
||||
llvm::Optional<Path> CompileCommandsDir, bool UseDirBasedCDB,
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
/// for compile_commands.json in all parent directories of each file.
|
||||
/// If UseDirBasedCDB is false, compile commands are not read from disk.
|
||||
// FIXME: Clean up signature around CDBs.
|
||||
ClangdLSPServer(Transport &Transp, const FileSystemProvider &FSProvider,
|
||||
ClangdLSPServer(Transport &Transp, const ThreadsafeFS &FSProvider,
|
||||
const clangd::CodeCompleteOptions &CCOpts,
|
||||
const clangd::RenameOptions &RenameOpts,
|
||||
llvm::Optional<Path> CompileCommandsDir, bool UseDirBasedCDB,
|
||||
@@ -207,7 +207,7 @@ private:
|
||||
notify("$/progress", Params);
|
||||
}
|
||||
|
||||
const FileSystemProvider &FSProvider;
|
||||
const ThreadsafeFS &FSProvider;
|
||||
/// Options used for code completion
|
||||
clangd::CodeCompleteOptions CCOpts;
|
||||
/// Options used for rename.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "refactor/Tweak.h"
|
||||
#include "support/Logger.h"
|
||||
#include "support/Markup.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "support/Trace.h"
|
||||
#include "clang/Format/Format.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
@@ -129,8 +130,8 @@ ClangdServer::Options::operator TUScheduler::Options() const {
|
||||
}
|
||||
|
||||
ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
|
||||
const FileSystemProvider &FSProvider,
|
||||
const Options &Opts, Callbacks *Callbacks)
|
||||
const ThreadsafeFS &FSProvider, const Options &Opts,
|
||||
Callbacks *Callbacks)
|
||||
: FSProvider(FSProvider),
|
||||
DynamicIdx(Opts.BuildDynamicSymbolIndex
|
||||
? new FileIndex(Opts.HeavyweightDynamicSymbolIndex)
|
||||
@@ -183,8 +184,8 @@ void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
|
||||
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(/*CWD=*/llvm::None), File);
|
||||
Opts.ClangTidyOpts =
|
||||
GetClangTidyOptions(*FSProvider.view(/*CWD=*/llvm::None), File);
|
||||
Opts.SuggestMissingIncludes = SuggestMissingIncludes;
|
||||
|
||||
// Compile command is set asynchronously during update, as it can be slow.
|
||||
@@ -318,9 +319,9 @@ ClangdServer::formatOnType(llvm::StringRef Code, PathRef File, Position Pos,
|
||||
llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
|
||||
if (!CursorPos)
|
||||
return CursorPos.takeError();
|
||||
auto Style = format::getStyle(
|
||||
format::DefaultFormatStyle, File, format::DefaultFallbackStyle, Code,
|
||||
FSProvider.getFileSystem(/*CWD=*/llvm::None).get());
|
||||
auto Style = format::getStyle(format::DefaultFormatStyle, File,
|
||||
format::DefaultFallbackStyle, Code,
|
||||
FSProvider.view(/*CWD=*/llvm::None).get());
|
||||
if (!Style)
|
||||
return Style.takeError();
|
||||
|
||||
@@ -549,7 +550,7 @@ void ClangdServer::switchSourceHeader(
|
||||
// 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(llvm::None)))
|
||||
std::string(Path), FSProvider.view(llvm::None)))
|
||||
return CB(std::move(CorrespondingFile));
|
||||
auto Action = [Path = Path.str(), CB = std::move(CB),
|
||||
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
#include "refactor/Rename.h"
|
||||
#include "refactor/Tweak.h"
|
||||
#include "support/Cancellation.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/Function.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "clang/Tooling/CompilationDatabase.h"
|
||||
#include "clang/Tooling/Core/Replacement.h"
|
||||
#include "llvm/ADT/FunctionExtras.h"
|
||||
@@ -172,7 +172,7 @@ public:
|
||||
/// those arguments for subsequent reparses. However, ClangdServer will check
|
||||
/// if compilation arguments changed on calls to forceReparse().
|
||||
ClangdServer(const GlobalCompilationDatabase &CDB,
|
||||
const FileSystemProvider &FSProvider, const Options &Opts,
|
||||
const ThreadsafeFS &FSProvider, const Options &Opts,
|
||||
Callbacks *Callbacks = nullptr);
|
||||
|
||||
/// Add a \p File to the list of tracked C++ files or update the contents if
|
||||
@@ -330,7 +330,7 @@ private:
|
||||
formatCode(llvm::StringRef Code, PathRef File,
|
||||
ArrayRef<tooling::Range> Ranges);
|
||||
|
||||
const FileSystemProvider &FSProvider;
|
||||
const ThreadsafeFS &FSProvider;
|
||||
|
||||
Path ResourceDir;
|
||||
// The index used to look up symbols. This could be:
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
#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/ThreadsafeFS.h"
|
||||
#include "support/Trace.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
@@ -1113,7 +1113,7 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
|
||||
// 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->view(
|
||||
Input.ParseInput.CompileCommand.Directory);
|
||||
if (Input.Preamble.StatCache)
|
||||
VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
|
||||
@@ -1364,7 +1364,7 @@ public:
|
||||
}
|
||||
|
||||
CodeCompleteResult runWithoutSema(llvm::StringRef Content, size_t Offset,
|
||||
const FileSystemProvider &FSProvider) && {
|
||||
const ThreadsafeFS &FSProvider) && {
|
||||
trace::Span Tracer("CodeCompleteWithoutSema");
|
||||
// Fill in fields normally set by runWithSema()
|
||||
HeuristicPrefix = guessCompletionPrefix(Content, Offset);
|
||||
|
||||
@@ -48,7 +48,7 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D,
|
||||
for (const auto &S : Inputs.CompileCommand.CommandLine)
|
||||
ArgStrs.push_back(S.c_str());
|
||||
|
||||
auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
|
||||
auto VFS = Inputs.FSProvider->view(Inputs.CompileCommand.Directory);
|
||||
llvm::IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
|
||||
CompilerInstance::createDiagnostics(new DiagnosticOptions, &D, false);
|
||||
std::unique_ptr<CompilerInvocation> CI = createInvocationFromCommandLine(
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "../clang-tidy/ClangTidyOptions.h"
|
||||
#include "GlobalCompilationDatabase.h"
|
||||
#include "index/Index.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/PrecompiledPreamble.h"
|
||||
#include "clang/Tooling/CompilationDatabase.h"
|
||||
@@ -46,7 +46,7 @@ struct ParseOptions {
|
||||
/// Information required to run clang, e.g. to parse AST or do code completion.
|
||||
struct ParseInputs {
|
||||
tooling::CompileCommand CompileCommand;
|
||||
const FileSystemProvider *FSProvider;
|
||||
const ThreadsafeFS *FSProvider;
|
||||
std::string Contents;
|
||||
// Version identifier for Contents, provided by the client and opaque to us.
|
||||
std::string Version = "null";
|
||||
|
||||
@@ -249,7 +249,7 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
|
||||
trace::Span Tracer("BuildAST");
|
||||
SPAN_ATTACH(Tracer, "File", Filename);
|
||||
|
||||
auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
|
||||
auto VFS = Inputs.FSProvider->view(Inputs.CompileCommand.Directory);
|
||||
if (Preamble && Preamble->StatCache)
|
||||
VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#include "Compiler.h"
|
||||
#include "Headers.h"
|
||||
#include "SourceCode.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/Logger.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "support/Trace.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
@@ -234,12 +234,12 @@ scanPreamble(llvm::StringRef Contents,
|
||||
// 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 {
|
||||
class VFSProvider : public ThreadsafeFS {
|
||||
public:
|
||||
VFSProvider(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
|
||||
: VFS(std::move(FS)) {}
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
getFileSystem(llvm::NoneType) const override {
|
||||
view(llvm::NoneType) const override {
|
||||
return VFS;
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
|
||||
CI.getPreprocessorOpts().WriteCommentListToPCH = false;
|
||||
|
||||
CppFilePreambleCallbacks SerializedDeclsCollector(FileName, PreambleCallback);
|
||||
auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
|
||||
auto VFS = Inputs.FSProvider->view(Inputs.CompileCommand.Directory);
|
||||
llvm::SmallString<32> AbsFileName(FileName);
|
||||
VFS->makeAbsolute(AbsFileName);
|
||||
auto StatCache = std::make_unique<PreambleFileStatusCache>(AbsFileName);
|
||||
@@ -395,7 +395,7 @@ bool isPreambleCompatible(const PreambleData &Preamble,
|
||||
llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
|
||||
auto Bounds =
|
||||
ComputePreambleBounds(*CI.getLangOpts(), ContentsBuffer.get(), 0);
|
||||
auto VFS = Inputs.FSProvider->getFileSystem(Inputs.CompileCommand.Directory);
|
||||
auto VFS = Inputs.FSProvider->view(Inputs.CompileCommand.Directory);
|
||||
return compileCommandsAreEqual(Inputs.CompileCommand,
|
||||
Preamble.CompileCommand) &&
|
||||
Preamble.Preamble.CanReuse(CI, ContentsBuffer.get(), Bounds,
|
||||
@@ -423,7 +423,7 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
|
||||
SPAN_ATTACH(Tracer, "File", FileName);
|
||||
assert(llvm::sys::path::is_absolute(FileName) && "relative FileName!");
|
||||
auto VFS = Baseline.StatCache->getConsumingFS(
|
||||
Modified.FSProvider->getFileSystem(/*CWD=*/llvm::None));
|
||||
Modified.FSProvider->view(/*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:
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include "Protocol.h"
|
||||
#include "refactor/Tweak.h"
|
||||
#include "support/Context.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/Logger.h"
|
||||
#include "support/Threading.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
@@ -575,12 +575,12 @@ llvm::Optional<FileDigest> digestFile(const SourceManager &SM, FileID FID) {
|
||||
return digest(Content);
|
||||
}
|
||||
|
||||
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());
|
||||
format::FormatStyle getFormatStyleForFile(llvm::StringRef File,
|
||||
llvm::StringRef Content,
|
||||
const ThreadsafeFS &FSProvider) {
|
||||
auto Style = format::getStyle(format::DefaultFormatStyle, File,
|
||||
format::DefaultFallbackStyle, Content,
|
||||
FSProvider.view(/*CWD=*/llvm::None).get());
|
||||
if (!Style) {
|
||||
log("getStyle() failed for file {0}: {1}. Fallback is LLVM style.", File,
|
||||
Style.takeError());
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "Protocol.h"
|
||||
#include "support/Context.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
@@ -168,7 +168,7 @@ llvm::Optional<std::string> getCanonicalPath(const FileEntry *F,
|
||||
/// though the latter may have been overridden in main()!
|
||||
format::FormatStyle getFormatStyleForFile(llvm::StringRef File,
|
||||
llvm::StringRef Content,
|
||||
const FileSystemProvider &FSProvider);
|
||||
const ThreadsafeFS &FSProvider);
|
||||
|
||||
/// Cleanup and format the given replacements.
|
||||
llvm::Expected<tooling::Replacements>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "ClangdServer.h"
|
||||
#include "CodeComplete.h"
|
||||
#include "refactor/Rename.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
@@ -31,7 +31,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
|
||||
auto Transport = newJSONTransport(In, llvm::nulls(),
|
||||
/*InMirror=*/nullptr, /*Pretty=*/false,
|
||||
/*Style=*/JSONStreamStyle::Delimited);
|
||||
RealFileSystemProvider FS;
|
||||
RealThreadsafeFS FS;
|
||||
CodeCompleteOptions CCOpts;
|
||||
CCOpts.EnableSnippets = false;
|
||||
ClangdServer::Options Opts;
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
#include "index/Serialization.h"
|
||||
#include "index/SymbolCollector.h"
|
||||
#include "support/Context.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/Logger.h"
|
||||
#include "support/Path.h"
|
||||
#include "support/Threading.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "support/Trace.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
@@ -90,7 +90,7 @@ bool shardIsStale(const LoadedShard &LS, llvm::vfs::FileSystem *FS) {
|
||||
} // namespace
|
||||
|
||||
BackgroundIndex::BackgroundIndex(
|
||||
Context BackgroundContext, const FileSystemProvider &FSProvider,
|
||||
Context BackgroundContext, const ThreadsafeFS &FSProvider,
|
||||
const GlobalCompilationDatabase &CDB,
|
||||
BackgroundIndexStorage::Factory IndexStorageFactory, size_t ThreadPoolSize,
|
||||
std::function<void(BackgroundQueue::Stats)> OnProgress)
|
||||
@@ -244,7 +244,7 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
|
||||
SPAN_ATTACH(Tracer, "file", Cmd.Filename);
|
||||
auto AbsolutePath = getAbsolutePath(Cmd);
|
||||
|
||||
auto FS = FSProvider.getFileSystem(Cmd.Directory);
|
||||
auto FS = FSProvider.view(Cmd.Directory);
|
||||
auto Buf = FS->getBufferForFile(AbsolutePath);
|
||||
if (!Buf)
|
||||
return llvm::errorCodeToError(Buf.getError());
|
||||
@@ -381,7 +381,7 @@ BackgroundIndex::loadProject(std::vector<std::string> MainFiles) {
|
||||
Rebuilder.loadedShard(LoadedShards);
|
||||
Rebuilder.doneLoading();
|
||||
|
||||
auto FS = FSProvider.getFileSystem(/*CWD=*/llvm::None);
|
||||
auto FS = FSProvider.view(/*CWD=*/llvm::None);
|
||||
llvm::DenseSet<PathRef> TUsToIndex;
|
||||
// We'll accept data from stale shards, but ensure the files get reindexed
|
||||
// soon.
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#include "index/Index.h"
|
||||
#include "index/Serialization.h"
|
||||
#include "support/Context.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/Path.h"
|
||||
#include "support/Threading.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "clang/Tooling/CompilationDatabase.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
/// rebuilt periodically (one per \p BuildIndexPeriodMs); otherwise, index is
|
||||
/// rebuilt for each indexed file.
|
||||
BackgroundIndex(
|
||||
Context BackgroundContext, const FileSystemProvider &,
|
||||
Context BackgroundContext, const ThreadsafeFS &,
|
||||
const GlobalCompilationDatabase &CDB,
|
||||
BackgroundIndexStorage::Factory IndexStorageFactory,
|
||||
size_t ThreadPoolSize = 0, // 0 = use all hardware threads
|
||||
@@ -178,7 +178,7 @@ private:
|
||||
bool HadErrors);
|
||||
|
||||
// configuration
|
||||
const FileSystemProvider &FSProvider;
|
||||
const ThreadsafeFS &FSProvider;
|
||||
const GlobalCompilationDatabase &CDB;
|
||||
Context BackgroundContext;
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ include_directories(..)
|
||||
add_clang_library(clangdSupport
|
||||
Cancellation.cpp
|
||||
Context.cpp
|
||||
FSProvider.cpp
|
||||
Logger.cpp
|
||||
Markup.cpp
|
||||
Shutdown.cpp
|
||||
Threading.cpp
|
||||
ThreadsafeFS.cpp
|
||||
Trace.cpp
|
||||
|
||||
LINK_LIBS
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
//===--- FSProvider.h - VFS provider for ClangdServer ------------*- C++-*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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>
|
||||
|
||||
namespace clang {
|
||||
namespace clangd {
|
||||
|
||||
// Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
|
||||
// As FileSystem is not threadsafe, concurrent threads must each obtain one.
|
||||
class FileSystemProvider {
|
||||
public:
|
||||
virtual ~FileSystemProvider() = default;
|
||||
/// Called by ClangdServer to obtain a vfs::FileSystem to be used for parsing.
|
||||
/// 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(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(llvm::NoneType) const override;
|
||||
};
|
||||
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
//===--- FSProvider.cpp - VFS provider for ClangdServer -------------------===//
|
||||
//===--- ThreadsafeFS.cpp -------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "Logger.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
@@ -75,15 +75,15 @@ private:
|
||||
} // namespace
|
||||
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
FileSystemProvider::getFileSystem(PathRef CWD) const {
|
||||
auto FS = getFileSystem(/*CWD=*/llvm::None);
|
||||
ThreadsafeFS::view(PathRef CWD) const {
|
||||
auto FS = view(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 {
|
||||
RealThreadsafeFS::view(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.
|
||||
52
clang-tools-extra/clangd/support/ThreadsafeFS.h
Normal file
52
clang-tools-extra/clangd/support/ThreadsafeFS.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//===--- ThreadsafeFS.h ------------------------------------------*- C++-*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADSAFEFS_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADSAFEFS_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>
|
||||
|
||||
namespace clang {
|
||||
namespace clangd {
|
||||
|
||||
/// Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
|
||||
/// As FileSystem is not threadsafe, concurrent threads must each obtain one.
|
||||
/// Implementations may choose to depend on Context::current() e.g. to implement
|
||||
/// snapshot semantics. clangd will not create vfs::FileSystems for use in
|
||||
/// different contexts, so either ThreadsafeFS::view or the returned FS may
|
||||
/// contain this logic.
|
||||
class ThreadsafeFS {
|
||||
public:
|
||||
virtual ~ThreadsafeFS() = default;
|
||||
|
||||
/// Obtain a vfs::FileSystem with an arbitrary initial working directory.
|
||||
virtual llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
view(llvm::NoneType CWD) const = 0;
|
||||
|
||||
/// Obtain a vfs::FileSystem with a specified working directory.
|
||||
/// If the working directory can't be set (e.g. doesn't exist), logs and
|
||||
/// returns the FS anyway.
|
||||
virtual llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
view(PathRef CWD) const;
|
||||
};
|
||||
|
||||
class RealThreadsafeFS : public ThreadsafeFS {
|
||||
public:
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
view(llvm::NoneType) const override;
|
||||
};
|
||||
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "refactor/Rename.h"
|
||||
#include "support/Path.h"
|
||||
#include "support/Shutdown.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "support/Trace.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Format/Format.h"
|
||||
@@ -675,7 +676,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
|
||||
CCOpts.AllScopes = AllScopesCompletion;
|
||||
CCOpts.RunParser = CodeCompletionParse;
|
||||
|
||||
RealFileSystemProvider FSProvider;
|
||||
RealThreadsafeFS FSProvider;
|
||||
// Initialize and run ClangdLSPServer.
|
||||
// Change stdin to binary to not lose \r\n on windows.
|
||||
llvm::sys::ChangeStdinToBinary();
|
||||
@@ -719,7 +720,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
|
||||
tidy::ClangTidyGlobalOptions(),
|
||||
/* Default */ EmptyDefaults,
|
||||
/* Override */ OverrideClangTidyOptions,
|
||||
FSProvider.getFileSystem(/*CWD=*/llvm::None));
|
||||
FSProvider.view(/*CWD=*/llvm::None));
|
||||
Opts.GetClangTidyOptions = [&](llvm::vfs::FileSystem &,
|
||||
llvm::StringRef File) {
|
||||
// This function must be thread-safe and tidy option providers are not.
|
||||
|
||||
@@ -86,7 +86,7 @@ protected:
|
||||
};
|
||||
|
||||
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[testPath("root/A.cc")] = "error file";
|
||||
llvm::StringMap<std::string> Storage;
|
||||
size_t CacheHits = 0;
|
||||
@@ -105,7 +105,7 @@ TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, IndexTwoFiles) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
// a.h yields different symbols when included by A.cc vs B.cc.
|
||||
FS.Files[testPath("root/A.h")] = R"cpp(
|
||||
void common();
|
||||
@@ -175,7 +175,7 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, ShardStorageTest) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[testPath("root/A.h")] = R"cpp(
|
||||
void common();
|
||||
void f_b();
|
||||
@@ -246,7 +246,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, DirectIncludesTest) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[testPath("root/B.h")] = "";
|
||||
FS.Files[testPath("root/A.h")] = R"cpp(
|
||||
#include "B.h"
|
||||
@@ -297,7 +297,7 @@ TEST_F(BackgroundIndexTest, DirectIncludesTest) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, ShardStorageLoad) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[testPath("root/A.h")] = R"cpp(
|
||||
void common();
|
||||
void f_b();
|
||||
@@ -368,7 +368,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[testPath("root/A.h")] = R"cpp(
|
||||
void common();
|
||||
void f_b();
|
||||
@@ -436,7 +436,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, NoDotsInAbsPath) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
llvm::StringMap<std::string> Storage;
|
||||
size_t CacheHits = 0;
|
||||
MemoryShardStorage MSS(Storage, CacheHits);
|
||||
@@ -467,7 +467,7 @@ TEST_F(BackgroundIndexTest, NoDotsInAbsPath) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, UncompilableFiles) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
llvm::StringMap<std::string> Storage;
|
||||
size_t CacheHits = 0;
|
||||
MemoryShardStorage MSS(Storage, CacheHits);
|
||||
@@ -530,7 +530,7 @@ TEST_F(BackgroundIndexTest, UncompilableFiles) {
|
||||
}
|
||||
|
||||
TEST_F(BackgroundIndexTest, CmdLineHash) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
llvm::StringMap<std::string> Storage;
|
||||
size_t CacheHits = 0;
|
||||
MemoryShardStorage MSS(Storage, CacheHits);
|
||||
|
||||
@@ -63,7 +63,7 @@ protected:
|
||||
stop();
|
||||
}
|
||||
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
CodeCompleteOptions CCOpts;
|
||||
RenameOptions RenameOpts;
|
||||
ClangdServer::Options Opts = ClangdServer::optsForTest();
|
||||
|
||||
@@ -145,7 +145,7 @@ protected:
|
||||
PathRef SourceFileRelPath, llvm::StringRef SourceContents,
|
||||
std::vector<std::pair<PathRef, llvm::StringRef>> ExtraFiles = {},
|
||||
bool ExpectErrors = false) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -198,7 +198,7 @@ int b = a;
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, Reparse) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -233,7 +233,7 @@ int b = a;
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, ReparseOnHeaderChange) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -272,9 +272,9 @@ int b = a;
|
||||
|
||||
TEST_F(ClangdVFSTest, PropagatesContexts) {
|
||||
static Key<int> Secret;
|
||||
struct FSProvider : public FileSystemProvider {
|
||||
struct FSProvider : public ThreadsafeFS {
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
getFileSystem(llvm::NoneType) const override {
|
||||
view(llvm::NoneType) const override {
|
||||
Got = Context::current().getExisting(Secret);
|
||||
return buildTestFS({});
|
||||
}
|
||||
@@ -302,7 +302,7 @@ TEST_F(ClangdVFSTest, PropagatesContexts) {
|
||||
|
||||
TEST_F(ClangdVFSTest, PropagatesVersion) {
|
||||
MockCompilationDatabase CDB;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
struct Callbacks : public ClangdServer::Callbacks {
|
||||
void onDiagnosticsReady(PathRef File, llvm::StringRef Version,
|
||||
std::vector<Diag> Diagnostics) override {
|
||||
@@ -321,7 +321,7 @@ TEST_F(ClangdVFSTest, PropagatesVersion) {
|
||||
#ifdef LLVM_ON_UNIX
|
||||
TEST_F(ClangdVFSTest, SearchLibDir) {
|
||||
// Checks that searches for GCC installation is done through vfs.
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
CDB.ExtraClangFlags.insert(CDB.ExtraClangFlags.end(),
|
||||
@@ -370,7 +370,7 @@ std::string x;
|
||||
#endif // LLVM_ON_UNIX
|
||||
|
||||
TEST_F(ClangdVFSTest, ForceReparseCompileCommand) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -406,7 +406,7 @@ struct bar { T x; };
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, ForceReparseCompileCommandDefines) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -458,7 +458,7 @@ this is an error
|
||||
int hello;
|
||||
)cpp");
|
||||
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
MultipleErrorCheckingCallbacks DiagConsumer;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -508,7 +508,7 @@ MATCHER_P4(Stats, Name, UsesMemory, PreambleBuilds, ASTBuilds, "") {
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, FileStats) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -544,7 +544,7 @@ struct Something {
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, InvalidCompileCommand) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
|
||||
@@ -605,7 +605,7 @@ int d;
|
||||
unsigned MaxColumnForFileRequests = 10;
|
||||
|
||||
std::vector<std::string> FilePaths;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
for (unsigned I = 0; I < FilesCount; ++I) {
|
||||
std::string Name = std::string("Foo") + std::to_string(I) + ".cpp";
|
||||
FS.Files[Name] = "";
|
||||
@@ -839,7 +839,7 @@ int d;
|
||||
)cpp";
|
||||
|
||||
auto FooCpp = testPath("foo.cpp");
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[FooCpp] = "";
|
||||
|
||||
std::promise<void> StartSecondPromise;
|
||||
@@ -856,7 +856,7 @@ int d;
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, FormatCode) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -885,7 +885,7 @@ void f() {}
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, ChangedHeaderFromISystem) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -924,13 +924,13 @@ TEST_F(ClangdVFSTest, ChangedHeaderFromISystem) {
|
||||
// Check that running code completion doesn't stat() a bunch of files from the
|
||||
// preamble again. (They should be using the preamble's stat-cache)
|
||||
TEST(ClangdTests, PreambleVFSStatCache) {
|
||||
class ListenStatsFSProvider : public FileSystemProvider {
|
||||
class ListenStatsFSProvider : public ThreadsafeFS {
|
||||
public:
|
||||
ListenStatsFSProvider(llvm::StringMap<unsigned> &CountStats)
|
||||
: CountStats(CountStats) {}
|
||||
|
||||
IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
getFileSystem(llvm::NoneType) const override {
|
||||
view(llvm::NoneType) const override {
|
||||
class ListenStatVFS : public llvm::vfs::ProxyFileSystem {
|
||||
public:
|
||||
ListenStatVFS(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
|
||||
@@ -990,7 +990,7 @@ TEST(ClangdTests, PreambleVFSStatCache) {
|
||||
#endif
|
||||
|
||||
TEST_F(ClangdVFSTest, FallbackWhenPreambleIsNotReady) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
@@ -1036,7 +1036,7 @@ TEST_F(ClangdVFSTest, FallbackWhenPreambleIsNotReady) {
|
||||
}
|
||||
|
||||
TEST_F(ClangdVFSTest, FallbackWhenWaitingForCompileCommand) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
// Returns compile command only when notified.
|
||||
class DelayedCompilationDatabase : public GlobalCompilationDatabase {
|
||||
@@ -1098,7 +1098,7 @@ TEST_F(ClangdVFSTest, FallbackWhenWaitingForCompileCommand) {
|
||||
// test as a workaround.
|
||||
#if !defined(__has_feature) || !__has_feature(address_sanitizer)
|
||||
TEST_F(ClangdVFSTest, TestStackOverflow) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ErrorCheckingCallbacks DiagConsumer;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer);
|
||||
|
||||
@@ -108,7 +108,7 @@ CodeCompleteResult completions(const TestTU &TU, Position Point,
|
||||
Opts.Index = OverrideIndex.get();
|
||||
}
|
||||
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto Inputs = TU.inputs(FS);
|
||||
Inputs.Opts.BuildRecoveryAST = true;
|
||||
Inputs.Opts.PreserveRecoveryASTType = true;
|
||||
@@ -149,7 +149,7 @@ CodeCompleteResult completionsNoCompile(llvm::StringRef Text,
|
||||
Opts.Index = OverrideIndex.get();
|
||||
}
|
||||
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
Annotations Test(Text);
|
||||
ParseInputs ParseInput{tooling::CompileCommand(), &FS, Test.code().str()};
|
||||
return codeComplete(FilePath, Test.point(), /*Preamble=*/nullptr, ParseInput,
|
||||
@@ -770,7 +770,7 @@ TEST(CompletionTest, CompletionRecoveryASTType) {
|
||||
}
|
||||
|
||||
TEST(CompletionTest, DynamicIndexIncludeInsertion) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer::Options Opts = ClangdServer::optsForTest();
|
||||
Opts.BuildDynamicSymbolIndex = true;
|
||||
@@ -805,7 +805,7 @@ TEST(CompletionTest, DynamicIndexIncludeInsertion) {
|
||||
}
|
||||
|
||||
TEST(CompletionTest, DynamicIndexMultiFile) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
auto Opts = ClangdServer::optsForTest();
|
||||
Opts.BuildDynamicSymbolIndex = true;
|
||||
@@ -865,7 +865,7 @@ TEST(CompletionTest, Documentation) {
|
||||
}
|
||||
|
||||
TEST(CompletionTest, CommentsFromSystemHeaders) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
|
||||
auto Opts = ClangdServer::optsForTest();
|
||||
@@ -1057,7 +1057,7 @@ SignatureHelp signatures(llvm::StringRef Text, Position Point,
|
||||
Index = memIndex(IndexSymbols);
|
||||
|
||||
auto TU = TestTU::withCode(Text);
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto Inputs = TU.inputs(FS);
|
||||
Inputs.Index = Index.get();
|
||||
Inputs.Opts.BuildRecoveryAST = true;
|
||||
@@ -1214,7 +1214,7 @@ TEST(SignatureHelpTest, StalePreamble) {
|
||||
TestTU TU;
|
||||
TU.Code = "";
|
||||
IgnoreDiagnostics Diags;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto Inputs = TU.inputs(FS);
|
||||
auto CI = buildCompilerInvocation(Inputs, Diags);
|
||||
ASSERT_TRUE(CI);
|
||||
@@ -1537,7 +1537,7 @@ TEST(CompletionTest, OverloadBundling) {
|
||||
}
|
||||
|
||||
TEST(CompletionTest, DocumentationFromChangedFileCrash) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto FooH = testPath("foo.h");
|
||||
auto FooCpp = testPath("foo.cpp");
|
||||
FS.Files[FooH] = R"cpp(
|
||||
@@ -1632,7 +1632,7 @@ TEST(CompletionTest, CompleteOnInvalidLine) {
|
||||
auto FooCpp = testPath("foo.cpp");
|
||||
|
||||
MockCompilationDatabase CDB;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[FooCpp] = "// empty file";
|
||||
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
||||
@@ -1761,7 +1761,7 @@ TEST(CompletionTest, CodeCompletionContext) {
|
||||
}
|
||||
|
||||
TEST(CompletionTest, FixItForArrowToDot) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
|
||||
CodeCompleteOptions Opts;
|
||||
@@ -1872,7 +1872,7 @@ TEST(CompletionTest, RenderWithFixItNonMerged) {
|
||||
}
|
||||
|
||||
TEST(CompletionTest, CompletionTokenRange) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
TestTU TU;
|
||||
TU.AdditionalFiles["foo/abc/foo.h"] = "";
|
||||
@@ -2037,7 +2037,7 @@ TEST(SignatureHelpTest, IndexDocumentation) {
|
||||
}
|
||||
|
||||
TEST(SignatureHelpTest, DynamicIndexDocumentation) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer::Options Opts = ClangdServer::optsForTest();
|
||||
Opts.BuildDynamicSymbolIndex = true;
|
||||
@@ -2209,7 +2209,7 @@ TEST(GuessCompletionPrefix, Filters) {
|
||||
}
|
||||
|
||||
TEST(CompletionTest, EnableSpeculativeIndexRequest) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace {
|
||||
using testing::IsEmpty;
|
||||
|
||||
TEST(BuildCompilerInvocation, DropsPCH) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
IgnoreDiagnostics Diags;
|
||||
TestTU TU;
|
||||
TU.AdditionalFiles["test.h.pch"] = "";
|
||||
|
||||
@@ -272,7 +272,7 @@ TEST(FileIndexTest, RebuildWithPreamble) {
|
||||
PI.CompileCommand.Filename = FooCpp;
|
||||
PI.CompileCommand.CommandLine = {"clang", "-xc++", FooCpp};
|
||||
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
FSProvider.Files[FooCpp] = "";
|
||||
FSProvider.Files[FooH] = R"cpp(
|
||||
namespace ns_in_header {
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server;
|
||||
int Limit = 0;
|
||||
@@ -310,7 +310,7 @@ public:
|
||||
DocumentSymbolsTest() : Server(CDB, FSProvider, optsForTests()) {}
|
||||
|
||||
protected:
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "TestFS.h"
|
||||
#include "TestTU.h"
|
||||
#include "index/MemIndex.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@@ -20,7 +21,7 @@ namespace clangd {
|
||||
namespace {
|
||||
|
||||
TEST(HeaderSourceSwitchTest, FileHeuristic) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto FooCpp = testPath("foo.cpp");
|
||||
auto FooH = testPath("foo.h");
|
||||
auto Invalid = testPath("main.cpp");
|
||||
@@ -29,11 +30,11 @@ TEST(HeaderSourceSwitchTest, FileHeuristic) {
|
||||
FS.Files[FooH];
|
||||
FS.Files[Invalid];
|
||||
Optional<Path> PathResult =
|
||||
getCorrespondingHeaderOrSource(FooCpp, FS.getFileSystem());
|
||||
getCorrespondingHeaderOrSource(FooCpp, FS.view(llvm::None));
|
||||
EXPECT_TRUE(PathResult.hasValue());
|
||||
ASSERT_EQ(PathResult.getValue(), FooH);
|
||||
|
||||
PathResult = getCorrespondingHeaderOrSource(FooH, FS.getFileSystem());
|
||||
PathResult = getCorrespondingHeaderOrSource(FooH, FS.view(llvm::None));
|
||||
EXPECT_TRUE(PathResult.hasValue());
|
||||
ASSERT_EQ(PathResult.getValue(), FooCpp);
|
||||
|
||||
@@ -44,7 +45,7 @@ TEST(HeaderSourceSwitchTest, FileHeuristic) {
|
||||
|
||||
FS.Files[FooC];
|
||||
FS.Files[FooHH];
|
||||
PathResult = getCorrespondingHeaderOrSource(FooC, FS.getFileSystem());
|
||||
PathResult = getCorrespondingHeaderOrSource(FooC, FS.view(llvm::None));
|
||||
EXPECT_TRUE(PathResult.hasValue());
|
||||
ASSERT_EQ(PathResult.getValue(), FooHH);
|
||||
|
||||
@@ -53,7 +54,7 @@ TEST(HeaderSourceSwitchTest, FileHeuristic) {
|
||||
auto Foo2HH = testPath("foo2.HH");
|
||||
FS.Files[Foo2C];
|
||||
FS.Files[Foo2HH];
|
||||
PathResult = getCorrespondingHeaderOrSource(Foo2C, FS.getFileSystem());
|
||||
PathResult = getCorrespondingHeaderOrSource(Foo2C, FS.view(llvm::None));
|
||||
EXPECT_TRUE(PathResult.hasValue());
|
||||
ASSERT_EQ(PathResult.getValue(), Foo2HH);
|
||||
|
||||
@@ -63,13 +64,13 @@ TEST(HeaderSourceSwitchTest, FileHeuristic) {
|
||||
|
||||
FS.Files[Foo3C];
|
||||
FS.Files[Foo3HXX];
|
||||
PathResult = getCorrespondingHeaderOrSource(Foo3C, FS.getFileSystem());
|
||||
PathResult = getCorrespondingHeaderOrSource(Foo3C, FS.view(llvm::None));
|
||||
EXPECT_TRUE(PathResult.hasValue());
|
||||
ASSERT_EQ(PathResult.getValue(), Foo3HXX);
|
||||
|
||||
// Test if asking for a corresponding file that doesn't exist returns an empty
|
||||
// string.
|
||||
PathResult = getCorrespondingHeaderOrSource(Invalid, FS.getFileSystem());
|
||||
PathResult = getCorrespondingHeaderOrSource(Invalid, FS.view(llvm::None));
|
||||
EXPECT_FALSE(PathResult.hasValue());
|
||||
}
|
||||
|
||||
@@ -252,7 +253,7 @@ TEST(HeaderSourceSwitchTest, ClangdServerIntegration) {
|
||||
MockCompilationDatabase CDB;
|
||||
CDB.ExtraClangFlags = {"-I" +
|
||||
testPath("src/include")}; // add search directory.
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
// File heuristic fails here, we rely on the index to find the .h file.
|
||||
std::string CppPath = testPath("src/lib/test.cpp");
|
||||
std::string HeaderPath = testPath("src/include/test.h");
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
EXPECT_TRUE(static_cast<bool>(CI));
|
||||
// The diagnostic options must be set before creating a CompilerInstance.
|
||||
CI->getDiagnosticOpts().IgnoreWarnings = true;
|
||||
auto VFS = PI.FSProvider->getFileSystem(Cmd->Directory);
|
||||
auto VFS = PI.FSProvider->view(Cmd->Directory);
|
||||
auto Clang = prepareCompilerInstance(
|
||||
std::move(CI), /*Preamble=*/nullptr,
|
||||
llvm::MemoryBuffer::getMemBuffer(FS.Files[MainFile], MainFile),
|
||||
@@ -120,7 +120,7 @@ protected:
|
||||
return Edit;
|
||||
}
|
||||
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
std::string MainFile = testPath("main.cpp");
|
||||
std::string Subdir = testPath("sub");
|
||||
|
||||
@@ -249,7 +249,7 @@ TEST(ParsedASTTest, NoCrashOnTokensWithTidyCheck) {
|
||||
}
|
||||
|
||||
TEST(ParsedASTTest, CanBuildInvocationWithUnknownArgs) {
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
FSProvider.Files = {{testPath("foo.cpp"), "void test() {}"}};
|
||||
// Unknown flags should not prevent a build of compiler invocation.
|
||||
ParseInputs Inputs;
|
||||
@@ -451,7 +451,7 @@ TEST(ParsedASTTest, ReplayPreambleForTidyCheckers) {
|
||||
llvm::StringLiteral Baseline = R"cpp(
|
||||
#include "a.h"
|
||||
#include "c.h")cpp";
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
TU.Code = Baseline.str();
|
||||
auto Inputs = TU.inputs(FS);
|
||||
auto BaselinePreamble = TU.preamble();
|
||||
@@ -539,7 +539,7 @@ TEST(ParsedASTTest, PatchesAdditionalIncludes) {
|
||||
// Build preamble with no includes.
|
||||
TU.Code = "";
|
||||
StoreDiags Diags;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto Inputs = TU.inputs(FS);
|
||||
auto CI = buildCompilerInvocation(Inputs, Diags);
|
||||
auto EmptyPreamble =
|
||||
@@ -582,7 +582,7 @@ TEST(ParsedASTTest, PatchesDeletedIncludes) {
|
||||
// Build preamble with no includes.
|
||||
TU.Code = R"cpp(#include <foo.h>)cpp";
|
||||
StoreDiags Diags;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto Inputs = TU.inputs(FS);
|
||||
auto CI = buildCompilerInvocation(Inputs, Diags);
|
||||
auto BaselinePreamble =
|
||||
|
||||
@@ -50,7 +50,7 @@ IncludeStructure
|
||||
collectPatchedIncludes(llvm::StringRef ModifiedContents,
|
||||
llvm::StringRef BaselineContents,
|
||||
llvm::StringRef MainFileName = "main.cpp") {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto TU = TestTU::withCode(BaselineContents);
|
||||
TU.Filename = MainFileName.str();
|
||||
// ms-compatibility changes meaning of #import, make sure it is turned off.
|
||||
@@ -74,7 +74,7 @@ collectPatchedIncludes(llvm::StringRef ModifiedContents,
|
||||
std::move(CI), &BaselinePreamble->Preamble,
|
||||
llvm::MemoryBuffer::getMemBufferCopy(
|
||||
ModifiedContents.slice(0, Bounds.Size).str()),
|
||||
PI.FSProvider->getFileSystem(PI.CompileCommand.Directory), Diags);
|
||||
PI.FSProvider->view(PI.CompileCommand.Directory), Diags);
|
||||
PreprocessOnlyAction Action;
|
||||
if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
|
||||
ADD_FAILURE() << "failed begin source file";
|
||||
@@ -165,7 +165,7 @@ TEST(PreamblePatchTest, MainFileIsEscaped) {
|
||||
}
|
||||
|
||||
TEST(PreamblePatchTest, PatchesPreambleIncludes) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
IgnoreDiagnostics Diags;
|
||||
auto TU = TestTU::withCode(R"cpp(
|
||||
#include "a.h"
|
||||
@@ -201,7 +201,7 @@ llvm::Optional<ParsedAST> createPatchedAST(llvm::StringRef Baseline,
|
||||
}
|
||||
|
||||
IgnoreDiagnostics Diags;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto TU = TestTU::withCode(Modified);
|
||||
auto CI = buildCompilerInvocation(TU.inputs(FS), Diags);
|
||||
if (!CI) {
|
||||
@@ -219,7 +219,7 @@ std::string getPreamblePatch(llvm::StringRef Baseline,
|
||||
ADD_FAILURE() << "Failed to build baseline preamble";
|
||||
return "";
|
||||
}
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
auto TU = TestTU::withCode(Modified);
|
||||
return PreamblePatch::create(testPath("main.cpp"), TU.inputs(FS),
|
||||
*BaselinePreamble)
|
||||
@@ -518,7 +518,7 @@ TEST(PreamblePatch, ModifiedBounds) {
|
||||
|
||||
Annotations Modified(Case.Modified);
|
||||
TU.Code = Modified.code().str();
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
auto PP = PreamblePatch::create(testPath(TU.Filename),
|
||||
TU.inputs(FSProvider), *BaselinePreamble);
|
||||
|
||||
|
||||
@@ -1027,7 +1027,7 @@ TEST(CrossFileRenameTests, WithUpToDateIndex) {
|
||||
std::string FooHPath = testPath("foo.h");
|
||||
std::string FooCCPath = testPath("foo.cc");
|
||||
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[FooHPath] = std::string(FooH.code());
|
||||
FS.Files[FooCCPath] = std::string(FooCC.code());
|
||||
|
||||
|
||||
@@ -728,7 +728,7 @@ TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
|
||||
};
|
||||
|
||||
auto FooCpp = testPath("foo.cpp");
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
FS.Files[FooCpp] = "";
|
||||
|
||||
MockCompilationDatabase MCD;
|
||||
|
||||
@@ -149,7 +149,7 @@ TEST(SemanticSelection, All) {
|
||||
}
|
||||
|
||||
TEST(SemanticSelection, RunViaClangdServer) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
#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"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "clang/Basic/DiagnosticDriver.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/FunctionExtras.h"
|
||||
@@ -150,7 +150,7 @@ protected:
|
||||
std::move(CB));
|
||||
}
|
||||
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
MockCompilationDatabase CDB;
|
||||
};
|
||||
|
||||
@@ -775,12 +775,11 @@ TEST_F(TUSchedulerTests, MissingHeader) {
|
||||
FSProvider.Timestamps[HeaderB] = time_t(1);
|
||||
|
||||
// The addition of the missing header file triggers a rebuild, no errors.
|
||||
updateWithDiags(
|
||||
S, Source, Inputs, WantDiagnostics::Yes,
|
||||
[&DiagCount](std::vector<Diag> Diags) {
|
||||
++DiagCount;
|
||||
EXPECT_THAT(Diags, IsEmpty());
|
||||
});
|
||||
updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
|
||||
[&DiagCount](std::vector<Diag> Diags) {
|
||||
++DiagCount;
|
||||
EXPECT_THAT(Diags, IsEmpty());
|
||||
});
|
||||
|
||||
// Ensure previous assertions are done before we touch the FS again.
|
||||
ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
|
||||
@@ -798,12 +797,12 @@ TEST_F(TUSchedulerTests, MissingHeader) {
|
||||
|
||||
// Forcing the reload should should cause a rebuild.
|
||||
Inputs.ForceRebuild = true;
|
||||
updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
|
||||
[&DiagCount](std::vector<Diag> Diags) {
|
||||
++DiagCount;
|
||||
ElementsAre(Field(&Diag::Message,
|
||||
"use of undeclared identifier 'b'"));
|
||||
});
|
||||
updateWithDiags(
|
||||
S, Source, Inputs, WantDiagnostics::Yes,
|
||||
[&DiagCount](std::vector<Diag> Diags) {
|
||||
++DiagCount;
|
||||
ElementsAre(Field(&Diag::Message, "use of undeclared identifier 'b'"));
|
||||
});
|
||||
|
||||
ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
|
||||
EXPECT_EQ(DiagCount, 3U);
|
||||
@@ -901,7 +900,7 @@ TEST_F(TUSchedulerTests, TUStatus) {
|
||||
std::vector<ASTAction::Kind> ASTActions;
|
||||
std::vector<PreambleAction> PreambleActions;
|
||||
} CaptureTUStatus;
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &CaptureTUStatus);
|
||||
Annotations Code("int m^ain () {}");
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTFS_H
|
||||
#include "ClangdServer.h"
|
||||
#include "GlobalCompilationDatabase.h"
|
||||
#include "support/FSProvider.h"
|
||||
#include "support/Path.h"
|
||||
#include "support/ThreadsafeFS.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
@@ -31,18 +31,11 @@ buildTestFS(llvm::StringMap<std::string> const &Files,
|
||||
llvm::StringMap<time_t> const &Timestamps = {});
|
||||
|
||||
// A VFS provider that returns TestFSes containing a provided set of files.
|
||||
class MockFSProvider : public FileSystemProvider {
|
||||
class MockFS : public ThreadsafeFS {
|
||||
public:
|
||||
// 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();
|
||||
view(llvm::NoneType) const override {
|
||||
return buildTestFS(Files, Timestamps);
|
||||
}
|
||||
|
||||
// If relative paths are used, they are resolved with testPath().
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
namespace clang {
|
||||
namespace clangd {
|
||||
|
||||
ParseInputs TestTU::inputs(MockFSProvider &FSProvider) const {
|
||||
ParseInputs TestTU::inputs(MockFS &FSProvider) const {
|
||||
std::string FullFilename = testPath(Filename),
|
||||
FullHeaderName = testPath(HeaderFilename),
|
||||
ImportThunk = testPath("import_thunk.h");
|
||||
@@ -67,7 +67,7 @@ ParseInputs TestTU::inputs(MockFSProvider &FSProvider) const {
|
||||
}
|
||||
|
||||
std::shared_ptr<const PreambleData> TestTU::preamble() const {
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
auto Inputs = inputs(FSProvider);
|
||||
IgnoreDiagnostics Diags;
|
||||
auto CI = buildCompilerInvocation(Inputs, Diags);
|
||||
@@ -78,7 +78,7 @@ std::shared_ptr<const PreambleData> TestTU::preamble() const {
|
||||
}
|
||||
|
||||
ParsedAST TestTU::build() const {
|
||||
MockFSProvider FSProvider;
|
||||
MockFS FSProvider;
|
||||
auto Inputs = inputs(FSProvider);
|
||||
StoreDiags Diags;
|
||||
auto CI = buildCompilerInvocation(Inputs, Diags);
|
||||
|
||||
@@ -70,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(MockFSProvider &FSProvider) const;
|
||||
ParseInputs inputs(MockFS &FSProvider) const;
|
||||
SymbolSlab headerSymbols() const;
|
||||
RefSlab headerRefs() const;
|
||||
std::unique_ptr<SymbolIndex> index() const;
|
||||
|
||||
@@ -974,7 +974,7 @@ int [[bar_not_preamble]];
|
||||
std::string BuildDir = testPath("build");
|
||||
MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
|
||||
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
||||
|
||||
// Fill the filesystem.
|
||||
@@ -1010,7 +1010,7 @@ int [[bar_not_preamble]];
|
||||
}
|
||||
|
||||
TEST(GoToInclude, All) {
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
||||
|
||||
@@ -1084,7 +1084,7 @@ TEST(GoToInclude, All) {
|
||||
TEST(LocateSymbol, WithPreamble) {
|
||||
// Test stragety: AST should always use the latest preamble instead of last
|
||||
// good preamble.
|
||||
MockFSProvider FS;
|
||||
MockFS FS;
|
||||
MockCompilationDatabase CDB;
|
||||
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user