summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/ASTManager.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/ASTManager.h')
-rw-r--r--clang-tools-extra/clangd/ASTManager.h162
1 files changed, 162 insertions, 0 deletions
diff --git a/clang-tools-extra/clangd/ASTManager.h b/clang-tools-extra/clangd/ASTManager.h
new file mode 100644
index 00000000000..e213822a845
--- /dev/null
+++ b/clang-tools-extra/clangd/ASTManager.h
@@ -0,0 +1,162 @@
+//===--- ASTManager.h - Clang AST manager -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTMANAGER_H
+
+#include "DocumentStore.h"
+#include "JSONRPCDispatcher.h"
+#include "Protocol.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <condition_variable>
+#include <deque>
+#include <thread>
+
+namespace clang {
+class ASTUnit;
+class DiagnosticsEngine;
+class PCHContainerOperations;
+namespace tooling {
+class CompilationDatabase;
+} // namespace tooling
+
+namespace clangd {
+
+/// Using 'unsigned' here to avoid undefined behaviour on overflow.
+typedef unsigned DocVersion;
+
+/// Stores ASTUnit and FixIts map for an opened document.
+class DocData {
+public:
+ typedef std::map<clangd::Diagnostic, std::vector<clang::tooling::Replacement>>
+ DiagnosticToReplacementMap;
+
+public:
+ void setAST(std::unique_ptr<ASTUnit> AST);
+ ASTUnit *getAST() const;
+
+ void cacheFixIts(DiagnosticToReplacementMap FixIts);
+ std::vector<clang::tooling::Replacement>
+ getFixIts(const clangd::Diagnostic &D) const;
+
+private:
+ std::unique_ptr<ASTUnit> AST;
+ DiagnosticToReplacementMap FixIts;
+};
+
+enum class ASTManagerRequestType { ParseAndPublishDiagnostics, RemoveDocData };
+
+/// A request to the worker thread
+class ASTManagerRequest {
+public:
+ ASTManagerRequest() = default;
+ ASTManagerRequest(ASTManagerRequestType Type, std::string File,
+ DocVersion Version);
+
+ ASTManagerRequestType Type;
+ std::string File;
+ DocVersion Version;
+};
+
+class ASTManager : public DocumentStoreListener {
+public:
+ ASTManager(JSONOutput &Output, DocumentStore &Store, bool RunSynchronously);
+ ~ASTManager() override;
+
+ void onDocumentAdd(StringRef File) override;
+ void onDocumentRemove(StringRef File) override;
+
+ /// Get code completions at a specified \p Line and \p Column in \p File.
+ ///
+ /// This function is thread-safe and returns completion items that own the
+ /// data they contain.
+ std::vector<CompletionItem> codeComplete(StringRef File, unsigned Line,
+ unsigned Column);
+
+ /// Get the fixes associated with a certain diagnostic in a specified file as
+ /// replacements.
+ ///
+ /// This function is thread-safe. It returns a copy to avoid handing out
+ /// references to unguarded data.
+ std::vector<clang::tooling::Replacement>
+ getFixIts(StringRef File, const clangd::Diagnostic &D);
+
+ DocumentStore &getStore() const { return Store; }
+
+private:
+ JSONOutput &Output;
+ DocumentStore &Store;
+
+ // Set to true if requests should block instead of being processed
+ // asynchronously.
+ bool RunSynchronously;
+
+ /// Loads a compilation database for File. May return nullptr if it fails. The
+ /// database is cached for subsequent accesses.
+ clang::tooling::CompilationDatabase *
+ getOrCreateCompilationDatabaseForFile(StringRef File);
+ // Creates a new ASTUnit for the document at File.
+ // FIXME: This calls chdir internally, which is thread unsafe.
+ std::unique_ptr<clang::ASTUnit>
+ createASTUnitForFile(StringRef File, const DocumentStore &Docs);
+
+ /// If RunSynchronously is false, queues the request to be run on the worker
+ /// thread.
+ /// If RunSynchronously is true, runs the request handler immediately on the
+ /// main thread.
+ void queueOrRun(ASTManagerRequestType RequestType, StringRef File);
+
+ void runWorker();
+ void handleRequest(ASTManagerRequestType RequestType, StringRef File);
+
+ /// Parses files and publishes diagnostics.
+ /// This function is called on the worker thread in asynchronous mode and
+ /// on the main thread in synchronous mode.
+ void parseFileAndPublishDiagnostics(StringRef File);
+
+ /// Caches compilation databases loaded from directories(keys are directories).
+ llvm::StringMap<std::unique_ptr<clang::tooling::CompilationDatabase>>
+ CompilationDatabases;
+
+ /// Clang objects.
+ /// A map from filenames to DocData structures that store ASTUnit and Fixits for
+ /// the files. The ASTUnits are used for generating diagnostics and fix-it-s
+ /// asynchronously by the worker thread and synchronously for code completion.
+ llvm::StringMap<DocData> DocDatas;
+ std::shared_ptr<clang::PCHContainerOperations> PCHs;
+ /// A lock for access to the DocDatas, CompilationDatabases and PCHs.
+ std::mutex ClangObjectLock;
+
+ /// Stores latest versions of the tracked documents to discard outdated requests.
+ /// Guarded by RequestLock.
+ /// TODO(ibiryukov): the entries are neved deleted from this map.
+ llvm::StringMap<DocVersion> DocVersions;
+
+ /// A LIFO queue of requests. Note that requests are discarded if the `version`
+ /// field is not equal to the one stored inside DocVersions.
+ /// TODO(krasimir): code completion should always have priority over parsing
+ /// for diagnostics.
+ std::deque<ASTManagerRequest> RequestQueue;
+ /// Setting Done to true will make the worker thread terminate.
+ bool Done = false;
+ /// Condition variable to wake up the worker thread.
+ std::condition_variable ClangRequestCV;
+ /// Lock for accesses to RequestQueue, DocVersions and Done.
+ std::mutex RequestLock;
+
+ /// We run parsing on a separate thread. This thread looks into RequestQueue to
+ /// find requests to handle and terminates when Done is set to true.
+ std::thread ClangWorker;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif
OpenPOWER on IntegriCloud