]> git.lizzy.rs Git - rust.git/blob - crates/rust-analyzer/src/lsp_ext.rs
Merge #8560
[rust.git] / crates / rust-analyzer / src / lsp_ext.rs
1 //! rust-analyzer extensions to the LSP.
2
3 use std::{collections::HashMap, path::PathBuf};
4
5 use lsp_types::request::Request;
6 use lsp_types::{
7     notification::Notification, CodeActionKind, Position, Range, TextDocumentIdentifier,
8 };
9 use serde::{Deserialize, Serialize};
10
11 pub enum AnalyzerStatus {}
12
13 impl Request for AnalyzerStatus {
14     type Params = AnalyzerStatusParams;
15     type Result = String;
16     const METHOD: &'static str = "rust-analyzer/analyzerStatus";
17 }
18
19 #[derive(Deserialize, Serialize, Debug)]
20 #[serde(rename_all = "camelCase")]
21 pub struct AnalyzerStatusParams {
22     pub text_document: Option<TextDocumentIdentifier>,
23 }
24
25 pub enum MemoryUsage {}
26
27 impl Request for MemoryUsage {
28     type Params = ();
29     type Result = String;
30     const METHOD: &'static str = "rust-analyzer/memoryUsage";
31 }
32
33 pub enum ReloadWorkspace {}
34
35 impl Request for ReloadWorkspace {
36     type Params = ();
37     type Result = ();
38     const METHOD: &'static str = "rust-analyzer/reloadWorkspace";
39 }
40
41 pub enum SyntaxTree {}
42
43 impl Request for SyntaxTree {
44     type Params = SyntaxTreeParams;
45     type Result = String;
46     const METHOD: &'static str = "rust-analyzer/syntaxTree";
47 }
48
49 #[derive(Deserialize, Serialize, Debug)]
50 #[serde(rename_all = "camelCase")]
51 pub struct SyntaxTreeParams {
52     pub text_document: TextDocumentIdentifier,
53     pub range: Option<Range>,
54 }
55
56 pub enum ViewHir {}
57
58 impl Request for ViewHir {
59     type Params = lsp_types::TextDocumentPositionParams;
60     type Result = String;
61     const METHOD: &'static str = "rust-analyzer/viewHir";
62 }
63
64 pub enum ExpandMacro {}
65
66 impl Request for ExpandMacro {
67     type Params = ExpandMacroParams;
68     type Result = Option<ExpandedMacro>;
69     const METHOD: &'static str = "rust-analyzer/expandMacro";
70 }
71
72 #[derive(Deserialize, Serialize, Debug)]
73 #[serde(rename_all = "camelCase")]
74 pub struct ExpandMacroParams {
75     pub text_document: TextDocumentIdentifier,
76     pub position: Position,
77 }
78
79 #[derive(Deserialize, Serialize, Debug)]
80 #[serde(rename_all = "camelCase")]
81 pub struct ExpandedMacro {
82     pub name: String,
83     pub expansion: String,
84 }
85
86 pub enum MatchingBrace {}
87
88 impl Request for MatchingBrace {
89     type Params = MatchingBraceParams;
90     type Result = Vec<Position>;
91     const METHOD: &'static str = "experimental/matchingBrace";
92 }
93
94 #[derive(Deserialize, Serialize, Debug)]
95 #[serde(rename_all = "camelCase")]
96 pub struct MatchingBraceParams {
97     pub text_document: TextDocumentIdentifier,
98     pub positions: Vec<Position>,
99 }
100
101 pub enum ParentModule {}
102
103 impl Request for ParentModule {
104     type Params = lsp_types::TextDocumentPositionParams;
105     type Result = Option<lsp_types::GotoDefinitionResponse>;
106     const METHOD: &'static str = "experimental/parentModule";
107 }
108
109 pub enum JoinLines {}
110
111 impl Request for JoinLines {
112     type Params = JoinLinesParams;
113     type Result = Vec<lsp_types::TextEdit>;
114     const METHOD: &'static str = "experimental/joinLines";
115 }
116
117 #[derive(Deserialize, Serialize, Debug)]
118 #[serde(rename_all = "camelCase")]
119 pub struct JoinLinesParams {
120     pub text_document: TextDocumentIdentifier,
121     pub ranges: Vec<Range>,
122 }
123
124 pub enum OnEnter {}
125
126 impl Request for OnEnter {
127     type Params = lsp_types::TextDocumentPositionParams;
128     type Result = Option<Vec<SnippetTextEdit>>;
129     const METHOD: &'static str = "experimental/onEnter";
130 }
131
132 pub enum Runnables {}
133
134 impl Request for Runnables {
135     type Params = RunnablesParams;
136     type Result = Vec<Runnable>;
137     const METHOD: &'static str = "experimental/runnables";
138 }
139
140 #[derive(Serialize, Deserialize, Debug)]
141 #[serde(rename_all = "camelCase")]
142 pub struct RunnablesParams {
143     pub text_document: TextDocumentIdentifier,
144     pub position: Option<Position>,
145 }
146
147 #[derive(Deserialize, Serialize, Debug)]
148 #[serde(rename_all = "camelCase")]
149 pub struct Runnable {
150     pub label: String,
151     #[serde(skip_serializing_if = "Option::is_none")]
152     pub location: Option<lsp_types::LocationLink>,
153     pub kind: RunnableKind,
154     pub args: CargoRunnable,
155 }
156
157 #[derive(Serialize, Deserialize, Debug)]
158 #[serde(rename_all = "lowercase")]
159 pub enum RunnableKind {
160     Cargo,
161 }
162
163 #[derive(Deserialize, Serialize, Debug)]
164 #[serde(rename_all = "camelCase")]
165 pub struct CargoRunnable {
166     // command to be executed instead of cargo
167     pub override_cargo: Option<String>,
168     #[serde(skip_serializing_if = "Option::is_none")]
169     pub workspace_root: Option<PathBuf>,
170     // command, --package and --lib stuff
171     pub cargo_args: Vec<String>,
172     // user-specified additional cargo args, like `--release`.
173     pub cargo_extra_args: Vec<String>,
174     // stuff after --
175     pub executable_args: Vec<String>,
176     #[serde(skip_serializing_if = "Option::is_none")]
177     pub expect_test: Option<bool>,
178 }
179
180 pub enum RelatedTests {}
181
182 impl Request for RelatedTests {
183     type Params = lsp_types::TextDocumentPositionParams;
184     type Result = Vec<TestInfo>;
185     const METHOD: &'static str = "rust-analyzer/relatedTests";
186 }
187
188 #[derive(Debug, Deserialize, Serialize)]
189 pub struct TestInfo {
190     pub runnable: Runnable,
191 }
192
193 pub enum InlayHints {}
194
195 impl Request for InlayHints {
196     type Params = InlayHintsParams;
197     type Result = Vec<InlayHint>;
198     const METHOD: &'static str = "rust-analyzer/inlayHints";
199 }
200
201 #[derive(Serialize, Deserialize, Debug)]
202 #[serde(rename_all = "camelCase")]
203 pub struct InlayHintsParams {
204     pub text_document: TextDocumentIdentifier,
205 }
206
207 #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
208 pub enum InlayKind {
209     TypeHint,
210     ParameterHint,
211     ChainingHint,
212 }
213
214 #[derive(Debug, Deserialize, Serialize)]
215 pub struct InlayHint {
216     pub range: Range,
217     pub kind: InlayKind,
218     pub label: String,
219 }
220
221 pub enum Ssr {}
222
223 impl Request for Ssr {
224     type Params = SsrParams;
225     type Result = lsp_types::WorkspaceEdit;
226     const METHOD: &'static str = "experimental/ssr";
227 }
228
229 #[derive(Debug, Deserialize, Serialize)]
230 #[serde(rename_all = "camelCase")]
231 pub struct SsrParams {
232     pub query: String,
233     pub parse_only: bool,
234
235     /// File position where SSR was invoked. Paths in `query` will be resolved relative to this
236     /// position.
237     #[serde(flatten)]
238     pub position: lsp_types::TextDocumentPositionParams,
239
240     /// Current selections. Search/replace will be restricted to these if non-empty.
241     pub selections: Vec<lsp_types::Range>,
242 }
243
244 pub enum ServerStatusNotification {}
245
246 impl Notification for ServerStatusNotification {
247     type Params = ServerStatusParams;
248     const METHOD: &'static str = "experimental/serverStatus";
249 }
250
251 #[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
252 pub struct ServerStatusParams {
253     pub health: Health,
254     pub quiescent: bool,
255     pub message: Option<String>,
256 }
257
258 #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
259 #[serde(rename_all = "camelCase")]
260 pub enum Health {
261     Ok,
262     Warning,
263     Error,
264 }
265
266 pub enum CodeActionRequest {}
267
268 impl Request for CodeActionRequest {
269     type Params = lsp_types::CodeActionParams;
270     type Result = Option<Vec<CodeAction>>;
271     const METHOD: &'static str = "textDocument/codeAction";
272 }
273
274 pub enum CodeActionResolveRequest {}
275 impl Request for CodeActionResolveRequest {
276     type Params = CodeAction;
277     type Result = CodeAction;
278     const METHOD: &'static str = "codeAction/resolve";
279 }
280
281 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
282 #[serde(rename_all = "camelCase")]
283 pub struct CodeAction {
284     pub title: String,
285     #[serde(skip_serializing_if = "Option::is_none")]
286     pub group: Option<String>,
287     #[serde(skip_serializing_if = "Option::is_none")]
288     pub kind: Option<CodeActionKind>,
289     // We don't handle commands on the client-side
290     // #[serde(skip_serializing_if = "Option::is_none")]
291     // pub command: Option<lsp_types::Command>,
292     #[serde(skip_serializing_if = "Option::is_none")]
293     pub edit: Option<SnippetWorkspaceEdit>,
294     #[serde(skip_serializing_if = "Option::is_none")]
295     pub is_preferred: Option<bool>,
296
297     #[serde(skip_serializing_if = "Option::is_none")]
298     pub data: Option<CodeActionData>,
299 }
300
301 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
302 #[serde(rename_all = "camelCase")]
303 pub struct CodeActionData {
304     pub code_action_params: lsp_types::CodeActionParams,
305     pub id: String,
306 }
307
308 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
309 #[serde(rename_all = "camelCase")]
310 pub struct SnippetWorkspaceEdit {
311     #[serde(skip_serializing_if = "Option::is_none")]
312     pub changes: Option<HashMap<lsp_types::Url, Vec<lsp_types::TextEdit>>>,
313     #[serde(skip_serializing_if = "Option::is_none")]
314     pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>,
315 }
316
317 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
318 #[serde(untagged, rename_all = "lowercase")]
319 pub enum SnippetDocumentChangeOperation {
320     Op(lsp_types::ResourceOp),
321     Edit(SnippetTextDocumentEdit),
322 }
323
324 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
325 #[serde(rename_all = "camelCase")]
326 pub struct SnippetTextDocumentEdit {
327     pub text_document: lsp_types::OptionalVersionedTextDocumentIdentifier,
328     pub edits: Vec<SnippetTextEdit>,
329 }
330
331 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
332 #[serde(rename_all = "camelCase")]
333 pub struct SnippetTextEdit {
334     pub range: Range,
335     pub new_text: String,
336     #[serde(skip_serializing_if = "Option::is_none")]
337     pub insert_text_format: Option<lsp_types::InsertTextFormat>,
338 }
339
340 pub enum HoverRequest {}
341
342 impl Request for HoverRequest {
343     type Params = lsp_types::HoverParams;
344     type Result = Option<Hover>;
345     const METHOD: &'static str = "textDocument/hover";
346 }
347
348 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
349 pub struct Hover {
350     #[serde(flatten)]
351     pub hover: lsp_types::Hover,
352     #[serde(skip_serializing_if = "Vec::is_empty")]
353     pub actions: Vec<CommandLinkGroup>,
354 }
355
356 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
357 pub struct CommandLinkGroup {
358     #[serde(skip_serializing_if = "Option::is_none")]
359     pub title: Option<String>,
360     pub commands: Vec<CommandLink>,
361 }
362
363 // LSP v3.15 Command does not have a `tooltip` field, vscode supports one.
364 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
365 pub struct CommandLink {
366     #[serde(flatten)]
367     pub command: lsp_types::Command,
368     #[serde(skip_serializing_if = "Option::is_none")]
369     pub tooltip: Option<String>,
370 }
371
372 pub enum ExternalDocs {}
373
374 impl Request for ExternalDocs {
375     type Params = lsp_types::TextDocumentPositionParams;
376     type Result = Option<lsp_types::Url>;
377     const METHOD: &'static str = "experimental/externalDocs";
378 }
379
380 pub enum OpenCargoToml {}
381
382 impl Request for OpenCargoToml {
383     type Params = OpenCargoTomlParams;
384     type Result = Option<lsp_types::GotoDefinitionResponse>;
385     const METHOD: &'static str = "experimental/openCargoToml";
386 }
387
388 #[derive(Serialize, Deserialize, Debug)]
389 #[serde(rename_all = "camelCase")]
390 pub struct OpenCargoTomlParams {
391     pub text_document: TextDocumentIdentifier,
392 }
393
394 /// Information about CodeLens, that is to be resolved.
395 #[derive(Debug, Serialize, Deserialize)]
396 #[serde(rename_all = "camelCase")]
397 pub(crate) enum CodeLensResolveData {
398     Impls(lsp_types::request::GotoImplementationParams),
399     References(lsp_types::TextDocumentPositionParams),
400 }
401
402 pub fn supports_utf8(caps: &lsp_types::ClientCapabilities) -> bool {
403     caps.offset_encoding.as_deref().unwrap_or_default().iter().any(|it| it == "utf-8")
404 }
405
406 pub enum MoveItem {}
407
408 impl Request for MoveItem {
409     type Params = MoveItemParams;
410     type Result = Vec<SnippetTextEdit>;
411     const METHOD: &'static str = "experimental/moveItem";
412 }
413
414 #[derive(Serialize, Deserialize, Debug)]
415 #[serde(rename_all = "camelCase")]
416 pub struct MoveItemParams {
417     pub direction: MoveItemDirection,
418     pub text_document: TextDocumentIdentifier,
419     pub range: Range,
420 }
421
422 #[derive(Serialize, Deserialize, Debug)]
423 pub enum MoveItemDirection {
424     Up,
425     Down,
426 }