1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0
use {
crate::{
Uri,
protocol::{
lsp::{
Location,
NumberOrString,
Range,
},
macros::lsp_enum,
},
},
serde::{
Deserialize,
Serialize,
de::Error,
},
std::collections::HashMap,
};
#[cfg(feature = "proposed")]
use crate::protocol::lsp::{
MarkupContent,
OneOf,
};
// TODO: we should Probably make this a struct that takes both the string and
// markup and depending on the client capability will use one or the other.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum StringOrMarkup {
String(String),
Markup(MarkupContent),
}
impl std::default::Default for StringOrMarkup {
fn default() -> Self {
StringOrMarkup::String(String::new())
}
}
impl std::fmt::Display for StringOrMarkup {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
| crate::protocol::lsp::StringOrMarkup::String(s) => s,
| crate::protocol::lsp::StringOrMarkup::Markup(m) => {
&m.value
},
})
}
}
/// Represents a diagnostic, such as a compiler error or warning.
/// Diagnostic objects are only valid in the scope of a resource.
#[derive(Default, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Diagnostic {
/// The range at which the message applies.
pub range: Range,
/// The diagnostic's severity. Can be omitted. If omitted it is up to the
/// client to interpret diagnostics as error, warning, info or hint.
#[serde(skip_serializing_if = "Option::is_none")]
pub severity: Option<DiagnosticSeverity>,
/// The diagnostic's code. Can be omitted.
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<NumberOrString>,
/// An optional property to describe the error code.
///
/// @since 3.16.0
#[serde(skip_serializing_if = "Option::is_none")]
pub code_description: Option<CodeDescription>,
/// A human-readable string describing the source of this
/// diagnostic, e.g. `typescript` or `super lint`.
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<String>,
/// The diagnostic's message.
///
/// @since 3.18.0 - support for `MarkupContent`. This is guarded by the
/// client capability `textDocument.diagnostic.markupMessageSupport`.]
pub message: StringOrMarkup,
/// An array of related diagnostic information, e.g. when symbol-names within
/// a scope collide all definitions can be marked via this property.
#[serde(skip_serializing_if = "Option::is_none")]
pub related_information: Option<Vec<DiagnosticRelatedInformation>>,
/// Additional metadata about the diagnostic.
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<DiagnosticTag>>,
/// A data entry field that is preserved between a
/// `textDocument/publishDiagnostics` notification and
/// `textDocument/codeAction` request.
///
/// @since 3.16.0
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
}
impl Diagnostic {
#[must_use]
pub const fn new(
range: Range,
severity: Option<DiagnosticSeverity>,
code: Option<NumberOrString>,
source: Option<String>,
message: StringOrMarkup,
related_information: Option<Vec<DiagnosticRelatedInformation>>,
tags: Option<Vec<DiagnosticTag>>,
) -> Self {
Self {
range,
severity,
code,
source,
message,
related_information,
tags,
code_description: None,
data: None,
}
}
#[must_use]
pub const fn new_simple(range: Range, message: String) -> Self {
Self::new(
range,
None,
None,
None,
StringOrMarkup::String(message),
None,
None,
)
}
#[must_use]
pub const fn new_with_code_number(
range: Range,
severity: DiagnosticSeverity,
code_number: i32,
source: Option<String>,
message: String,
) -> Self {
let code = Some(NumberOrString::Number(code_number));
Self::new(
range,
Some(severity),
code,
source,
StringOrMarkup::String(message),
None,
None,
)
}
}
/// The protocol currently supports the following diagnostic severities:
#[derive(
Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize,
)]
#[serde(transparent)]
pub struct DiagnosticSeverity(i32);
lsp_enum! {
impl DiagnosticSeverity {
/// Reports an error.
const ERROR = 1;
/// Reports a warning.
const WARNING = 2;
/// Reports information.
const INFORMATION = 3;
/// Reports a hint.
const HINT = 4;
}
}
/// The diagnostic tags.
#[derive(Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(transparent)]
pub struct DiagnosticTag(i32);
lsp_enum! {
impl DiagnosticTag {
/// Unused or unnecessary code.
/// Clients are allowed to render diagnostics with this tag faded out instead of having
/// an error squiggle.
const UNNECESSARY = 1;
/// Deprecated or obsolete code.
/// Clients are allowed to render diagnostics with this tag strike through.
const DEPRECATED = 2;
}
}
/// Represents a related message and source code location for a diagnostic. This
/// should be used to point to code locations that cause or related to a
/// diagnostics, e.g when duplicating a symbol in a scope.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct DiagnosticRelatedInformation {
/// The location of this related diagnostic information.
pub location: Location,
/// The message of this related diagnostic information.
pub message: String,
}
/// Structure to capture a description for an error code.
///
/// @since 3.16.0
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CodeDescription {
/// A URI to open with more information about the diagnostic error.
pub href: Uri,
}