LCOV - code coverage report
Current view: top level - clang/tools/extra/clangd - ClangdServer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 0 1 0.0 %
Date: 2018-10-20 13:21:21 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- ClangdServer.h - Main clangd server code ----------------*- C++-*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
      11             : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
      12             : 
      13             : #include "Cancellation.h"
      14             : #include "ClangdUnit.h"
      15             : #include "CodeComplete.h"
      16             : #include "FSProvider.h"
      17             : #include "Function.h"
      18             : #include "GlobalCompilationDatabase.h"
      19             : #include "Protocol.h"
      20             : #include "TUScheduler.h"
      21             : #include "index/FileIndex.h"
      22             : #include "index/Index.h"
      23             : #include "clang/Tooling/CompilationDatabase.h"
      24             : #include "clang/Tooling/Core/Replacement.h"
      25             : #include "llvm/ADT/IntrusiveRefCntPtr.h"
      26             : #include "llvm/ADT/Optional.h"
      27             : #include "llvm/ADT/StringRef.h"
      28             : #include <functional>
      29             : #include <future>
      30             : #include <string>
      31             : #include <type_traits>
      32             : #include <utility>
      33             : 
      34             : namespace clang {
      35             : class PCHContainerOperations;
      36             : 
      37             : namespace clangd {
      38             : 
      39             : class DiagnosticsConsumer {
      40             : public:
      41           0 :   virtual ~DiagnosticsConsumer() = default;
      42             : 
      43             :   /// Called by ClangdServer when \p Diagnostics for \p File are ready.
      44             :   virtual void onDiagnosticsReady(PathRef File,
      45             :                                   std::vector<Diag> Diagnostics) = 0;
      46             : };
      47             : 
      48             : /// Manages a collection of source files and derived data (ASTs, indexes),
      49             : /// and provides language-aware features such as code completion.
      50             : ///
      51             : /// The primary client is ClangdLSPServer which exposes these features via
      52             : /// the Language Server protocol. ClangdServer may also be embedded directly,
      53             : /// though its API is not stable over time.
      54             : ///
      55             : /// ClangdServer should be used from a single thread. Many potentially-slow
      56             : /// operations have asynchronous APIs and deliver their results on another
      57             : /// thread.
      58             : /// Such operations support cancellation: if the caller sets up a cancelable
      59             : /// context, many operations will notice cancellation and fail early.
      60             : /// (ClangdLSPServer uses this to implement $/cancelRequest).
      61             : class ClangdServer {
      62             : public:
      63             :   struct Options {
      64             :     /// To process requests asynchronously, ClangdServer spawns worker threads.
      65             :     /// If this is zero, no threads are spawned. All work is done on the calling
      66             :     /// thread, and callbacks are invoked before "async" functions return.
      67             :     unsigned AsyncThreadsCount = getDefaultAsyncThreadsCount();
      68             : 
      69             :     /// AST caching policy. The default is to keep up to 3 ASTs in memory.
      70             :     ASTRetentionPolicy RetentionPolicy;
      71             : 
      72             :     /// Cached preambles are potentially large. If false, store them on disk.
      73             :     bool StorePreamblesInMemory = true;
      74             : 
      75             :     /// If true, ClangdServer builds a dynamic in-memory index for symbols in
      76             :     /// opened files and uses the index to augment code completion results.
      77             :     bool BuildDynamicSymbolIndex = false;
      78             :     /// Use a heavier and faster in-memory index implementation.
      79             :     /// FIXME: we should make this true if it isn't too slow to build!.
      80             :     bool HeavyweightDynamicSymbolIndex = false;
      81             : 
      82             :     /// URI schemes to use when building the dynamic index.
      83             :     /// If empty, the default schemes in SymbolCollector will be used.
      84             :     std::vector<std::string> URISchemes;
      85             : 
      86             :     /// If set, use this index to augment code completion results.
      87             :     SymbolIndex *StaticIndex = nullptr;
      88             : 
      89             :     /// The resource directory is used to find internal headers, overriding
      90             :     /// defaults and -resource-dir compiler flag).
      91             :     /// If None, ClangdServer calls CompilerInvocation::GetResourcePath() to
      92             :     /// obtain the standard resource directory.
      93             :     llvm::Optional<std::string> ResourceDir = llvm::None;
      94             : 
      95             :     /// Time to wait after a new file version before computing diagnostics.
      96             :     std::chrono::steady_clock::duration UpdateDebounce =
      97             :         std::chrono::milliseconds(500);
      98             :   };
      99             :   // Sensible default options for use in tests.
     100             :   // Features like indexing must be enabled if desired.
     101             :   static Options optsForTest();
     102             : 
     103             :   /// Creates a new ClangdServer instance.
     104             :   ///
     105             :   /// ClangdServer uses \p CDB to obtain compilation arguments for parsing. Note
     106             :   /// that ClangdServer only obtains compilation arguments once for each newly
     107             :   /// added file (i.e., when processing a first call to addDocument) and reuses
     108             :   /// those arguments for subsequent reparses. However, ClangdServer will check
     109             :   /// if compilation arguments changed on calls to forceReparse().
     110             :   ///
     111             :   /// After each parsing request finishes, ClangdServer reports diagnostics to
     112             :   /// \p DiagConsumer. Note that a callback to \p DiagConsumer happens on a
     113             :   /// worker thread. Therefore, instances of \p DiagConsumer must properly
     114             :   /// synchronize access to shared state.
     115             :   ClangdServer(const GlobalCompilationDatabase &CDB,
     116             :                const FileSystemProvider &FSProvider,
     117             :                DiagnosticsConsumer &DiagConsumer, const Options &Opts);
     118             : 
     119             :   /// Set the root path of the workspace.
     120             :   void setRootPath(PathRef RootPath);
     121             : 
     122             :   /// Add a \p File to the list of tracked C++ files or update the contents if
     123             :   /// \p File is already tracked. Also schedules parsing of the AST for it on a
     124             :   /// separate thread. When the parsing is complete, DiagConsumer passed in
     125             :   /// constructor will receive onDiagnosticsReady callback.
     126             :   void addDocument(PathRef File, StringRef Contents,
     127             :                    WantDiagnostics WD = WantDiagnostics::Auto);
     128             : 
     129             :   /// Remove \p File from list of tracked files, schedule a request to free
     130             :   /// resources associated with it.
     131             :   void removeDocument(PathRef File);
     132             : 
     133             :   /// Run code completion for \p File at \p Pos.
     134             :   /// Request is processed asynchronously.
     135             :   ///
     136             :   /// This method should only be called for currently tracked files. However, it
     137             :   /// is safe to call removeDocument for \p File after this method returns, even
     138             :   /// while returned future is not yet ready.
     139             :   /// A version of `codeComplete` that runs \p Callback on the processing thread
     140             :   /// when codeComplete results become available.
     141             :   void codeComplete(PathRef File, Position Pos,
     142             :                     const clangd::CodeCompleteOptions &Opts,
     143             :                     Callback<CodeCompleteResult> CB);
     144             : 
     145             :   /// Provide signature help for \p File at \p Pos.  This method should only be
     146             :   /// called for tracked files.
     147             :   void signatureHelp(PathRef File, Position Pos, Callback<SignatureHelp> CB);
     148             : 
     149             :   /// Get definition of symbol at a specified \p Line and \p Column in \p File.
     150             :   void findDefinitions(PathRef File, Position Pos,
     151             :                        Callback<std::vector<Location>> CB);
     152             : 
     153             :   /// Helper function that returns a path to the corresponding source file when
     154             :   /// given a header file and vice versa.
     155             :   llvm::Optional<Path> switchSourceHeader(PathRef Path);
     156             : 
     157             :   /// Get document highlights for a given position.
     158             :   void findDocumentHighlights(PathRef File, Position Pos,
     159             :                               Callback<std::vector<DocumentHighlight>> CB);
     160             : 
     161             :   /// Get code hover for a given position.
     162             :   void findHover(PathRef File, Position Pos,
     163             :                  Callback<llvm::Optional<Hover>> CB);
     164             : 
     165             :   /// Retrieve the top symbols from the workspace matching a query.
     166             :   void workspaceSymbols(StringRef Query, int Limit,
     167             :                         Callback<std::vector<SymbolInformation>> CB);
     168             : 
     169             :   /// Retrieve the symbols within the specified file.
     170             :   void documentSymbols(StringRef File,
     171             :                        Callback<std::vector<SymbolInformation>> CB);
     172             : 
     173             :   /// Retrieve locations for symbol references.
     174             :   void findReferences(PathRef File, Position Pos,
     175             :                       Callback<std::vector<Location>> CB);
     176             : 
     177             :   /// Run formatting for \p Rng inside \p File with content \p Code.
     178             :   llvm::Expected<tooling::Replacements> formatRange(StringRef Code,
     179             :                                                     PathRef File, Range Rng);
     180             : 
     181             :   /// Run formatting for the whole \p File with content \p Code.
     182             :   llvm::Expected<tooling::Replacements> formatFile(StringRef Code,
     183             :                                                    PathRef File);
     184             : 
     185             :   /// Run formatting after a character was typed at \p Pos in \p File with
     186             :   /// content \p Code.
     187             :   llvm::Expected<tooling::Replacements>
     188             :   formatOnType(StringRef Code, PathRef File, Position Pos);
     189             : 
     190             :   /// Rename all occurrences of the symbol at the \p Pos in \p File to
     191             :   /// \p NewName.
     192             :   void rename(PathRef File, Position Pos, llvm::StringRef NewName,
     193             :               Callback<std::vector<tooling::Replacement>> CB);
     194             : 
     195             :   /// Only for testing purposes.
     196             :   /// Waits until all requests to worker thread are finished and dumps AST for
     197             :   /// \p File. \p File must be in the list of added documents.
     198             :   void dumpAST(PathRef File, llvm::unique_function<void(std::string)> Callback);
     199             :   /// Called when an event occurs for a watched file in the workspace.
     200             :   void onFileEvent(const DidChangeWatchedFilesParams &Params);
     201             : 
     202             :   /// Returns estimated memory usage for each of the currently open files.
     203             :   /// The order of results is unspecified.
     204             :   /// Overall memory usage of clangd may be significantly more than reported
     205             :   /// here, as this metric does not account (at least) for:
     206             :   ///   - memory occupied by static and dynamic index,
     207             :   ///   - memory required for in-flight requests,
     208             :   /// FIXME: those metrics might be useful too, we should add them.
     209             :   std::vector<std::pair<Path, std::size_t>> getUsedBytesPerFile() const;
     210             : 
     211             :   /// Returns the active dynamic index if one was built.
     212             :   /// This can be useful for testing, debugging, or observing memory usage.
     213             :   const SymbolIndex *dynamicIndex() const { return DynamicIdx.get(); }
     214             : 
     215             :   // Blocks the main thread until the server is idle. Only for use in tests.
     216             :   // Returns false if the timeout expires.
     217             :   LLVM_NODISCARD bool
     218             :   blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds = 10);
     219             : 
     220             : private:
     221             :   /// FIXME: This stats several files to find a .clang-format file. I/O can be
     222             :   /// slow. Think of a way to cache this.
     223             :   llvm::Expected<tooling::Replacements>
     224             :   formatCode(llvm::StringRef Code, PathRef File,
     225             :              ArrayRef<tooling::Range> Ranges);
     226             : 
     227             :   typedef uint64_t DocVersion;
     228             : 
     229             :   void consumeDiagnostics(PathRef File, DocVersion Version,
     230             :                           std::vector<Diag> Diags);
     231             : 
     232             :   tooling::CompileCommand getCompileCommand(PathRef File);
     233             : 
     234             :   const GlobalCompilationDatabase &CDB;
     235             :   DiagnosticsConsumer &DiagConsumer;
     236             :   const FileSystemProvider &FSProvider;
     237             : 
     238             :   /// Used to synchronize diagnostic responses for added and removed files.
     239             :   llvm::StringMap<DocVersion> InternalVersion;
     240             : 
     241             :   Path ResourceDir;
     242             :   // The index used to look up symbols. This could be:
     243             :   //   - null (all index functionality is optional)
     244             :   //   - the dynamic index owned by ClangdServer (DynamicIdx)
     245             :   //   - the static index passed to the constructor
     246             :   //   - a merged view of a static and dynamic index (MergedIndex)
     247             :   const SymbolIndex *Index;
     248             :   // If present, an index of symbols in open files. Read via *Index.
     249             :   std::unique_ptr<FileIndex> DynamicIdx;
     250             :   // If present, storage for the merged static/dynamic index. Read via *Index.
     251             :   std::unique_ptr<SymbolIndex> MergedIdx;
     252             : 
     253             :   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
     254             :   llvm::StringMap<llvm::Optional<FuzzyFindRequest>>
     255             :       CachedCompletionFuzzyFindRequestByFile;
     256             :   mutable std::mutex CachedCompletionFuzzyFindRequestMutex;
     257             : 
     258             :   // If set, this represents the workspace path.
     259             :   llvm::Optional<std::string> RootPath;
     260             :   std::shared_ptr<PCHContainerOperations> PCHs;
     261             :   /// Used to serialize diagnostic callbacks.
     262             :   /// FIXME(ibiryukov): get rid of an extra map and put all version counters
     263             :   /// into CppFile.
     264             :   std::mutex DiagnosticsMutex;
     265             :   /// Maps from a filename to the latest version of reported diagnostics.
     266             :   llvm::StringMap<DocVersion> ReportedDiagnosticVersions;
     267             :   // WorkScheduler has to be the last member, because its destructor has to be
     268             :   // called before all other members to stop the worker thread that references
     269             :   // ClangdServer.
     270             :   TUScheduler WorkScheduler;
     271             : };
     272             : 
     273             : } // namespace clangd
     274             : } // namespace clang
     275             : 
     276             : #endif

Generated by: LCOV version 1.13