1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use url::Url;
5
6use crate::{
7 Diagnostic, PartialResultParams, StaticRegistrationOptions, TextDocumentIdentifier,
8 TextDocumentRegistrationOptions, WorkDoneProgressOptions, WorkDoneProgressParams,
9};
10
11/// Client capabilities specific to diagnostic pull requests.
12///
13/// @since 3.17.0
14#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
15#[serde(rename_all = "camelCase")]
16pub struct DiagnosticClientCapabilities {
17 /// Whether implementation supports dynamic registration.
18 ///
19 /// If this is set to `true` the client supports the new `(TextDocumentRegistrationOptions &
20 /// StaticRegistrationOptions)` return value for the corresponding server capability as well.
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub dynamic_registration: Option<bool>,
23
24 /// Whether the clients supports related documents for document diagnostic pulls.
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub related_document_support: Option<bool>,
27}
28
29/// Diagnostic options.
30///
31/// @since 3.17.0
32#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
33#[serde(rename_all = "camelCase")]
34pub struct DiagnosticOptions {
35 /// An optional identifier under which the diagnostics are
36 /// managed by the client.
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub identifier: Option<String>,
39
40 /// Whether the language has inter file dependencies, meaning that editing code in one file can
41 /// result in a different diagnostic set in another file. Inter file dependencies are common
42 /// for most programming languages and typically uncommon for linters.
43 pub inter_file_dependencies: bool,
44
45 /// The server provides support for workspace diagnostics as well.
46 pub workspace_diagnostics: bool,
47
48 #[serde(flatten)]
49 pub work_done_progress_options: WorkDoneProgressOptions,
50}
51
52/// Diagnostic registration options.
53///
54/// @since 3.17.0
55#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
56#[serde(rename_all = "camelCase")]
57pub struct DiagnosticRegistrationOptions {
58 #[serde(flatten)]
59 pub text_document_registration_options: TextDocumentRegistrationOptions,
60
61 #[serde(flatten)]
62 pub diagnostic_options: DiagnosticOptions,
63
64 #[serde(flatten)]
65 pub static_registration_options: StaticRegistrationOptions,
66}
67
68#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
69#[serde(untagged)]
70pub enum DiagnosticServerCapabilities {
71 Options(DiagnosticOptions),
72 RegistrationOptions(DiagnosticRegistrationOptions),
73}
74
75/// Parameters of the document diagnostic request.
76///
77/// @since 3.17.0
78#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
79#[serde(rename_all = "camelCase")]
80pub struct DocumentDiagnosticParams {
81 /// The text document.
82 pub text_document: TextDocumentIdentifier,
83
84 /// The additional identifier provided during registration.
85 pub identifier: Option<String>,
86
87 /// The result ID of a previous response if provided.
88 pub previous_result_id: Option<String>,
89
90 #[serde(flatten)]
91 pub work_done_progress_params: WorkDoneProgressParams,
92
93 #[serde(flatten)]
94 pub partial_result_params: PartialResultParams,
95}
96
97/// A diagnostic report with a full set of problems.
98///
99/// @since 3.17.0
100#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
101#[serde(rename_all = "camelCase")]
102pub struct FullDocumentDiagnosticReport {
103 /// An optional result ID. If provided it will be sent on the next diagnostic request for the
104 /// same document.
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub result_id: Option<String>,
107
108 /// The actual items.
109 pub items: Vec<Diagnostic>,
110}
111
112/// A diagnostic report indicating that the last returned report is still accurate.
113///
114/// A server can only return `unchanged` if result ids are provided.
115///
116/// @since 3.17.0
117#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
118#[serde(rename_all = "camelCase")]
119pub struct UnchangedDocumentDiagnosticReport {
120 /// A result ID which will be sent on the next diagnostic request for the same document.
121 pub result_id: String,
122}
123
124/// The document diagnostic report kinds.
125///
126/// @since 3.17.0
127#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
128#[serde(tag = "kind", rename_all = "lowercase")]
129pub enum DocumentDiagnosticReportKind {
130 /// A diagnostic report with a full set of problems.
131 Full(FullDocumentDiagnosticReport),
132 /// A report indicating that the last returned report is still accurate.
133 Unchanged(UnchangedDocumentDiagnosticReport),
134}
135
136impl From<FullDocumentDiagnosticReport> for DocumentDiagnosticReportKind {
137 fn from(from: FullDocumentDiagnosticReport) -> Self {
138 DocumentDiagnosticReportKind::Full(from)
139 }
140}
141
142impl From<UnchangedDocumentDiagnosticReport> for DocumentDiagnosticReportKind {
143 fn from(from: UnchangedDocumentDiagnosticReport) -> Self {
144 DocumentDiagnosticReportKind::Unchanged(from)
145 }
146}
147
148/// A full diagnostic report with a set of related documents.
149///
150/// @since 3.17.0
151#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
152#[serde(rename_all = "camelCase")]
153pub struct RelatedFullDocumentDiagnosticReport {
154 /// Diagnostics of related documents.
155 ///
156 /// This information is useful in programming languages where code in a file A can generate
157 /// diagnostics in a file B which A depends on. An example of such a language is C/C++ where
158 /// macro definitions in a file `a.cpp` result in errors in a header file `b.hpp`.
159 ///
160 /// @since 3.17.0
161 #[serde(with = "crate::url_map")]
162 #[serde(skip_serializing_if = "Option::is_none")]
163 #[serde(default)]
164 pub related_documents: Option<HashMap<Url, DocumentDiagnosticReportKind>>,
165 // relatedDocuments?: { [uri: string]: FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport; };
166 #[serde(flatten)]
167 pub full_document_diagnostic_report: FullDocumentDiagnosticReport,
168}
169
170/// An unchanged diagnostic report with a set of related documents.
171///
172/// @since 3.17.0
173#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
174#[serde(rename_all = "camelCase")]
175pub struct RelatedUnchangedDocumentDiagnosticReport {
176 /// Diagnostics of related documents.
177 ///
178 /// This information is useful in programming languages where code in a file A can generate
179 /// diagnostics in a file B which A depends on. An example of such a language is C/C++ where
180 /// macro definitions in a file `a.cpp` result in errors in a header file `b.hpp`.
181 ///
182 /// @since 3.17.0
183 #[serde(with = "crate::url_map")]
184 #[serde(skip_serializing_if = "Option::is_none")]
185 #[serde(default)]
186 pub related_documents: Option<HashMap<Url, DocumentDiagnosticReportKind>>,
187 // relatedDocuments?: { [uri: string]: FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport; };
188 #[serde(flatten)]
189 pub unchanged_document_diagnostic_report: UnchangedDocumentDiagnosticReport,
190}
191
192/// The result of a document diagnostic pull request.
193///
194/// A report can either be a full report containing all diagnostics for the requested document or
195/// an unchanged report indicating that nothing has changed in terms of diagnostics in comparison
196/// to the last pull request.
197///
198/// @since 3.17.0
199#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
200#[serde(tag = "kind", rename_all = "lowercase")]
201pub enum DocumentDiagnosticReport {
202 /// A diagnostic report with a full set of problems.
203 Full(RelatedFullDocumentDiagnosticReport),
204 /// A report indicating that the last returned report is still accurate.
205 Unchanged(RelatedUnchangedDocumentDiagnosticReport),
206}
207
208impl From<RelatedFullDocumentDiagnosticReport> for DocumentDiagnosticReport {
209 fn from(from: RelatedFullDocumentDiagnosticReport) -> Self {
210 DocumentDiagnosticReport::Full(from)
211 }
212}
213
214impl From<RelatedUnchangedDocumentDiagnosticReport> for DocumentDiagnosticReport {
215 fn from(from: RelatedUnchangedDocumentDiagnosticReport) -> Self {
216 DocumentDiagnosticReport::Unchanged(from)
217 }
218}
219
220/// A partial result for a document diagnostic report.
221///
222/// @since 3.17.0
223#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
224#[serde(rename_all = "camelCase")]
225pub struct DocumentDiagnosticReportPartialResult {
226 #[serde(with = "crate::url_map")]
227 #[serde(skip_serializing_if = "Option::is_none")]
228 #[serde(default)]
229 pub related_documents: Option<HashMap<Url, DocumentDiagnosticReportKind>>,
230 // relatedDocuments?: { [uri: string]: FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport; };
231}
232
233#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
234#[serde(untagged)]
235pub enum DocumentDiagnosticReportResult {
236 Report(DocumentDiagnosticReport),
237 Partial(DocumentDiagnosticReportPartialResult),
238}
239
240impl From<DocumentDiagnosticReport> for DocumentDiagnosticReportResult {
241 fn from(from: DocumentDiagnosticReport) -> Self {
242 DocumentDiagnosticReportResult::Report(from)
243 }
244}
245
246impl From<DocumentDiagnosticReportPartialResult> for DocumentDiagnosticReportResult {
247 fn from(from: DocumentDiagnosticReportPartialResult) -> Self {
248 DocumentDiagnosticReportResult::Partial(from)
249 }
250}
251
252/// Cancellation data returned from a diagnostic request.
253///
254/// If no data is provided, it defaults to `{ retrigger_request: true }`.
255///
256/// @since 3.17.0
257#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
258#[serde(rename_all = "camelCase")]
259pub struct DiagnosticServerCancellationData {
260 pub retrigger_request: bool,
261}
262
263impl Default for DiagnosticServerCancellationData {
264 fn default() -> Self {
265 DiagnosticServerCancellationData {
266 retrigger_request: true,
267 }
268 }
269}
270