• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! rust-analyzer extensions to the LSP.
2 
3 use std::{collections::HashMap, path::PathBuf};
4 
5 use ide_db::line_index::WideEncoding;
6 use lsp_types::request::Request;
7 use lsp_types::{
8     notification::Notification, CodeActionKind, DocumentOnTypeFormattingParams,
9     PartialResultParams, Position, Range, TextDocumentIdentifier, WorkDoneProgressParams,
10 };
11 use lsp_types::{PositionEncodingKind, Url};
12 use serde::{Deserialize, Serialize};
13 
14 use crate::line_index::PositionEncoding;
15 
16 pub enum AnalyzerStatus {}
17 
18 impl Request for AnalyzerStatus {
19     type Params = AnalyzerStatusParams;
20     type Result = String;
21     const METHOD: &'static str = "rust-analyzer/analyzerStatus";
22 }
23 
24 #[derive(Deserialize, Serialize, Debug)]
25 #[serde(rename_all = "camelCase")]
26 pub struct AnalyzerStatusParams {
27     pub text_document: Option<TextDocumentIdentifier>,
28 }
29 
30 #[derive(Deserialize, Serialize, Debug)]
31 #[serde(rename_all = "camelCase")]
32 pub struct CrateInfoResult {
33     pub name: Option<String>,
34     pub version: Option<String>,
35     pub path: Url,
36 }
37 pub enum FetchDependencyList {}
38 
39 impl Request for FetchDependencyList {
40     type Params = FetchDependencyListParams;
41     type Result = FetchDependencyListResult;
42     const METHOD: &'static str = "rust-analyzer/fetchDependencyList";
43 }
44 
45 #[derive(Deserialize, Serialize, Debug)]
46 #[serde(rename_all = "camelCase")]
47 pub struct FetchDependencyListParams {}
48 
49 #[derive(Deserialize, Serialize, Debug)]
50 #[serde(rename_all = "camelCase")]
51 pub struct FetchDependencyListResult {
52     pub crates: Vec<CrateInfoResult>,
53 }
54 
55 pub enum MemoryUsage {}
56 
57 impl Request for MemoryUsage {
58     type Params = ();
59     type Result = String;
60     const METHOD: &'static str = "rust-analyzer/memoryUsage";
61 }
62 
63 pub enum ShuffleCrateGraph {}
64 
65 impl Request for ShuffleCrateGraph {
66     type Params = ();
67     type Result = ();
68     const METHOD: &'static str = "rust-analyzer/shuffleCrateGraph";
69 }
70 
71 pub enum ReloadWorkspace {}
72 
73 impl Request for ReloadWorkspace {
74     type Params = ();
75     type Result = ();
76     const METHOD: &'static str = "rust-analyzer/reloadWorkspace";
77 }
78 
79 pub enum RebuildProcMacros {}
80 
81 impl Request for RebuildProcMacros {
82     type Params = ();
83     type Result = ();
84     const METHOD: &'static str = "rust-analyzer/rebuildProcMacros";
85 }
86 
87 pub enum SyntaxTree {}
88 
89 impl Request for SyntaxTree {
90     type Params = SyntaxTreeParams;
91     type Result = String;
92     const METHOD: &'static str = "rust-analyzer/syntaxTree";
93 }
94 
95 #[derive(Deserialize, Serialize, Debug)]
96 #[serde(rename_all = "camelCase")]
97 pub struct SyntaxTreeParams {
98     pub text_document: TextDocumentIdentifier,
99     pub range: Option<Range>,
100 }
101 
102 pub enum ViewHir {}
103 
104 impl Request for ViewHir {
105     type Params = lsp_types::TextDocumentPositionParams;
106     type Result = String;
107     const METHOD: &'static str = "rust-analyzer/viewHir";
108 }
109 
110 pub enum ViewMir {}
111 
112 impl Request for ViewMir {
113     type Params = lsp_types::TextDocumentPositionParams;
114     type Result = String;
115     const METHOD: &'static str = "rust-analyzer/viewMir";
116 }
117 
118 pub enum InterpretFunction {}
119 
120 impl Request for InterpretFunction {
121     type Params = lsp_types::TextDocumentPositionParams;
122     type Result = String;
123     const METHOD: &'static str = "rust-analyzer/interpretFunction";
124 }
125 
126 pub enum ViewFileText {}
127 
128 impl Request for ViewFileText {
129     type Params = lsp_types::TextDocumentIdentifier;
130     type Result = String;
131     const METHOD: &'static str = "rust-analyzer/viewFileText";
132 }
133 
134 #[derive(Deserialize, Serialize, Debug)]
135 #[serde(rename_all = "camelCase")]
136 pub struct ViewCrateGraphParams {
137     /// Include *all* crates, not just crates in the workspace.
138     pub full: bool,
139 }
140 
141 pub enum ViewCrateGraph {}
142 
143 impl Request for ViewCrateGraph {
144     type Params = ViewCrateGraphParams;
145     type Result = String;
146     const METHOD: &'static str = "rust-analyzer/viewCrateGraph";
147 }
148 
149 #[derive(Deserialize, Serialize, Debug)]
150 #[serde(rename_all = "camelCase")]
151 pub struct ViewItemTreeParams {
152     pub text_document: TextDocumentIdentifier,
153 }
154 
155 pub enum ViewItemTree {}
156 
157 impl Request for ViewItemTree {
158     type Params = ViewItemTreeParams;
159     type Result = String;
160     const METHOD: &'static str = "rust-analyzer/viewItemTree";
161 }
162 
163 pub enum ExpandMacro {}
164 
165 impl Request for ExpandMacro {
166     type Params = ExpandMacroParams;
167     type Result = Option<ExpandedMacro>;
168     const METHOD: &'static str = "rust-analyzer/expandMacro";
169 }
170 
171 #[derive(Deserialize, Serialize, Debug)]
172 #[serde(rename_all = "camelCase")]
173 pub struct ExpandMacroParams {
174     pub text_document: TextDocumentIdentifier,
175     pub position: Position,
176 }
177 
178 #[derive(Deserialize, Serialize, Debug)]
179 #[serde(rename_all = "camelCase")]
180 pub struct ExpandedMacro {
181     pub name: String,
182     pub expansion: String,
183 }
184 
185 pub enum CancelFlycheck {}
186 
187 impl Notification for CancelFlycheck {
188     type Params = ();
189     const METHOD: &'static str = "rust-analyzer/cancelFlycheck";
190 }
191 
192 pub enum RunFlycheck {}
193 
194 impl Notification for RunFlycheck {
195     type Params = RunFlycheckParams;
196     const METHOD: &'static str = "rust-analyzer/runFlycheck";
197 }
198 
199 pub enum ClearFlycheck {}
200 
201 impl Notification for ClearFlycheck {
202     type Params = ();
203     const METHOD: &'static str = "rust-analyzer/clearFlycheck";
204 }
205 
206 pub enum OpenServerLogs {}
207 
208 impl Notification for OpenServerLogs {
209     type Params = ();
210     const METHOD: &'static str = "rust-analyzer/openServerLogs";
211 }
212 
213 #[derive(Deserialize, Serialize, Debug)]
214 #[serde(rename_all = "camelCase")]
215 pub struct RunFlycheckParams {
216     pub text_document: Option<TextDocumentIdentifier>,
217 }
218 
219 pub enum MatchingBrace {}
220 
221 impl Request for MatchingBrace {
222     type Params = MatchingBraceParams;
223     type Result = Vec<Position>;
224     const METHOD: &'static str = "experimental/matchingBrace";
225 }
226 
227 #[derive(Deserialize, Serialize, Debug)]
228 #[serde(rename_all = "camelCase")]
229 pub struct MatchingBraceParams {
230     pub text_document: TextDocumentIdentifier,
231     pub positions: Vec<Position>,
232 }
233 
234 pub enum ParentModule {}
235 
236 impl Request for ParentModule {
237     type Params = lsp_types::TextDocumentPositionParams;
238     type Result = Option<lsp_types::GotoDefinitionResponse>;
239     const METHOD: &'static str = "experimental/parentModule";
240 }
241 
242 pub enum JoinLines {}
243 
244 impl Request for JoinLines {
245     type Params = JoinLinesParams;
246     type Result = Vec<lsp_types::TextEdit>;
247     const METHOD: &'static str = "experimental/joinLines";
248 }
249 
250 #[derive(Deserialize, Serialize, Debug)]
251 #[serde(rename_all = "camelCase")]
252 pub struct JoinLinesParams {
253     pub text_document: TextDocumentIdentifier,
254     pub ranges: Vec<Range>,
255 }
256 
257 pub enum OnEnter {}
258 
259 impl Request for OnEnter {
260     type Params = lsp_types::TextDocumentPositionParams;
261     type Result = Option<Vec<SnippetTextEdit>>;
262     const METHOD: &'static str = "experimental/onEnter";
263 }
264 
265 pub enum Runnables {}
266 
267 impl Request for Runnables {
268     type Params = RunnablesParams;
269     type Result = Vec<Runnable>;
270     const METHOD: &'static str = "experimental/runnables";
271 }
272 
273 #[derive(Serialize, Deserialize, Debug)]
274 #[serde(rename_all = "camelCase")]
275 pub struct RunnablesParams {
276     pub text_document: TextDocumentIdentifier,
277     pub position: Option<Position>,
278 }
279 
280 #[derive(Deserialize, Serialize, Debug)]
281 #[serde(rename_all = "camelCase")]
282 pub struct Runnable {
283     pub label: String,
284     #[serde(skip_serializing_if = "Option::is_none")]
285     pub location: Option<lsp_types::LocationLink>,
286     pub kind: RunnableKind,
287     pub args: CargoRunnable,
288 }
289 
290 #[derive(Serialize, Deserialize, Debug)]
291 #[serde(rename_all = "lowercase")]
292 pub enum RunnableKind {
293     Cargo,
294 }
295 
296 #[derive(Deserialize, Serialize, Debug)]
297 #[serde(rename_all = "camelCase")]
298 pub struct CargoRunnable {
299     // command to be executed instead of cargo
300     pub override_cargo: Option<String>,
301     #[serde(skip_serializing_if = "Option::is_none")]
302     pub workspace_root: Option<PathBuf>,
303     // command, --package and --lib stuff
304     pub cargo_args: Vec<String>,
305     // user-specified additional cargo args, like `--release`.
306     pub cargo_extra_args: Vec<String>,
307     // stuff after --
308     pub executable_args: Vec<String>,
309     #[serde(skip_serializing_if = "Option::is_none")]
310     pub expect_test: Option<bool>,
311 }
312 
313 pub enum RelatedTests {}
314 
315 impl Request for RelatedTests {
316     type Params = lsp_types::TextDocumentPositionParams;
317     type Result = Vec<TestInfo>;
318     const METHOD: &'static str = "rust-analyzer/relatedTests";
319 }
320 
321 #[derive(Debug, Deserialize, Serialize)]
322 pub struct TestInfo {
323     pub runnable: Runnable,
324 }
325 
326 #[derive(Serialize, Deserialize, Debug)]
327 #[serde(rename_all = "camelCase")]
328 pub struct InlayHintsParams {
329     pub text_document: TextDocumentIdentifier,
330     pub range: Option<lsp_types::Range>,
331 }
332 
333 pub enum Ssr {}
334 
335 impl Request for Ssr {
336     type Params = SsrParams;
337     type Result = lsp_types::WorkspaceEdit;
338     const METHOD: &'static str = "experimental/ssr";
339 }
340 
341 #[derive(Debug, Deserialize, Serialize)]
342 #[serde(rename_all = "camelCase")]
343 pub struct SsrParams {
344     pub query: String,
345     pub parse_only: bool,
346 
347     /// File position where SSR was invoked. Paths in `query` will be resolved relative to this
348     /// position.
349     #[serde(flatten)]
350     pub position: lsp_types::TextDocumentPositionParams,
351 
352     /// Current selections. Search/replace will be restricted to these if non-empty.
353     pub selections: Vec<lsp_types::Range>,
354 }
355 
356 pub enum ServerStatusNotification {}
357 
358 impl Notification for ServerStatusNotification {
359     type Params = ServerStatusParams;
360     const METHOD: &'static str = "experimental/serverStatus";
361 }
362 
363 #[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
364 pub struct ServerStatusParams {
365     pub health: Health,
366     pub quiescent: bool,
367     pub message: Option<String>,
368 }
369 
370 #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
371 #[serde(rename_all = "camelCase")]
372 pub enum Health {
373     Ok,
374     Warning,
375     Error,
376 }
377 
378 pub enum CodeActionRequest {}
379 
380 impl Request for CodeActionRequest {
381     type Params = lsp_types::CodeActionParams;
382     type Result = Option<Vec<CodeAction>>;
383     const METHOD: &'static str = "textDocument/codeAction";
384 }
385 
386 pub enum CodeActionResolveRequest {}
387 
388 impl Request for CodeActionResolveRequest {
389     type Params = CodeAction;
390     type Result = CodeAction;
391     const METHOD: &'static str = "codeAction/resolve";
392 }
393 
394 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
395 #[serde(rename_all = "camelCase")]
396 pub struct CodeAction {
397     pub title: String,
398     #[serde(skip_serializing_if = "Option::is_none")]
399     pub group: Option<String>,
400     #[serde(skip_serializing_if = "Option::is_none")]
401     pub kind: Option<CodeActionKind>,
402     #[serde(skip_serializing_if = "Option::is_none")]
403     pub command: Option<lsp_types::Command>,
404     #[serde(skip_serializing_if = "Option::is_none")]
405     pub edit: Option<SnippetWorkspaceEdit>,
406     #[serde(skip_serializing_if = "Option::is_none")]
407     pub is_preferred: Option<bool>,
408 
409     #[serde(skip_serializing_if = "Option::is_none")]
410     pub data: Option<CodeActionData>,
411 }
412 
413 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
414 #[serde(rename_all = "camelCase")]
415 pub struct CodeActionData {
416     pub code_action_params: lsp_types::CodeActionParams,
417     pub id: String,
418 }
419 
420 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
421 #[serde(rename_all = "camelCase")]
422 pub struct SnippetWorkspaceEdit {
423     #[serde(skip_serializing_if = "Option::is_none")]
424     pub changes: Option<HashMap<lsp_types::Url, Vec<lsp_types::TextEdit>>>,
425     #[serde(skip_serializing_if = "Option::is_none")]
426     pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>,
427     #[serde(skip_serializing_if = "Option::is_none")]
428     pub change_annotations:
429         Option<HashMap<lsp_types::ChangeAnnotationIdentifier, lsp_types::ChangeAnnotation>>,
430 }
431 
432 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
433 #[serde(untagged, rename_all = "lowercase")]
434 pub enum SnippetDocumentChangeOperation {
435     Op(lsp_types::ResourceOp),
436     Edit(SnippetTextDocumentEdit),
437 }
438 
439 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
440 #[serde(rename_all = "camelCase")]
441 pub struct SnippetTextDocumentEdit {
442     pub text_document: lsp_types::OptionalVersionedTextDocumentIdentifier,
443     pub edits: Vec<SnippetTextEdit>,
444 }
445 
446 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
447 #[serde(rename_all = "camelCase")]
448 pub struct SnippetTextEdit {
449     pub range: Range,
450     pub new_text: String,
451     #[serde(skip_serializing_if = "Option::is_none")]
452     pub insert_text_format: Option<lsp_types::InsertTextFormat>,
453     /// The annotation id if this is an annotated
454     #[serde(skip_serializing_if = "Option::is_none")]
455     pub annotation_id: Option<lsp_types::ChangeAnnotationIdentifier>,
456 }
457 
458 pub enum HoverRequest {}
459 
460 impl Request for HoverRequest {
461     type Params = HoverParams;
462     type Result = Option<Hover>;
463     const METHOD: &'static str = lsp_types::request::HoverRequest::METHOD;
464 }
465 
466 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
467 #[serde(rename_all = "camelCase")]
468 pub struct HoverParams {
469     pub text_document: TextDocumentIdentifier,
470     pub position: PositionOrRange,
471 
472     #[serde(flatten)]
473     pub work_done_progress_params: WorkDoneProgressParams,
474 }
475 
476 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
477 #[serde(untagged)]
478 pub enum PositionOrRange {
479     Position(lsp_types::Position),
480     Range(lsp_types::Range),
481 }
482 
483 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
484 pub struct Hover {
485     #[serde(flatten)]
486     pub hover: lsp_types::Hover,
487     #[serde(skip_serializing_if = "Vec::is_empty")]
488     pub actions: Vec<CommandLinkGroup>,
489 }
490 
491 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
492 pub struct CommandLinkGroup {
493     #[serde(skip_serializing_if = "Option::is_none")]
494     pub title: Option<String>,
495     pub commands: Vec<CommandLink>,
496 }
497 
498 // LSP v3.15 Command does not have a `tooltip` field, vscode supports one.
499 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
500 pub struct CommandLink {
501     #[serde(flatten)]
502     pub command: lsp_types::Command,
503     #[serde(skip_serializing_if = "Option::is_none")]
504     pub tooltip: Option<String>,
505 }
506 
507 pub enum ExternalDocs {}
508 
509 impl Request for ExternalDocs {
510     type Params = lsp_types::TextDocumentPositionParams;
511     type Result = ExternalDocsResponse;
512     const METHOD: &'static str = "experimental/externalDocs";
513 }
514 
515 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
516 #[serde(untagged)]
517 pub enum ExternalDocsResponse {
518     Simple(Option<lsp_types::Url>),
519     WithLocal(ExternalDocsPair),
520 }
521 
522 #[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
523 #[serde(rename_all = "camelCase")]
524 pub struct ExternalDocsPair {
525     pub web: Option<lsp_types::Url>,
526     pub local: Option<lsp_types::Url>,
527 }
528 
529 pub enum OpenCargoToml {}
530 
531 impl Request for OpenCargoToml {
532     type Params = OpenCargoTomlParams;
533     type Result = Option<lsp_types::GotoDefinitionResponse>;
534     const METHOD: &'static str = "experimental/openCargoToml";
535 }
536 
537 #[derive(Serialize, Deserialize, Debug)]
538 #[serde(rename_all = "camelCase")]
539 pub struct OpenCargoTomlParams {
540     pub text_document: TextDocumentIdentifier,
541 }
542 
543 /// Information about CodeLens, that is to be resolved.
544 #[derive(Debug, Serialize, Deserialize)]
545 #[serde(rename_all = "camelCase")]
546 pub struct CodeLensResolveData {
547     pub version: i32,
548     pub kind: CodeLensResolveDataKind,
549 }
550 
551 #[derive(Debug, Serialize, Deserialize)]
552 #[serde(rename_all = "camelCase")]
553 pub enum CodeLensResolveDataKind {
554     Impls(lsp_types::request::GotoImplementationParams),
555     References(lsp_types::TextDocumentPositionParams),
556 }
557 
negotiated_encoding(caps: &lsp_types::ClientCapabilities) -> PositionEncoding558 pub fn negotiated_encoding(caps: &lsp_types::ClientCapabilities) -> PositionEncoding {
559     let client_encodings = match &caps.general {
560         Some(general) => general.position_encodings.as_deref().unwrap_or_default(),
561         None => &[],
562     };
563 
564     for enc in client_encodings {
565         if enc == &PositionEncodingKind::UTF8 {
566             return PositionEncoding::Utf8;
567         } else if enc == &PositionEncodingKind::UTF32 {
568             return PositionEncoding::Wide(WideEncoding::Utf32);
569         }
570         // NB: intentionally prefer just about anything else to utf-16.
571     }
572 
573     PositionEncoding::Wide(WideEncoding::Utf16)
574 }
575 
576 pub enum MoveItem {}
577 
578 impl Request for MoveItem {
579     type Params = MoveItemParams;
580     type Result = Vec<SnippetTextEdit>;
581     const METHOD: &'static str = "experimental/moveItem";
582 }
583 
584 #[derive(Serialize, Deserialize, Debug)]
585 #[serde(rename_all = "camelCase")]
586 pub struct MoveItemParams {
587     pub direction: MoveItemDirection,
588     pub text_document: TextDocumentIdentifier,
589     pub range: Range,
590 }
591 
592 #[derive(Serialize, Deserialize, Debug)]
593 pub enum MoveItemDirection {
594     Up,
595     Down,
596 }
597 
598 #[derive(Debug)]
599 pub enum WorkspaceSymbol {}
600 
601 impl Request for WorkspaceSymbol {
602     type Params = WorkspaceSymbolParams;
603     type Result = Option<Vec<lsp_types::SymbolInformation>>;
604     const METHOD: &'static str = "workspace/symbol";
605 }
606 
607 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
608 #[serde(rename_all = "camelCase")]
609 pub struct WorkspaceSymbolParams {
610     #[serde(flatten)]
611     pub partial_result_params: PartialResultParams,
612 
613     #[serde(flatten)]
614     pub work_done_progress_params: WorkDoneProgressParams,
615 
616     /// A non-empty query string
617     pub query: String,
618 
619     pub search_scope: Option<WorkspaceSymbolSearchScope>,
620 
621     pub search_kind: Option<WorkspaceSymbolSearchKind>,
622 }
623 
624 #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
625 #[serde(rename_all = "camelCase")]
626 pub enum WorkspaceSymbolSearchScope {
627     Workspace,
628     WorkspaceAndDependencies,
629 }
630 
631 #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
632 #[serde(rename_all = "camelCase")]
633 pub enum WorkspaceSymbolSearchKind {
634     OnlyTypes,
635     AllSymbols,
636 }
637 
638 /// The document on type formatting request is sent from the client to
639 /// the server to format parts of the document during typing.  This is
640 /// almost same as lsp_types::request::OnTypeFormatting, but the
641 /// result has SnippetTextEdit in it instead of TextEdit.
642 #[derive(Debug)]
643 pub enum OnTypeFormatting {}
644 
645 impl Request for OnTypeFormatting {
646     type Params = DocumentOnTypeFormattingParams;
647     type Result = Option<Vec<SnippetTextEdit>>;
648     const METHOD: &'static str = "textDocument/onTypeFormatting";
649 }
650 
651 #[derive(Debug, Serialize, Deserialize)]
652 pub struct CompletionResolveData {
653     pub position: lsp_types::TextDocumentPositionParams,
654     pub imports: Vec<CompletionImport>,
655 }
656 
657 #[derive(Debug, Serialize, Deserialize)]
658 pub struct InlayHintResolveData {}
659 
660 #[derive(Debug, Serialize, Deserialize)]
661 pub struct CompletionImport {
662     pub full_import_path: String,
663     pub imported_name: String,
664 }
665 
666 #[derive(Debug, Deserialize, Default)]
667 pub struct ClientCommandOptions {
668     pub commands: Vec<String>,
669 }
670