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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits