blob: b2174f6676721ac051a2a0956add56b12e71647a [file] [log] [blame]
Ilya Biryukov71028b82018-03-12 15:28:22 +00001//===--- Diagnostics.h ------------------------------------------*- C++-*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===---------------------------------------------------------------------===//
9
10#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H
11#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_DIAGNOSTICS_H
12
13#include "Path.h"
14#include "Protocol.h"
15#include "clang/Basic/Diagnostic.h"
16#include "clang/Basic/LangOptions.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringSet.h"
20#include <cassert>
21#include <string>
22
23namespace clang {
24namespace clangd {
25
26/// Contains basic information about a diagnostic.
27struct DiagBase {
28 std::string Message;
29 // Intended to be used only in error messages.
30 // May be relative, absolute or even artifically constructed.
31 std::string File;
32 clangd::Range Range;
33 DiagnosticsEngine::Level Severity = DiagnosticsEngine::Note;
34 // Since File is only descriptive, we store a separate flag to distinguish
35 // diags from the main file.
36 bool InsideMainFile = false;
37};
38llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DiagBase &D);
39
40/// Represents a single fix-it that editor can apply to fix the error.
41struct Fix {
42 /// Message for the fix-it.
43 std::string Message;
44 /// TextEdits from clang's fix-its. Must be non-empty.
45 llvm::SmallVector<TextEdit, 1> Edits;
46};
47llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Fix &F);
48
49/// Represents a note for the diagnostic. Severity of notes can only be 'note'
50/// or 'remark'.
51struct Note : DiagBase {};
52
53/// A top-level diagnostic that may have Notes and Fixes.
54struct Diag : DiagBase {
55 /// Elaborate on the problem, usually pointing to a related piece of code.
56 std::vector<Note> Notes;
57 /// *Alternative* fixes for this diagnostic, one should be chosen.
58 std::vector<Fix> Fixes;
59};
60llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diag &D);
61
62/// Conversion to LSP diagnostics. Formats the error message of each diagnostic
63/// to include all its notes. Notes inside main file are also provided as
64/// separate diagnostics with their corresponding fixits. Notes outside main
65/// file do not have a corresponding LSP diagnostic, but can still be included
66/// as part of their main diagnostic's message.
67void toLSPDiags(
68 const Diag &D,
69 llvm::function_ref<void(clangd::Diagnostic, llvm::ArrayRef<Fix>)> OutFn);
70
71/// Convert from clang diagnostic level to LSP severity.
72int getSeverity(DiagnosticsEngine::Level L);
73
74/// StoreDiags collects the diagnostics that can later be reported by
75/// clangd. It groups all notes for a diagnostic into a single Diag
76/// and filters out diagnostics that don't mention the main file (i.e. neither
77/// the diag itself nor its notes are in the main file).
78class StoreDiags : public DiagnosticConsumer {
79public:
80 std::vector<Diag> take();
81
82 void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override;
83 void EndSourceFile() override;
84 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
85 const clang::Diagnostic &Info) override;
86
87private:
88 bool shouldIgnore(DiagnosticsEngine::Level DiagLevel,
89 const clang::Diagnostic &Info);
90
91 void flushLastDiag();
92
93 std::vector<Diag> Output;
94 llvm::Optional<LangOptions> LangOpts;
95 llvm::Optional<Diag> LastDiag;
96 /// Is any diag or note from LastDiag in the main file?
97 bool LastDiagMentionsMainFile = false;
98};
99
100} // namespace clangd
101} // namespace clang
102
103#endif