clang-tools 24.0.0git
Diagnostics.h
Go to the documentation of this file.
1//===--- Diagnostics.h -------------------------------------------*- C++-*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H
11
12#include "Protocol.h"
13#include "clang/Basic/Diagnostic.h"
14#include "clang/Basic/LangOptions.h"
15#include "clang/Basic/SourceLocation.h"
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/DenseSet.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/StringSet.h"
20#include "llvm/Support/JSON.h"
21#include "llvm/Support/SourceMgr.h"
22#include <cassert>
23#include <functional>
24#include <memory>
25#include <optional>
26#include <string>
27#include <utility>
28#include <vector>
29
30namespace clang {
31namespace clangd {
32
34 /// If true, Clangd uses an LSP extension to embed the fixes with the
35 /// diagnostics that are sent to the client.
37
38 /// If true, Clangd uses the relatedInformation field to include other
39 /// locations (in particular attached notes).
40 /// Otherwise, these are flattened into the diagnostic message.
42
43 /// If true, Clangd uses an LSP extension to send the diagnostic's
44 /// category to the client. The category typically describes the compilation
45 /// stage during which the issue was produced, e.g. "Semantic Issue" or "Parse
46 /// Issue".
48
49 /// If true, Clangd will add a number of available fixes to the diagnostic's
50 /// message.
51 bool DisplayFixesCount = true;
52};
53
54/// Contains basic information about a diagnostic.
55struct DiagBase {
56 std::string Message;
57 // Intended to be used only in error messages.
58 // May be relative, absolute or even artificially constructed.
59 std::string File;
60 // Absolute path to containing file, if available.
61 std::optional<std::string> AbsFile;
62
64 DiagnosticsEngine::Level Severity = DiagnosticsEngine::Note;
65 std::string Category;
66 // Since File is only descriptive, we store a separate flag to distinguish
67 // diags from the main file.
68 bool InsideMainFile = false;
69 unsigned ID = 0; // e.g. member of clang::diag, or clang-tidy assigned ID.
70 // Feature modules can make use of this field to propagate data from a
71 // diagnostic to a CodeAction request. Each module should only append to the
72 // list.
73 llvm::json::Object OpaqueData;
74};
75llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DiagBase &D);
76
77/// Represents a single fix-it that editor can apply to fix the error.
78struct Fix {
79 /// Message for the fix-it.
80 std::string Message;
81 /// TextEdits from clang's fix-its. Must be non-empty.
82 llvm::SmallVector<TextEdit, 1> Edits;
83
84 /// Annotations for the Edits.
85 llvm::SmallVector<std::pair<ChangeAnnotationIdentifier, ChangeAnnotation>>
87};
88llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Fix &F);
89
90/// Represents a note for the diagnostic. Severity of notes can only be 'note'
91/// or 'remark'.
92struct Note : DiagBase {};
93
94/// A top-level diagnostic that may have Notes and Fixes.
95struct Diag : DiagBase {
96 std::string Name; // if ID was recognized.
97 // The source of this diagnostic.
105 /// Elaborate on the problem, usually pointing to a related piece of code.
106 std::vector<Note> Notes;
107 /// *Alternative* fixes for this diagnostic, one should be chosen.
108 std::vector<Fix> Fixes;
109 llvm::SmallVector<DiagnosticTag, 1> Tags;
110};
111llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diag &D);
112
113Diag toDiag(const llvm::SMDiagnostic &, Diag::DiagSource Source);
114
115/// Conversion to LSP diagnostics. Formats the error message of each diagnostic
116/// to include all its notes. Notes inside main file are also provided as
117/// separate diagnostics with their corresponding fixits. Notes outside main
118/// file do not have a corresponding LSP diagnostic, but can still be included
119/// as part of their main diagnostic's message.
120void toLSPDiags(
121 const Diag &D, const URIForFile &File, const ClangdDiagnosticOptions &Opts,
122 llvm::function_ref<void(clangd::Diagnostic, llvm::ArrayRef<Fix>)> OutFn);
123
124/// Convert from clang diagnostic level to LSP severity.
125int getSeverity(DiagnosticsEngine::Level L);
126
127/// Returns a URI providing more information about a particular diagnostic.
128std::optional<std::string> getDiagnosticDocURI(Diag::DiagSource, unsigned ID,
129 llvm::StringRef Name);
130
131/// StoreDiags collects the diagnostics that can later be reported by
132/// clangd. It groups all notes for a diagnostic into a single Diag
133/// and filters out diagnostics that don't mention the main file (i.e. neither
134/// the diag itself nor its notes are in the main file).
136public:
137 std::vector<Diag> take();
138
139 void BeginSourceFile(const LangOptions &Opts,
140 const Preprocessor *PP) override;
141 void EndSourceFile() override;
142 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
143 const clang::Diagnostic &Info) override;
144
145 /// When passed a main diagnostic, returns fixes to add to it.
146 /// When passed a note diagnostic, returns fixes to replace it with.
147 using DiagFixer = std::function<std::vector<Fix>(DiagnosticsEngine::Level,
148 const clang::Diagnostic &)>;
149 using LevelAdjuster = std::function<DiagnosticsEngine::Level(
150 DiagnosticsEngine::Level, const clang::Diagnostic &)>;
152 std::function<void(const clang::Diagnostic &, clangd::Diag &)>;
153 using DiagFinalizer = std::function<void(Diag &)>;
154 /// If set, possibly adds fixes for diagnostics using \p Fixer.
155 void contributeFixes(DiagFixer Fixer) { this->Fixer = Fixer; }
156 /// If set, this allows the client of this class to adjust the level of
157 /// diagnostics, such as promoting warnings to errors, or ignoring
158 /// diagnostics.
159 void setLevelAdjuster(LevelAdjuster Adjuster) { this->Adjuster = Adjuster; }
160 /// Invokes a callback when a main diagnostic is first formed, before notes
161 /// and fixes are attached. The callback can mutate the diagnostic.
162 void setDiagCallback(DiagCallback CB) { DiagCB = std::move(CB); }
163 /// Invokes a callback after notes and fixes have been attached.
164 void setDiagFinalizer(DiagFinalizer F) { Finalizer = std::move(F); }
165
166private:
167 void flushLastDiag();
168
169 DiagFixer Fixer = nullptr;
170 LevelAdjuster Adjuster = nullptr;
171 DiagCallback DiagCB = nullptr;
172 DiagFinalizer Finalizer = nullptr;
173 std::vector<Diag> Output;
174 std::optional<LangOptions> LangOpts;
175 std::optional<Diag> LastDiag;
176 std::optional<FullSourceLoc> LastDiagLoc; // Valid only when LastDiag is set.
177 bool LastDiagOriginallyError = false; // Valid only when LastDiag is set.
178 SourceManager *OrigSrcMgr = nullptr;
179
180 llvm::DenseSet<std::pair<unsigned, unsigned>> IncludedErrorLocations;
181};
182
183/// Take a user-specified diagnostic code, and convert it to a normalized form
184/// stored in the config and consumed by isDiagnosticsSuppressed.
185///
186/// (This strips err_ and -W prefix so we can match with or without them.)
187llvm::StringRef normalizeSuppressedCode(llvm::StringRef);
188
189} // namespace clangd
190} // namespace clang
191
192#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H
StoreDiags collects the diagnostics that can later be reported by clangd.
std::function< void(Diag &)> DiagFinalizer
void contributeFixes(DiagFixer Fixer)
If set, possibly adds fixes for diagnostics using Fixer.
void setDiagFinalizer(DiagFinalizer F)
Invokes a callback after notes and fixes have been attached.
void setLevelAdjuster(LevelAdjuster Adjuster)
If set, this allows the client of this class to adjust the level of diagnostics, such as promoting wa...
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override
std::function< void(const clang::Diagnostic &, clangd::Diag &)> DiagCallback
void setDiagCallback(DiagCallback CB)
Invokes a callback when a main diagnostic is first formed, before notes and fixes are attached.
void BeginSourceFile(const LangOptions &Opts, const Preprocessor *PP) override
void EndSourceFile() override
std::function< DiagnosticsEngine::Level( DiagnosticsEngine::Level, const clang::Diagnostic &)> LevelAdjuster
std::vector< Diag > take()
std::function< std::vector< Fix >(DiagnosticsEngine::Level, const clang::Diagnostic &)> DiagFixer
When passed a main diagnostic, returns fixes to add to it.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:44
@ Info
An information message.
Definition Protocol.h:755
void toLSPDiags(const Diag &D, const URIForFile &File, const ClangdDiagnosticOptions &Opts, llvm::function_ref< void(clangd::Diagnostic, llvm::ArrayRef< Fix >)> OutFn)
Conversion to LSP diagnostics.
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
llvm::StringRef normalizeSuppressedCode(llvm::StringRef Code)
Take a user-specified diagnostic code, and convert it to a normalized form stored in the config and c...
Diag toDiag(const llvm::SMDiagnostic &D, Diag::DiagSource Source)
int getSeverity(DiagnosticsEngine::Level L)
Convert from clang diagnostic level to LSP severity.
std::optional< std::string > getDiagnosticDocURI(Diag::DiagSource Source, unsigned ID, llvm::StringRef Name)
Returns a URI providing more information about a particular diagnostic.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
bool EmbedFixesInDiagnostics
If true, Clangd uses an LSP extension to embed the fixes with the diagnostics that are sent to the cl...
Definition Diagnostics.h:36
bool SendDiagnosticCategory
If true, Clangd uses an LSP extension to send the diagnostic's category to the client.
Definition Diagnostics.h:47
bool DisplayFixesCount
If true, Clangd will add a number of available fixes to the diagnostic's message.
Definition Diagnostics.h:51
bool EmitRelatedLocations
If true, Clangd uses the relatedInformation field to include other locations (in particular attached ...
Definition Diagnostics.h:41
Contains basic information about a diagnostic.
Definition Diagnostics.h:55
llvm::json::Object OpaqueData
Definition Diagnostics.h:73
DiagnosticsEngine::Level Severity
Definition Diagnostics.h:64
std::optional< std::string > AbsFile
Definition Diagnostics.h:61
A top-level diagnostic that may have Notes and Fixes.
Definition Diagnostics.h:95
std::vector< Fix > Fixes
Alternative fixes for this diagnostic, one should be chosen.
llvm::SmallVector< DiagnosticTag, 1 > Tags
enum clang::clangd::Diag::DiagSource Source
std::vector< Note > Notes
Elaborate on the problem, usually pointing to a related piece of code.
Represents a single fix-it that editor can apply to fix the error.
Definition Diagnostics.h:78
llvm::SmallVector< std::pair< ChangeAnnotationIdentifier, ChangeAnnotation > > Annotations
Annotations for the Edits.
Definition Diagnostics.h:86
std::string Message
Message for the fix-it.
Definition Diagnostics.h:80
llvm::SmallVector< TextEdit, 1 > Edits
TextEdits from clang's fix-its. Must be non-empty.
Definition Diagnostics.h:82
Represents a note for the diagnostic.
Definition Diagnostics.h:92