forked from OSchip/llvm-project
163 lines
5.5 KiB
C++
163 lines
5.5 KiB
C++
//===--- 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
|