Index: clang-tools-extra/trunk/clangd/ClangdServer.h =================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.h +++ clang-tools-extra/trunk/clangd/ClangdServer.h @@ -50,6 +50,12 @@ virtual void onFileUpdated(PathRef File, const TUStatus &Status){}; }; +/// When set, used by ClangdServer to get clang-tidy options for each particular +/// file. Must be thread-safe. We use this instead of ClangTidyOptionsProvider +/// to allow reading tidy configs from the VFS used for parsing. +using ClangTidyOptionsBuilder = std::function; + /// Manages a collection of source files and derived data (ASTs, indexes), /// and provides language-aware features such as code completion. /// @@ -94,12 +100,12 @@ /// If set, use this index to augment code completion results. SymbolIndex *StaticIndex = nullptr; - /// If set, enable clang-tidy in clangd, used to get clang-tidy + /// If set, enable clang-tidy in clangd and use to it get clang-tidy /// configurations for a particular file. /// Clangd supports only a small subset of ClangTidyOptions, these options /// (Checks, CheckOptions) are about which clang-tidy checks will be /// enabled. - tidy::ClangTidyOptionsProvider *ClangTidyOptProvider = nullptr; + ClangTidyOptionsBuilder GetClangTidyOptions; /// Clangd's workspace root. Relevant for "workspace" operations not bound /// to a particular file. @@ -278,8 +284,8 @@ // Storage for merged views of the various indexes. std::vector> MergedIdx; - // The provider used to provide a clang-tidy option for a specific file. - tidy::ClangTidyOptionsProvider *ClangTidyOptProvider = nullptr; + // When set, provides clang-tidy options for a specific file. + ClangTidyOptionsBuilder GetClangTidyOptions; // If this is true, suggest include insertion fixes for diagnostic errors that // can be caused by missing includes (e.g. member access in incomplete type). Index: clang-tools-extra/trunk/clangd/ClangdServer.cpp =================================================================== --- clang-tools-extra/trunk/clangd/ClangdServer.cpp +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp @@ -90,7 +90,7 @@ DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex) : nullptr), - ClangTidyOptProvider(Opts.ClangTidyOptProvider), + GetClangTidyOptions(Opts.GetClangTidyOptions), SuggestMissingIncludes(Opts.SuggestMissingIncludes), WorkspaceRoot(Opts.WorkspaceRoot), // Pass a callback into `WorkScheduler` to extract symbols from a newly @@ -126,15 +126,18 @@ void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents, WantDiagnostics WantDiags) { + auto FS = FSProvider.getFileSystem(); + ParseOptions Opts; Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults(); - if (ClangTidyOptProvider) - Opts.ClangTidyOpts = ClangTidyOptProvider->getOptions(File); + // FIXME: call tidy options builder on the worker thread, it can do IO. + if (GetClangTidyOptions) + Opts.ClangTidyOpts = GetClangTidyOptions(*FS, File); Opts.SuggestMissingIncludes = SuggestMissingIncludes; // Compile command is set asynchronously during update, as it can be slow. ParseInputs Inputs; - Inputs.FS = FSProvider.getFileSystem(); + Inputs.FS = FS; Inputs.Contents = Contents; Inputs.Opts = std::move(Opts); Inputs.Index = Index; Index: clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp =================================================================== --- clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp +++ clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/Version.h" #include "clang/Format/Format.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -496,7 +498,9 @@ } // Create an empty clang-tidy option. - std::unique_ptr ClangTidyOptProvider; + std::mutex ClangTidyOptMu; + std::unique_ptr + ClangTidyOptProvider; /*GUARDED_BY(ClangTidyOptMu)*/ if (EnableClangTidy) { auto OverrideClangTidyOptions = tidy::ClangTidyOptions::getDefaults(); OverrideClangTidyOptions.Checks = ClangTidyChecks; @@ -505,7 +509,13 @@ /* Default */ tidy::ClangTidyOptions::getDefaults(), /* Override */ OverrideClangTidyOptions, FSProvider.getFileSystem()); } - Opts.ClangTidyOptProvider = ClangTidyOptProvider.get(); + Opts.GetClangTidyOptions = [&](llvm::vfs::FileSystem &, + llvm::StringRef File) { + // This function must be thread-safe and tidy option providers are not. + std::lock_guard Lock(ClangTidyOptMu); + // FIXME: use the FS provided to the function. + return ClangTidyOptProvider->getOptions(File); + }; Opts.SuggestMissingIncludes = SuggestMissingIncludes; llvm::Optional OffsetEncodingFromFlag; if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)