]> git.lizzy.rs Git - rust.git/blob - crates/rust-analyzer/src/lsp_ext.rs
Trigger hover requests on closing brace hints
[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, PartialResultParams, Position, Range,
8     TextDocumentIdentifier, WorkDoneProgressParams,
9 };
10 use serde::{Deserialize, Serialize};
11
12 pub enum AnalyzerStatus {}
13
14 impl Request for AnalyzerStatus {
15     type Params = AnalyzerStatusParams;
16     type Result = String;
17     const METHOD: &'static str = "rust-analyzer/analyzerStatus";
18 }
19
20 #[derive(Deserialize, Serialize, Debug)]
21 #[serde(rename_all = "camelCase")]
22 pub struct AnalyzerStatusParams {
23     pub text_document: Option<TextDocumentIdentifier>,
24 }
25
26 pub enum MemoryUsage {}
27
28 impl Request for MemoryUsage {
29     type Params = ();
30     type Result = String;
31     const METHOD: &'static str = "rust-analyzer/memoryUsage";
32 }
33
34 pub enum ShuffleCrateGraph {}
35
36 impl Request for ShuffleCrateGraph {
37     type Params = ();
38     type Result = ();
39     const METHOD: &'static str = "rust-analyzer/shuffleCrateGraph";
40 }
41
42 pub enum ReloadWorkspace {}
43
44 impl Request for ReloadWorkspace {
45     type Params = ();
46     type Result = ();
47     const METHOD: &'static str = "rust-analyzer/reloadWorkspace";
48 }
49
50 pub enum SyntaxTree {}
51
52 impl Request for SyntaxTree {
53     type Params = SyntaxTreeParams;
54     type Result = String;
55     const METHOD: &'static str = "rust-analyzer/syntaxTree";
56 }
57
58 #[derive(Deserialize, Serialize, Debug)]
59 #[serde(rename_all = "camelCase")]
60 pub struct SyntaxTreeParams {
61     pub text_document: TextDocumentIdentifier,
62     pub range: Option<Range>,
63 }
64
65 pub enum ViewHir {}
66
67 impl Request for ViewHir {
68     type Params = lsp_types::TextDocumentPositionParams;
69     type Result = String;
70     const METHOD: &'static str = "rust-analyzer/viewHir";
71 }
72
73 pub enum ViewFileText {}
74
75 impl Request for ViewFileText {
76     type Params = lsp_types::TextDocumentIdentifier;
77     type Result = String;
78     const METHOD: &'static str = "rust-analyzer/viewFileText";
79 }
80
81 #[derive(Deserialize, Serialize, Debug)]
82 #[serde(rename_all = "camelCase")]
83 pub struct ViewCrateGraphParams {
84     /// Include *all* crates, not just crates in the workspace.
85     pub full: bool,
86 }
87
88 pub enum ViewCrateGraph {}
89
90 impl Request for ViewCrateGraph {
91     type Params = ViewCrateGraphParams;
92     type Result = String;
93     const METHOD: &'static str = "rust-analyzer/viewCrateGraph";
94 }
95
96 #[derive(Deserialize, Serialize, Debug)]
97 #[serde(rename_all = "camelCase")]
98 pub struct ViewItemTreeParams {
99     pub text_document: TextDocumentIdentifier,
100 }
101
102 pub enum ViewItemTree {}
103
104 impl Request for ViewItemTree {
105     type Params = ViewItemTreeParams;
106     type Result = String;
107     const METHOD: &'static str = "rust-analyzer/viewItemTree";
108 }
109
110 pub enum ExpandMacro {}
111
112 impl Request for ExpandMacro {
113     type Params = ExpandMacroParams;
114     type Result = Option<ExpandedMacro>;
115     const METHOD: &'static str = "rust-analyzer/expandMacro";
116 }
117
118 #[derive(Deserialize, Serialize, Debug)]
119 #[serde(rename_all = "camelCase")]
120 pub struct ExpandMacroParams {
121     pub text_document: TextDocumentIdentifier,
122     pub position: Position,
123 }
124
125 #[derive(Deserialize, Serialize, Debug)]
126 #[serde(rename_all = "camelCase")]
127 pub struct ExpandedMacro {
128     pub name: String,
129     pub expansion: String,
130 }
131
132 pub enum MatchingBrace {}
133
134 impl Request for MatchingBrace {
135     type Params = MatchingBraceParams;
136     type Result = Vec<Position>;
137     const METHOD: &'static str = "experimental/matchingBrace";
138 }
139
140 #[derive(Deserialize, Serialize, Debug)]
141 #[serde(rename_all = "camelCase")]
142 pub struct MatchingBraceParams {
143     pub text_document: TextDocumentIdentifier,
144     pub positions: Vec<Position>,
145 }
146
147 pub enum ParentModule {}
148
149 impl Request for ParentModule {
150     type Params = lsp_types::TextDocumentPositionParams;
151     type Result = Option<lsp_types::GotoDefinitionResponse>;
152     const METHOD: &'static str = "experimental/parentModule";
153 }
154
155 pub enum JoinLines {}
156
157 impl Request for JoinLines {
158     type Params = JoinLinesParams;
159     type Result = Vec<lsp_types::TextEdit>;
160     const METHOD: &'static str = "experimental/joinLines";
161 }
162
163 #[derive(Deserialize, Serialize, Debug)]
164 #[serde(rename_all = "camelCase")]
165 pub struct JoinLinesParams {
166     pub text_document: TextDocumentIdentifier,
167     pub ranges: Vec<Range>,
168 }
169
170 pub enum OnEnter {}
171
172 impl Request for OnEnter {
173     type Params = lsp_types::TextDocumentPositionParams;
174     type Result = Option<Vec<SnippetTextEdit>>;
175     const METHOD: &'static str = "experimental/onEnter";
176 }
177
178 pub enum Runnables {}
179
180 impl Request for Runnables {
181     type Params = RunnablesParams;
182     type Result = Vec<Runnable>;
183     const METHOD: &'static str = "experimental/runnables";
184 }
185
186 #[derive(Serialize, Deserialize, Debug)]
187 #[serde(rename_all = "camelCase")]
188 pub struct RunnablesParams {
189     pub text_document: TextDocumentIdentifier,
190     pub position: Option<Position>,
191 }
192
193 #[derive(Deserialize, Serialize, Debug)]
194 #[serde(rename_all = "camelCase")]
195 pub struct Runnable {
196     pub label: String,
197     #[serde(skip_serializing_if = "Option::is_none")]
198     pub location: Option<lsp_types::LocationLink>,
199     pub kind: RunnableKind,
200     pub args: CargoRunnable,
201 }
202
203 #[derive(Serialize, Deserialize, Debug)]
204 #[serde(rename_all = "lowercase")]
205 pub enum RunnableKind {
206     Cargo,
207 }
208
209 #[derive(Deserialize, Serialize, Debug)]
210 #[serde(rename_all = "camelCase")]
211 pub struct CargoRunnable {
212     // command to be executed instead of cargo
213     pub override_cargo: Option<String>,
214     #[serde(skip_serializing_if = "Option::is_none")]
215     pub workspace_root: Option<PathBuf>,
216     // command, --package and --lib stuff
217     pub cargo_args: Vec<String>,
218     // user-specified additional cargo args, like `--release`.
219     pub cargo_extra_args: Vec<String>,
220     // stuff after --
221     pub executable_args: Vec<String>,
222     #[serde(skip_serializing_if = "Option::is_none")]
223     pub expect_test: Option<bool>,
224 }
225
226 pub enum RelatedTests {}
227
228 impl Request for RelatedTests {
229     type Params = lsp_types::TextDocumentPositionParams;
230     type Result = Vec<TestInfo>;
231     const METHOD: &'static str = "rust-analyzer/relatedTests";
232 }
233
234 #[derive(Debug, Deserialize, Serialize)]
235 pub struct TestInfo {
236     pub runnable: Runnable,
237 }
238
239 #[derive(Serialize, Deserialize, Debug)]
240 #[serde(rename_all = "camelCase")]
241 pub struct InlayHintsParams {
242     pub text_document: TextDocumentIdentifier,
243     pub range: Option<lsp_types::Range>,
244 }
245
246 pub enum Ssr {}
247
248 impl Request for Ssr {
249     type Params = SsrParams;
250     type Result = lsp_types::WorkspaceEdit;
251     const METHOD: &'static str = "experimental/ssr";
252 }
253
254 #[derive(Debug, Deserialize, Serialize)]
255 #[serde(rename_all = "camelCase")]
256 pub struct SsrParams {
257     pub query: String,
258     pub parse_only: bool,
259
260     /// File position where SSR was invoked. Paths in `query` will be resolved relative to this
261     /// position.
262     #[serde(flatten)]
263     pub position: lsp_types::TextDocumentPositionParams,
264
265     /// Current selections. Search/replace will be restricted to these if non-empty.
266     pub selections: Vec<lsp_types::Range>,
267 }
268
269 pub enum ServerStatusNotification {}
270
271 impl Notification for ServerStatusNotification {
272     type Params = ServerStatusParams;
273     const METHOD: &'static str = "experimental/serverStatus";
274 }
275
276 #[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
277 pub struct ServerStatusParams {
278     pub health: Health,
279     pub quiescent: bool,
280     pub message: Option<String>,
281 }
282
283 #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
284 #[serde(rename_all = "camelCase")]
285 pub enum Health {
286     Ok,
287     Warning,
288     Error,
289 }
290
291 pub enum CodeActionRequest {}
292
293 impl Request for CodeActionRequest {
294     type Params = lsp_types::CodeActionParams;
295     type Result = Option<Vec<CodeAction>>;
296     const METHOD: &'static str = "textDocument/codeAction";
297 }
298
299 pub enum CodeActionResolveRequest {}
300 impl Request for CodeActionResolveRequest {
301     type Params = CodeAction;
302     type Result = CodeAction;
303     const METHOD: &'static str = "codeAction/resolve";
304 }
305
306 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
307 #[serde(rename_all = "camelCase")]
308 pub struct CodeAction {
309     pub title: String,
310     #[serde(skip_serializing_if = "Option::is_none")]
311     pub group: Option<String>,
312     #[serde(skip_serializing_if = "Option::is_none")]
313     pub kind: Option<CodeActionKind>,
314     #[serde(skip_serializing_if = "Option::is_none")]
315     pub command: Option<lsp_types::Command>,
316     #[serde(skip_serializing_if = "Option::is_none")]
317     pub edit: Option<SnippetWorkspaceEdit>,
318     #[serde(skip_serializing_if = "Option::is_none")]
319     pub is_preferred: Option<bool>,
320
321     #[serde(skip_serializing_if = "Option::is_none")]
322     pub data: Option<CodeActionData>,
323 }
324
325 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
326 #[serde(rename_all = "camelCase")]
327 pub struct CodeActionData {
328     pub code_action_params: lsp_types::CodeActionParams,
329     pub id: String,
330 }
331
332 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
333 #[serde(rename_all = "camelCase")]
334 pub struct SnippetWorkspaceEdit {
335     #[serde(skip_serializing_if = "Option::is_none")]
336     pub changes: Option<HashMap<lsp_types::Url, Vec<lsp_types::TextEdit>>>,
337     #[serde(skip_serializing_if = "Option::is_none")]
338     pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>,
339     #[serde(skip_serializing_if = "Option::is_none")]
340     pub change_annotations:
341         Option<HashMap<lsp_types::ChangeAnnotationIdentifier, lsp_types::ChangeAnnotation>>,
342 }
343
344 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
345 #[serde(untagged, rename_all = "lowercase")]
346 pub enum SnippetDocumentChangeOperation {
347     Op(lsp_types::ResourceOp),
348     Edit(SnippetTextDocumentEdit),
349 }
350
351 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
352 #[serde(rename_all = "camelCase")]
353 pub struct SnippetTextDocumentEdit {
354     pub text_document: lsp_types::OptionalVersionedTextDocumentIdentifier,
355     pub edits: Vec<SnippetTextEdit>,
356 }
357
358 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
359 #[serde(rename_all = "camelCase")]
360 pub struct SnippetTextEdit {
361     pub range: Range,
362     pub new_text: String,
363     #[serde(skip_serializing_if = "Option::is_none")]
364     pub insert_text_format: Option<lsp_types::InsertTextFormat>,
365     /// The annotation id if this is an annotated
366     #[serde(skip_serializing_if = "Option::is_none")]
367     pub annotation_id: Option<lsp_types::ChangeAnnotationIdentifier>,
368 }
369
370 pub enum HoverRequest {}
371
372 impl Request for HoverRequest {
373     type Params = HoverParams;
374     type Result = Option<Hover>;
375     const METHOD: &'static str = "textDocument/hover";
376 }
377
378 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
379 #[serde(rename_all = "camelCase")]
380 pub struct HoverParams {
381     pub text_document: TextDocumentIdentifier,
382     pub position: PositionOrRange,
383
384     #[serde(flatten)]
385     pub work_done_progress_params: WorkDoneProgressParams,
386 }
387
388 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
389 #[serde(untagged)]
390 pub enum PositionOrRange {
391     Position(lsp_types::Position),
392     Range(lsp_types::Range),
393 }
394
395 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
396 pub struct Hover {
397     #[serde(flatten)]
398     pub hover: lsp_types::Hover,
399     #[serde(skip_serializing_if = "Vec::is_empty")]
400     pub actions: Vec<CommandLinkGroup>,
401 }
402
403 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
404 pub struct CommandLinkGroup {
405     #[serde(skip_serializing_if = "Option::is_none")]
406     pub title: Option<String>,
407     pub commands: Vec<CommandLink>,
408 }
409
410 // LSP v3.15 Command does not have a `tooltip` field, vscode supports one.
411 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
412 pub struct CommandLink {
413     #[serde(flatten)]
414     pub command: lsp_types::Command,
415     #[serde(skip_serializing_if = "Option::is_none")]
416     pub tooltip: Option<String>,
417 }
418
419 pub enum ExternalDocs {}
420
421 impl Request for ExternalDocs {
422     type Params = lsp_types::TextDocumentPositionParams;
423     type Result = Option<lsp_types::Url>;
424     const METHOD: &'static str = "experimental/externalDocs";
425 }
426
427 pub enum OpenCargoToml {}
428
429 impl Request for OpenCargoToml {
430     type Params = OpenCargoTomlParams;
431     type Result = Option<lsp_types::GotoDefinitionResponse>;
432     const METHOD: &'static str = "experimental/openCargoToml";
433 }
434
435 #[derive(Serialize, Deserialize, Debug)]
436 #[serde(rename_all = "camelCase")]
437 pub struct OpenCargoTomlParams {
438     pub text_document: TextDocumentIdentifier,
439 }
440
441 /// Information about CodeLens, that is to be resolved.
442 #[derive(Debug, Serialize, Deserialize)]
443 #[serde(rename_all = "camelCase")]
444 pub(crate) enum CodeLensResolveData {
445     Impls(lsp_types::request::GotoImplementationParams),
446     References(lsp_types::TextDocumentPositionParams),
447 }
448
449 pub fn supports_utf8(caps: &lsp_types::ClientCapabilities) -> bool {
450     caps.offset_encoding.as_deref().unwrap_or_default().iter().any(|it| it == "utf-8")
451 }
452
453 pub enum MoveItem {}
454
455 impl Request for MoveItem {
456     type Params = MoveItemParams;
457     type Result = Vec<SnippetTextEdit>;
458     const METHOD: &'static str = "experimental/moveItem";
459 }
460
461 #[derive(Serialize, Deserialize, Debug)]
462 #[serde(rename_all = "camelCase")]
463 pub struct MoveItemParams {
464     pub direction: MoveItemDirection,
465     pub text_document: TextDocumentIdentifier,
466     pub range: Range,
467 }
468
469 #[derive(Serialize, Deserialize, Debug)]
470 pub enum MoveItemDirection {
471     Up,
472     Down,
473 }
474
475 #[derive(Debug)]
476 pub enum WorkspaceSymbol {}
477
478 impl Request for WorkspaceSymbol {
479     type Params = WorkspaceSymbolParams;
480     type Result = Option<Vec<lsp_types::SymbolInformation>>;
481     const METHOD: &'static str = "workspace/symbol";
482 }
483
484 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
485 #[serde(rename_all = "camelCase")]
486 pub struct WorkspaceSymbolParams {
487     #[serde(flatten)]
488     pub partial_result_params: PartialResultParams,
489
490     #[serde(flatten)]
491     pub work_done_progress_params: WorkDoneProgressParams,
492
493     /// A non-empty query string
494     pub query: String,
495
496     pub search_scope: Option<WorkspaceSymbolSearchScope>,
497
498     pub search_kind: Option<WorkspaceSymbolSearchKind>,
499 }
500
501 #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
502 #[serde(rename_all = "camelCase")]
503 pub enum WorkspaceSymbolSearchScope {
504     Workspace,
505     WorkspaceAndDependencies,
506 }
507
508 #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
509 #[serde(rename_all = "camelCase")]
510 pub enum WorkspaceSymbolSearchKind {
511     OnlyTypes,
512     AllSymbols,
513 }
514
515 #[derive(Debug, Serialize, Deserialize)]
516 pub struct CompletionResolveData {
517     pub position: lsp_types::TextDocumentPositionParams,
518     pub imports: Vec<CompletionImport>,
519 }
520
521 #[derive(Debug, Serialize, Deserialize)]
522 pub struct InlayHintResolveData {
523     pub position: lsp_types::TextDocumentPositionParams,
524 }
525
526 #[derive(Debug, Serialize, Deserialize)]
527 pub struct CompletionImport {
528     pub full_import_path: String,
529     pub imported_name: String,
530 }
531
532 #[derive(Debug, Deserialize, Default)]
533 pub struct ClientCommandOptions {
534     pub commands: Vec<String>,
535 }