summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/Diagnostics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/Diagnostics.cpp')
-rw-r--r--clang-tools-extra/clangd/Diagnostics.cpp55
1 files changed, 45 insertions, 10 deletions
diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp
index 7f1ab06db9d..c9e1ed6bc68 100644
--- a/clang-tools-extra/clangd/Diagnostics.cpp
+++ b/clang-tools-extra/clangd/Diagnostics.cpp
@@ -16,11 +16,13 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Capacity.h"
@@ -393,6 +395,9 @@ int getSeverity(DiagnosticsEngine::Level L) {
}
std::vector<Diag> StoreDiags::take(const clang::tidy::ClangTidyContext *Tidy) {
+ // Do not forget to emit a pending diagnostic if there is one.
+ flushLastDiag();
+
// Fill in name/source now that we have all the context needed to map them.
for (auto &Diag : Output) {
if (const char *ClangDiag = getDiagnosticCode(Diag.ID)) {
@@ -448,7 +453,6 @@ void StoreDiags::BeginSourceFile(const LangOptions &Opts,
}
void StoreDiags::EndSourceFile() {
- flushLastDiag();
LangOpts = None;
}
@@ -467,10 +471,46 @@ static void writeCodeToFixMessage(llvm::raw_ostream &OS, llvm::StringRef Code) {
OS << "…";
}
+/// Fills \p D with all information, except the location-related bits.
+/// Also note that ID and Name are not part of clangd::DiagBase and should be
+/// set elsewhere.
+static void fillNonLocationData(DiagnosticsEngine::Level DiagLevel,
+ const clang::Diagnostic &Info,
+ clangd::DiagBase &D) {
+ llvm::SmallString<64> Message;
+ Info.FormatDiagnostic(Message);
+
+ D.Message = Message.str();
+ D.Severity = DiagLevel;
+ D.Category = DiagnosticIDs::getCategoryNameFromID(
+ DiagnosticIDs::getCategoryNumberForDiag(Info.getID()))
+ .str();
+}
+
void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &Info) {
DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
+ if (Info.getLocation().isInvalid()) {
+ // Handle diagnostics coming from command-line arguments. The source manager
+ // is *not* available at this point, so we cannot use it.
+ if (DiagLevel < DiagnosticsEngine::Level::Error) {
+ IgnoreDiagnostics::log(DiagLevel, Info);
+ return; // non-errors add too much noise, do not show them.
+ }
+
+ flushLastDiag();
+
+ LastDiag = Diag();
+ LastDiag->ID = Info.getID();
+ fillNonLocationData(DiagLevel, Info, *LastDiag);
+ LastDiag->InsideMainFile = true;
+ // Put it at the start of the main file, for a lack of a better place.
+ LastDiag->Range.start = Position{0, 0};
+ LastDiag->Range.end = Position{0, 0};
+ return;
+ }
+
if (!LangOpts || !Info.hasSourceManager()) {
IgnoreDiagnostics::log(DiagLevel, Info);
return;
@@ -480,18 +520,13 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
SourceManager &SM = Info.getSourceManager();
auto FillDiagBase = [&](DiagBase &D) {
- D.Range = diagnosticRange(Info, *LangOpts);
- llvm::SmallString<64> Message;
- Info.FormatDiagnostic(Message);
- D.Message = Message.str();
+ fillNonLocationData(DiagLevel, Info, D);
+
D.InsideMainFile = InsideMainFile;
+ D.Range = diagnosticRange(Info, *LangOpts);
D.File = SM.getFilename(Info.getLocation());
D.AbsFile = getCanonicalPath(
SM.getFileEntryForID(SM.getFileID(Info.getLocation())), SM);
- D.Severity = DiagLevel;
- D.Category = DiagnosticIDs::getCategoryNameFromID(
- DiagnosticIDs::getCategoryNumberForDiag(Info.getID()))
- .str();
return D;
};
@@ -564,7 +599,6 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
LastDiag = Diag();
LastDiag->ID = Info.getID();
FillDiagBase(*LastDiag);
- LastDiagWasAdjusted = false;
if (!InsideMainFile)
LastDiagWasAdjusted = adjustDiagFromHeader(*LastDiag, Info, *LangOpts);
@@ -617,6 +651,7 @@ void StoreDiags::flushLastDiag() {
vlog("Dropped diagnostic: {0}: {1}", LastDiag->File, LastDiag->Message);
}
LastDiag.reset();
+ LastDiagWasAdjusted = false;
}
} // namespace clangd
OpenPOWER on IntegriCloud