summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/TUScheduler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/TUScheduler.cpp')
-rw-r--r--clang-tools-extra/clangd/TUScheduler.cpp42
1 files changed, 30 insertions, 12 deletions
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index a09bf3f6a43..7052feceb35 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -44,6 +44,7 @@
#include "TUScheduler.h"
#include "Cancellation.h"
#include "Compiler.h"
+#include "Diagnostics.h"
#include "GlobalCompilationDatabase.h"
#include "Logger.h"
#include "Trace.h"
@@ -365,6 +366,14 @@ ASTWorker::~ASTWorker() {
void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
llvm::StringRef TaskName = "Update";
auto Task = [=]() mutable {
+ auto RunPublish = [&](llvm::function_ref<void()> Publish) {
+ // Ensure we only publish results from the worker if the file was not
+ // removed, making sure there are not race conditions.
+ std::lock_guard<std::mutex> Lock(PublishMu);
+ if (CanPublishResults)
+ Publish();
+ };
+
// Get the actual command as `Inputs` does not have a command.
// FIXME: some build systems like Bazel will take time to preparing
// environment to build the file, it would be nice if we could emit a
@@ -394,8 +403,11 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
Inputs.CompileCommand.Directory,
llvm::join(Inputs.CompileCommand.CommandLine, " "));
// Rebuild the preamble and the AST.
+ StoreDiags CompilerInvocationDiagConsumer;
std::unique_ptr<CompilerInvocation> Invocation =
- buildCompilerInvocation(Inputs);
+ buildCompilerInvocation(Inputs, CompilerInvocationDiagConsumer);
+ std::vector<Diag> CompilerInvocationDiags =
+ CompilerInvocationDiagConsumer.take();
if (!Invocation) {
elog("Could not build CompilerInvocation for file {0}", FileName);
// Remove the old AST if it's still in cache.
@@ -403,6 +415,9 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
TUStatus::BuildDetails Details;
Details.BuildFailed = true;
emitTUStatus({TUAction::BuildingPreamble, TaskName}, &Details);
+ // Report the diagnostics we collected when parsing the command line.
+ Callbacks.onFailedAST(FileName, std::move(CompilerInvocationDiags),
+ RunPublish);
// Make sure anyone waiting for the preamble gets notified it could not
// be built.
PreambleWasBuilt.notify();
@@ -468,7 +483,8 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
if (!AST) {
llvm::Optional<ParsedAST> NewAST =
- buildAST(FileName, std::move(Invocation), Inputs, NewPreamble);
+ buildAST(FileName, std::move(Invocation), CompilerInvocationDiags,
+ Inputs, NewPreamble);
AST = NewAST ? std::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
if (!(*AST)) { // buildAST fails.
TUStatus::BuildDetails Details;
@@ -481,22 +497,22 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
Details.ReuseAST = true;
emitTUStatus({TUAction::BuildingFile, TaskName}, &Details);
}
+
// 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.
// Note *AST can still be null if buildAST fails.
if (*AST) {
trace::Span Span("Running main AST callback");
- auto RunPublish = [&](llvm::function_ref<void()> Publish) {
- // Ensure we only publish results from the worker if the file was not
- // removed, making sure there are not race conditions.
- std::lock_guard<std::mutex> Lock(PublishMu);
- if (CanPublishResults)
- Publish();
- };
Callbacks.onMainAST(FileName, **AST, RunPublish);
RanASTCallback = true;
+ } else {
+ // Failed to build the AST, at least report diagnostics from the command
+ // line if there were any.
+ // FIXME: we might have got more errors while trying to build the AST,
+ // surface them too.
+ Callbacks.onFailedAST(FileName, CompilerInvocationDiags, RunPublish);
}
// Stash the AST in the cache for further use.
IdleASTs.put(this, std::move(*AST));
@@ -513,14 +529,16 @@ void ASTWorker::runWithAST(
llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
auto CurrentInputs = getCurrentFileInputs();
if (!AST) {
- std::unique_ptr<CompilerInvocation> Invocation =
- buildCompilerInvocation(*CurrentInputs);
+ StoreDiags CompilerInvocationDiagConsumer;
+ std::unique_ptr<CompilerInvocation> Invocation = buildCompilerInvocation(
+ *CurrentInputs, CompilerInvocationDiagConsumer);
// Try rebuilding the AST.
llvm::Optional<ParsedAST> NewAST =
Invocation
? buildAST(FileName,
std::make_unique<CompilerInvocation>(*Invocation),
- *CurrentInputs, getPossiblyStalePreamble())
+ CompilerInvocationDiagConsumer.take(), *CurrentInputs,
+ getPossiblyStalePreamble())
: None;
AST = NewAST ? std::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
}
OpenPOWER on IntegriCloud