ilya-biryukov created this revision.
ilya-biryukov added a reviewer: sammccall.
Herald added subscribers: ioeric, jkorous-apple, klimek.

To make the removal of DraftMgr from ClangdServer easier 
(https://reviews.llvm.org/D44408).


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D44462

Files:
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/TUScheduler.cpp
  clangd/TUScheduler.h

Index: clangd/TUScheduler.h
===================================================================
--- clangd/TUScheduler.h
+++ clangd/TUScheduler.h
@@ -59,6 +59,18 @@
   /// The order of results is unspecified.
   std::vector<std::pair<Path, std::size_t>> getUsedBytesPerFile() const;
 
+  /// Returns a list of currently tracked files. File starts being trakced on
+  /// first update() call to it and stops being tracked on remove() call.
+  std::vector<Path> getTrackedFiles() const;
+
+  /// Schedule a reparse for \p File with a new compile command. File must be
+  /// tracked.
+  /// FIXME: remove the callback from this function
+  void updateCompileCommand(PathRef File, tooling::CompileCommand NewCommand,
+                            IntrusiveRefCntPtr<vfs::FileSystem> FS,
+                            WantDiagnostics WantDiags,
+                            UniqueFunction<void(std::vector<Diag>)> OnUpdated);
+
   /// Schedule an update for \p File. Adds \p File to a list of tracked files if
   /// \p File was not part of it before.
   /// FIXME(ibiryukov): remove the callback from this function.
Index: clangd/TUScheduler.cpp
===================================================================
--- clangd/TUScheduler.cpp
+++ clangd/TUScheduler.cpp
@@ -110,6 +110,9 @@
   Deadline scheduleLocked();
   /// Should the first task in the queue be skipped instead of run?
   bool shouldSkipHeadLocked() const;
+  /// Rebuilds AST and pushes the new diagnostics, if required.
+  void rebuildASTLocked(WantDiagnostics WantDiags,
+                        UniqueFunction<void(std::vector<Diag>)> OnUpdated);
 
   struct Request {
     UniqueFunction<void()> Action;
@@ -213,20 +216,8 @@
 void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
                        UniqueFunction<void(std::vector<Diag>)> OnUpdated) {
   auto Task = [=](decltype(OnUpdated) OnUpdated) mutable {
-    FileInputs = Inputs;
-    auto Diags = AST.rebuild(std::move(Inputs));
-
-    {
-      std::lock_guard<std::mutex> Lock(Mutex);
-      if (AST.getPreamble())
-        LastBuiltPreamble = AST.getPreamble();
-      LastASTSize = AST.getUsedBytes();
-    }
-    // We want to report the diagnostics even if this update was cancelled.
-    // It seems more useful than making the clients wait indefinitely if they
-    // spam us with updates.
-    if (Diags && WantDiags != WantDiagnostics::No)
-      OnUpdated(std::move(*Diags));
+    FileInputs = std::move(Inputs);
+    rebuildASTLocked(WantDiags, std::move(OnUpdated));
   };
 
   startTask("Update", Bind(Task, std::move(OnUpdated)), WantDiags);
@@ -388,6 +379,23 @@
   llvm_unreachable("Unknown WantDiagnostics");
 }
 
+void ASTWorker::rebuildASTLocked(
+    WantDiagnostics WantDiags,
+    UniqueFunction<void(std::vector<Diag>)> OnUpdated) {
+  auto Diags = AST.rebuild(ParseInputs(FileInputs));
+  {
+    std::lock_guard<std::mutex> Lock(Mutex);
+    if (AST.getPreamble())
+      LastBuiltPreamble = AST.getPreamble();
+    LastASTSize = AST.getUsedBytes();
+  }
+  // We want to report the diagnostics even if this update was cancelled.
+  // It seems more useful than making the clients wait indefinitely if they
+  // spam us with updates.
+  if (Diags && WantDiags != WantDiagnostics::No)
+    OnUpdated(std::move(*Diags));
+}
+
 bool ASTWorker::blockUntilIdle(Deadline Timeout) const {
   std::unique_lock<std::mutex> Lock(Mutex);
   return wait(Lock, RequestsCV, Timeout, [&] { return Requests.empty(); });
@@ -446,6 +454,20 @@
   return true;
 }
 
+void TUScheduler::updateCompileCommand(
+    PathRef File, tooling::CompileCommand NewCommand,
+    IntrusiveRefCntPtr<vfs::FileSystem> FS, WantDiagnostics WantDiags,
+    UniqueFunction<void(std::vector<Diag>)> OnUpdated) {
+  auto FDIt = Files.find(File);
+  assert(FDIt != Files.end() &&
+         "calling updateCompileCommand on non-tracked file");
+
+  FDIt->second->Inputs.CompileCommand = std::move(NewCommand);
+  FDIt->second->Inputs.FS = std::move(FS);
+  FDIt->second->Worker->update(FDIt->second->Inputs, WantDiags,
+                               std::move(OnUpdated));
+}
+
 void TUScheduler::update(PathRef File, ParseInputs Inputs,
                          WantDiagnostics WantDiags,
                          UniqueFunction<void(std::vector<Diag>)> OnUpdated) {
@@ -533,5 +555,9 @@
   return Result;
 }
 
+std::vector<Path> TUScheduler::getTrackedFiles() const {
+  return std::vector<Path>(Files.keys().begin(), Files.keys().end());
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -240,9 +240,8 @@
   formatCode(llvm::StringRef Code, PathRef File,
              ArrayRef<tooling::Range> Ranges);
 
-  void scheduleReparseAndDiags(PathRef File, VersionedDraft Contents,
-                               WantDiagnostics WD,
-                               IntrusiveRefCntPtr<vfs::FileSystem> FS);
+  void consumeDiagnostics(PathRef File, DocVersion Version,
+                          std::vector<Diag> Diags);
 
   CompileArgsCache CompileArgs;
   DiagnosticsConsumer &DiagConsumer;
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -118,8 +118,14 @@
 void ClangdServer::addDocument(PathRef File, StringRef Contents,
                                WantDiagnostics WantDiags) {
   DocVersion Version = DraftMgr.updateDraft(File, Contents);
-  scheduleReparseAndDiags(File, VersionedDraft{Version, Contents.str()},
-                          WantDiags, FSProvider.getFileSystem());
+  ParseInputs Inputs = {CompileArgs.getCompileCommand(File),
+                        FSProvider.getFileSystem(), Contents.str()};
+
+  Path FileStr = File.str();
+  WorkScheduler.update(File, std::move(Inputs), WantDiags,
+                       [this, FileStr, Version](std::vector<Diag> Diags) {
+                         consumeDiagnostics(FileStr, Version, std::move(Diags));
+                       });
 }
 
 void ClangdServer::removeDocument(PathRef File) {
@@ -129,16 +135,18 @@
 }
 
 void ClangdServer::forceReparse(PathRef File) {
-  auto FileContents = DraftMgr.getDraft(File);
-  assert(FileContents.Draft &&
-         "forceReparse() was called for non-added document");
-
   // forceReparse promises to request new compilation flags from CDB, so we
   // remove any cahced flags.
   CompileArgs.invalidate(File);
 
-  scheduleReparseAndDiags(File, std::move(FileContents), WantDiagnostics::Yes,
-                          FSProvider.getFileSystem());
+  tooling::CompileCommand NewCommand = CompileArgs.getCompileCommand(File);
+  DocVersion Version = DraftMgr.getVersion(File);
+  Path FileStr = File.str();
+  WorkScheduler.updateCompileCommand(
+      File, std::move(NewCommand), FSProvider.getFileSystem(),
+      WantDiagnostics::Yes, [this, FileStr, Version](std::vector<Diag> Diags) {
+        consumeDiagnostics(FileStr, Version, std::move(Diags));
+      });
 }
 
 void ClangdServer::codeComplete(PathRef File, Position Pos,
@@ -499,38 +507,26 @@
   WorkScheduler.runWithAST("Hover", File, Bind(Action, std::move(CB)));
 }
 
-void ClangdServer::scheduleReparseAndDiags(
-    PathRef File, VersionedDraft Contents, WantDiagnostics WantDiags,
-    IntrusiveRefCntPtr<vfs::FileSystem> FS) {
-  tooling::CompileCommand Command = CompileArgs.getCompileCommand(File);
-
-  DocVersion Version = Contents.Version;
-  Path FileStr = File.str();
-
-  auto Callback = [this, Version, FileStr](std::vector<Diag> Diags) {
-    // We need to serialize access to resulting diagnostics to avoid calling
-    // `onDiagnosticsReady` in the wrong order.
-    std::lock_guard<std::mutex> DiagsLock(DiagnosticsMutex);
-    DocVersion &LastReportedDiagsVersion = ReportedDiagnosticVersions[FileStr];
-    // FIXME(ibiryukov): get rid of '<' comparison here. In the current
-    // implementation diagnostics will not be reported after version counters'
-    // overflow. This should not happen in practice, since DocVersion is a
-    // 64-bit unsigned integer.
-    if (Version < LastReportedDiagsVersion)
-      return;
-    LastReportedDiagsVersion = Version;
-
-    DiagConsumer.onDiagnosticsReady(FileStr, std::move(Diags));
-  };
-
-  WorkScheduler.update(File,
-                       ParseInputs{std::move(Command), std::move(FS),
-                                   std::move(*Contents.Draft)},
-                       WantDiags, std::move(Callback));
+void ClangdServer::consumeDiagnostics(PathRef File, DocVersion Version,
+                                      std::vector<Diag> Diags) {
+  // We need to serialize access to resulting diagnostics to avoid calling
+  // `onDiagnosticsReady` in the wrong order.
+  std::lock_guard<std::mutex> DiagsLock(DiagnosticsMutex);
+  DocVersion &LastReportedDiagsVersion = ReportedDiagnosticVersions[File];
+
+  // FIXME(ibiryukov): get rid of '<' comparison here. In the current
+  // implementation diagnostics will not be reported after version counters'
+  // overflow. This should not happen in practice, since DocVersion is a
+  // 64-bit unsigned integer.
+  if (Version < LastReportedDiagsVersion)
+    return;
+  LastReportedDiagsVersion = Version;
+
+  DiagConsumer.onDiagnosticsReady(File, std::move(Diags));
 }
 
 void ClangdServer::reparseOpenedFiles() {
-  for (const Path &FilePath : DraftMgr.getActiveFiles())
+  for (const Path &FilePath : WorkScheduler.getTrackedFiles())
     forceReparse(FilePath);
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to