From 343d5ff383dbb31115b96195a3d726e8ec38b32e Mon Sep 17 00:00:00 2001 From: edragain Date: Tue, 7 Jul 2026 15:54:08 +0000 Subject: [PATCH 1/7] fix: avoid panic in merge imports on trailing path separator --- crates/ide-assists/src/handlers/merge_imports.rs | 11 +++++++++++ crates/ide-db/src/imports/merge_imports.rs | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/merge_imports.rs b/crates/ide-assists/src/handlers/merge_imports.rs index c0356337057b..2d3b1b05400c 100644 --- a/crates/ide-assists/src/handlers/merge_imports.rs +++ b/crates/ide-assists/src/handlers/merge_imports.rs @@ -824,6 +824,17 @@ mod top { } use top::{a::A, b::{B as D, B as C}}; +", + ); + } + + #[test] + fn test_merge_with_trailing_path_separator() { + check_assist_not_applicable( + merge_imports, + r" +use foo::bar; +use foo::$0; ", ); } diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs index 9b68c27ae344..17fae61da613 100644 --- a/crates/ide-db/src/imports/merge_imports.rs +++ b/crates/ide-db/src/imports/merge_imports.rs @@ -827,7 +827,10 @@ fn split_prefix( make.use_tree(self_path, None, use_tree.rename(), false) } } else { - let suffix_segments = path.segments().skip(prefix.segments().count()); + let suffix_segments: Vec<_> = path.segments().skip(prefix.segments().count()).collect(); + if suffix_segments.is_empty() { + return None; + } let suffix_path = make.path_from_segments(suffix_segments, false); make.use_tree( suffix_path, From d299ea7515d19495b05c5f2fd55fc8b52adbc2c3 Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Wed, 24 Jun 2026 07:55:01 -0700 Subject: [PATCH 2/7] Bump gen-lsp-types to v0.10.0 Includes various metaModel updates, fixes, and API improvements to make e.g. LspRequestMethod more ergonomic (and use less allocations). --- Cargo.lock | 8 +- crates/rust-analyzer/Cargo.toml | 2 +- crates/rust-analyzer/src/diagnostics.rs | 2 +- .../src/diagnostics/flycheck_to_proto.rs | 4 +- .../test_data/clippy_pass_by_ref.txt | 12 ++- .../test_data/handles_macro_location.txt | 4 +- .../test_data/macro_compiler_error.txt | 12 ++- ...easonable_line_numbers_from_empty_file.txt | 4 +- .../rustc_incompatible_type_for_trait.txt | 4 +- .../test_data/rustc_mismatched_type.txt | 4 +- .../rustc_range_map_lsp_position.txt | 8 +- .../test_data/rustc_unused_variable.txt | 8 +- .../rustc_unused_variable_as_hint.txt | 8 +- .../rustc_unused_variable_as_info.txt | 8 +- .../rustc_wrong_number_of_parameters.txt | 8 +- .../test_data/snap_multi_line_fix.txt | 12 ++- crates/rust-analyzer/src/global_state.rs | 19 +++- crates/rust-analyzer/src/lsp/ext.rs | 95 ++++++++++--------- .../rust-analyzer/src/lsp/semantic_tokens.rs | 17 +--- crates/rust-analyzer/src/lsp/utils.rs | 1 + .../tests/slow-tests/flycheck.rs | 15 ++- docs/book/src/contributing/lsp-extensions.md | 2 +- lib/lsp-server/Cargo.toml | 2 +- lib/lsp-server/examples/minimal_lsp.rs | 13 +-- 24 files changed, 168 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6acaa08fac6..75ccd77262a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -720,9 +720,9 @@ dependencies = [ [[package]] name = "gen-lsp-types" -version = "0.4.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b8ec601e62362b666a3def1fed667ee87b10a4507402618376d142a05373c6" +checksum = "4cd635c5206acd03ea024d6b5902539e5c903de3afa220fdb5c94b583af77f4f" dependencies = [ "serde", "serde_json", @@ -2636,9 +2636,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "indexmap", "itoa", diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index dd8649e09529..ae0c9571210a 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -29,7 +29,7 @@ ide-completion.workspace = true indexmap.workspace = true itertools.workspace = true scip = "0.7.1" -lsp-types = { version = "0.4.0", package = "gen-lsp-types", features=["url"] } +lsp-types = { version = "0.10.0", package = "gen-lsp-types", features = ["url"] } parking_lot = "0.12.4" xflags = "0.3.2" oorandom = "11.1.5" diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index 889d20a184b2..9edcdf075bac 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -362,7 +362,7 @@ pub(crate) fn convert_diagnostic( href: lsp_types::Uri::parse(&d.code.url()).unwrap(), }), source: Some("rust-analyzer".to_owned()), - message: d.message, + message: lsp_types::Message::String(d.message), related_information: None, tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::Unnecessary]), data: None, diff --git a/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs b/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs index 8568f4798c03..59ab748c2f62 100644 --- a/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs @@ -375,7 +375,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( if needs_primary_span_label && let Some(primary_span_label) = &primary_span.label { format_to!(message, "\n{}", primary_span_label); } - message + lsp_types::Message::String(message) }; let mut related_info_macro_calls = vec![]; @@ -475,7 +475,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), code_description: code_description.clone(), source: Some(source.to_owned()), - message: sub.related.message.clone(), + message: sub.related.message.clone().into(), related_information: Some(vec![back_ref.clone()]), tags: None, // don't apply modifiers again data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt index 71f99874b173..4f6d2009d2c6 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt @@ -54,7 +54,9 @@ source: Some( "clippy", ), - message: "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref", + message: String( + "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref", + ), tags: None, related_information: Some( [ @@ -171,7 +173,9 @@ source: Some( "clippy", ), - message: "lint level defined here", + message: String( + "lint level defined here", + ), tags: None, related_information: Some( [ @@ -262,7 +266,9 @@ source: Some( "clippy", ), - message: "consider passing by value instead: `self`", + message: String( + "consider passing by value instead: `self`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt b/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt index bd1abfe92118..f1bcc06991c6 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "can't compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", + message: String( + "can't compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt b/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt index cc870c48af74..2405831682a7 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt @@ -30,7 +30,9 @@ source: Some( "rustc", ), - message: "Please register your known path in the path module", + message: String( + "Please register your known path in the path module", + ), tags: None, related_information: Some( [ @@ -97,7 +99,9 @@ source: Some( "rustc", ), - message: "Please register your known path in the path module", + message: String( + "Please register your known path in the path module", + ), tags: None, related_information: Some( [ @@ -164,7 +168,9 @@ source: Some( "rustc", ), - message: "Please register your known path in the path module", + message: String( + "Please register your known path in the path module", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt index 176d7198ac20..8500e61d300b 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "`main` function not found in crate `current`\nconsider adding a `main` function to `src/bin/current.rs`", + message: String( + "`main` function not found in crate `current`\nconsider adding a `main` function to `src/bin/current.rs`", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt index e78ac4b27dab..909bbe2f6a2f 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref>`", + message: String( + "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref>`", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt index add343d24566..39941652fda3 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "mismatched types\nexpected usize, found u32", + message: String( + "mismatched types\nexpected usize, found u32", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt index a510943965b4..3c10dacafb41 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "mismatched types\nexpected `u32`, found `&str`", + message: String( + "mismatched types\nexpected `u32`, found `&str`", + ), tags: None, related_information: Some( [ @@ -145,7 +147,9 @@ source: Some( "rustc", ), - message: "expected due to this", + message: String( + "expected due to this", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt index f5bf2dce3057..7410e1497287 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt @@ -34,7 +34,9 @@ source: Some( "rustc", ), - message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + message: String( + "unused variable: `foo`\n#[warn(unused_variables)] on by default", + ), tags: Some( [ Unnecessary, @@ -109,7 +111,9 @@ source: Some( "rustc", ), - message: "consider prefixing with an underscore: `_foo`", + message: String( + "consider prefixing with an underscore: `_foo`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt index 5f4aa7157644..0cff5ebba802 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt @@ -34,7 +34,9 @@ source: Some( "rustc", ), - message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + message: String( + "unused variable: `foo`\n#[warn(unused_variables)] on by default", + ), tags: Some( [ Unnecessary, @@ -109,7 +111,9 @@ source: Some( "rustc", ), - message: "consider prefixing with an underscore: `_foo`", + message: String( + "consider prefixing with an underscore: `_foo`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt index 26adf5311857..23797634ae05 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt @@ -34,7 +34,9 @@ source: Some( "rustc", ), - message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + message: String( + "unused variable: `foo`\n#[warn(unused_variables)] on by default", + ), tags: Some( [ Unnecessary, @@ -109,7 +111,9 @@ source: Some( "rustc", ), - message: "consider prefixing with an underscore: `_foo`", + message: String( + "consider prefixing with an underscore: `_foo`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt index cd3c24f0c3cf..900f99701b2b 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters", + message: String( + "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters", + ), tags: None, related_information: Some( [ @@ -145,7 +147,9 @@ source: Some( "rustc", ), - message: "defined here", + message: String( + "defined here", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt index a977d14cf784..bb8612f43ecf 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt @@ -54,7 +54,9 @@ source: Some( "clippy", ), - message: "returning the result of a let binding from a block\n`#[warn(clippy::let_and_return)]` on by default\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return", + message: String( + "returning the result of a let binding from a block\n`#[warn(clippy::let_and_return)]` on by default\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return", + ), tags: None, related_information: Some( [ @@ -171,7 +173,9 @@ source: Some( "clippy", ), - message: "unnecessary let binding", + message: String( + "unnecessary let binding", + ), tags: None, related_information: Some( [ @@ -262,7 +266,9 @@ source: Some( "clippy", ), - message: "return the expression directly: `(0..10).collect()`", + message: String( + "return the expression directly: `(0..10).collect()`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 2d01aa4d515e..5388f68f0219 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -661,17 +661,28 @@ impl GlobalState { // See https://github.com/rust-lang/rust-analyzer/issues/11404 // See https://github.com/rust-lang/rust-analyzer/issues/13130 - let patch_empty = |message: &mut String| { - if message.is_empty() { - " ".clone_into(message); + let patch_empty = |message: &mut lsp_types::Message| match message { + lsp_types::Message::String(m) if m.is_empty() => { + " ".clone_into(m); } + lsp_types::Message::MarkupContent(lsp_types::MarkupContent { + value, + kind: _, + }) if value.is_empty() => { + " ".clone_into(value); + } + _ => {} }; for d in &mut diagnostics { patch_empty(&mut d.message); if let Some(dri) = &mut d.related_information { for dri in dri { - patch_empty(&mut dri.message); + // The LSP does not (yet?) specify that related diagnostic messages can + // be in Markdown format (in addition to plain text). + if dri.message.is_empty() { + " ".clone_into(&mut dri.message); + } } } } diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs index 3a1945c88170..8e0bb285c231 100644 --- a/crates/rust-analyzer/src/lsp/ext.rs +++ b/crates/rust-analyzer/src/lsp/ext.rs @@ -35,7 +35,7 @@ impl Request for InternalTestingFetchConfigRequest { type Params = InternalTestingFetchConfigParams; // Option is solely to circumvent Default bound. type Result = Option; - const METHOD: LspRequestMethod = + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer-internal/internalTestingFetchConfig"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -51,7 +51,7 @@ pub enum AnalyzerStatusRequest {} impl Request for AnalyzerStatusRequest { type Params = AnalyzerStatusParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/analyzerStatus"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/analyzerStatus"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -73,7 +73,7 @@ pub enum FetchDependencyListRequest {} impl Request for FetchDependencyListRequest { type Params = FetchDependencyListParams; type Result = FetchDependencyListResult; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/fetchDependencyList"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/fetchDependencyList"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -92,7 +92,7 @@ pub enum MemoryUsageRequest {} impl Request for MemoryUsageRequest { type Params = (); type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/memoryUsage"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/memoryUsage"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -101,7 +101,7 @@ pub enum ReloadWorkspaceRequest {} impl Request for ReloadWorkspaceRequest { type Params = (); type Result = (); - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/reloadWorkspace"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/reloadWorkspace"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -110,7 +110,7 @@ pub enum RebuildProcMacrosRequest {} impl Request for RebuildProcMacrosRequest { type Params = (); type Result = (); - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/rebuildProcMacros"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/rebuildProcMacros"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -119,7 +119,7 @@ pub enum ViewSyntaxTreeRequest {} impl Request for ViewSyntaxTreeRequest { type Params = ViewSyntaxTreeParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewSyntaxTree"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewSyntaxTree"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -134,7 +134,7 @@ pub enum ViewHirRequest {} impl Request for ViewHirRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewHir"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewHir"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -143,7 +143,7 @@ pub enum ViewMirRequest {} impl Request for ViewMirRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewMir"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewMir"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -152,7 +152,7 @@ pub enum InterpretFunctionRequest {} impl Request for InterpretFunctionRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/interpretFunction"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/interpretFunction"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -161,7 +161,7 @@ pub enum ViewFileTextRequest {} impl Request for ViewFileTextRequest { type Params = lsp_types::TextDocumentIdentifier; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewFileText"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewFileText"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -177,7 +177,7 @@ pub enum ViewCrateGraphRequest {} impl Request for ViewCrateGraphRequest { type Params = ViewCrateGraphParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewCrateGraph"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewCrateGraph"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -192,7 +192,7 @@ pub enum ViewItemTreeRequest {} impl Request for ViewItemTreeRequest { type Params = ViewItemTreeParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewItemTree"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewItemTree"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -236,7 +236,7 @@ pub enum DiscoverTestRequest {} impl Request for DiscoverTestRequest { type Params = DiscoverTestParams; type Result = DiscoverTestResults; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/discoverTest"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/discoverTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -244,7 +244,7 @@ pub enum DiscoveredTestsNotification {} impl Notification for DiscoveredTestsNotification { type Params = DiscoverTestResults; - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/discoveredTests"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -261,7 +261,7 @@ pub enum RunTestRequest {} impl Request for RunTestRequest { type Params = RunTestParams; type Result = (); - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/runTest"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/runTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -269,7 +269,7 @@ pub enum EndRunTestNotification {} impl Notification for EndRunTestNotification { type Params = (); - const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/endRunTest"); + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/endRunTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -277,7 +277,7 @@ pub enum AppendOutputToRunTestNotification {} impl Notification for AppendOutputToRunTestNotification { type Params = String; - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/appendOutputToRunTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -286,7 +286,8 @@ pub enum AbortRunTestNotification {} impl Notification for AbortRunTestNotification { type Params = (); - const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/abortRunTest"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("experimental/abortRunTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -311,7 +312,7 @@ pub enum ChangeTestStateNotification {} impl Notification for ChangeTestStateNotification { type Params = ChangeTestStateParams; - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/changeTestState"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -321,7 +322,7 @@ pub enum ExpandMacroRequest {} impl Request for ExpandMacroRequest { type Params = ExpandMacroParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/expandMacro"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/expandMacro"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -344,7 +345,7 @@ pub enum ViewRecursiveMemoryLayoutRequest {} impl Request for ViewRecursiveMemoryLayoutRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option; - const METHOD: LspRequestMethod = + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewRecursiveMemoryLayout"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -372,7 +373,7 @@ pub enum CancelFlycheckNotification {} impl Notification for CancelFlycheckNotification { type Params = (); - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("rust-analyzer/cancelFlycheck"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -381,7 +382,8 @@ pub enum RunFlycheckNotification {} impl Notification for RunFlycheckNotification { type Params = RunFlycheckParams; - const METHOD: LspNotificationMethod = LspNotificationMethod::new("rust-analyzer/runFlycheck"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("rust-analyzer/runFlycheck"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -389,7 +391,8 @@ pub enum ClearFlycheckNotification {} impl Notification for ClearFlycheckNotification { type Params = (); - const METHOD: LspNotificationMethod = LspNotificationMethod::new("rust-analyzer/clearFlycheck"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("rust-analyzer/clearFlycheck"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -397,7 +400,7 @@ pub enum OpenServerLogsNotification {} impl Notification for OpenServerLogsNotification { type Params = (); - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("rust-analyzer/openServerLogs"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -413,7 +416,7 @@ pub enum MatchingBraceRequest {} impl Request for MatchingBraceRequest { type Params = MatchingBraceParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/matchingBrace"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/matchingBrace"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -429,7 +432,7 @@ pub enum ParentModuleRequest {} impl Request for ParentModuleRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/parentModule"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/parentModule"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -438,7 +441,7 @@ pub enum ChildModulesRequest {} impl Request for ChildModulesRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/childModules"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/childModules"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -447,7 +450,7 @@ pub enum JoinLinesRequest {} impl Request for JoinLinesRequest { type Params = JoinLinesParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/joinLines"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/joinLines"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -463,7 +466,7 @@ pub enum OnEnterRequest {} impl Request for OnEnterRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option>; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/onEnter"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/onEnter"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -472,7 +475,7 @@ pub enum RunnablesRequest {} impl Request for RunnablesRequest { type Params = RunnablesParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/runnables"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/runnables"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -531,7 +534,7 @@ pub enum RelatedTestsRequest {} impl Request for RelatedTestsRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/relatedTests"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/relatedTests"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -545,7 +548,7 @@ pub enum SsrRequest {} impl Request for SsrRequest { type Params = SsrParams; type Result = lsp_types::WorkspaceEdit; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/ssr"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/ssr"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -568,7 +571,8 @@ pub enum ServerStatusNotification {} impl Notification for ServerStatusNotification { type Params = ServerStatusParams; - const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/serverStatus"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("experimental/serverStatus"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -603,7 +607,7 @@ pub enum CodeActionRequest {} impl Request for CodeActionRequest { type Params = lsp_types::CodeActionParams; type Result = Option>; - const METHOD: LspRequestMethod = LspRequestMethod::new("textDocument/codeAction"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::TextDocumentCodeAction; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -612,7 +616,7 @@ pub enum CodeActionResolveRequest {} impl Request for CodeActionResolveRequest { type Params = CodeAction; type Result = CodeAction; - const METHOD: LspRequestMethod = LspRequestMethod::new("codeAction/resolve"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::CodeActionResolve; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -690,7 +694,7 @@ pub enum HoverRequest {} impl Request for HoverRequest { type Params = HoverParams; type Result = Option; - const METHOD: LspRequestMethod = lsp_types::HoverRequest::METHOD; + const METHOD: LspRequestMethod<'_> = lsp_types::HoverRequest::METHOD; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -740,7 +744,7 @@ pub enum ExternalDocsRequest {} impl Request for ExternalDocsRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = ExternalDocsResponse; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/externalDocs"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/externalDocs"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -769,7 +773,7 @@ pub enum OpenCargoTomlRequest {} impl Request for OpenCargoTomlRequest { type Params = OpenCargoTomlParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/openCargoToml"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/openCargoToml"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -799,7 +803,7 @@ pub enum MoveItemRequest {} impl Request for MoveItemRequest { type Params = MoveItemParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/moveItem"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/moveItem"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -823,7 +827,7 @@ pub enum WorkspaceSymbolRequest {} impl Request for WorkspaceSymbolRequest { type Params = WorkspaceSymbolParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("workspace/symbol"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::WorkspaceSymbol; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -868,7 +872,7 @@ pub enum DocumentOnTypeFormattingRequest {} impl Request for DocumentOnTypeFormattingRequest { type Params = DocumentOnTypeFormattingParams; type Result = Option>; - const METHOD: LspRequestMethod = LspRequestMethod::new("textDocument/onTypeFormatting"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::TextDocumentOnTypeFormatting; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -938,7 +942,7 @@ pub enum PredicateEvaluationStatus { impl Request for EvaluatePredicateRequest { type Params = EvaluatePredicateParams; type Result = EvaluatePredicateResult; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/evaluatePredicate"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/evaluatePredicate"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -954,7 +958,8 @@ pub struct GetFailedObligationsParams { impl Request for GetFailedObligationsRequest { type Params = GetFailedObligationsParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/getFailedObligations"); + const METHOD: LspRequestMethod<'_> = + LspRequestMethod::new("rust-analyzer/getFailedObligations"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } diff --git a/crates/rust-analyzer/src/lsp/semantic_tokens.rs b/crates/rust-analyzer/src/lsp/semantic_tokens.rs index 78198064238c..fcfe3fb27c29 100644 --- a/crates/rust-analyzer/src/lsp/semantic_tokens.rs +++ b/crates/rust-analyzer/src/lsp/semantic_tokens.rs @@ -344,10 +344,11 @@ pub(crate) fn diff_tokens( // The lsp data field is actually a byte-diff but we // travel in tokens so `start` and `delete_count` are in multiples of the // serialized size of `SemanticToken`. + let data = new.iter().copied().flat_map(<[u32; 5]>::from).collect(); vec![SemanticTokensEdit { start: 5 * offset as u32, delete_count: 5 * old.len() as u32, - data: Some(new.into()), + data: Some(data), }] } } @@ -378,11 +379,7 @@ mod tests { let edits = diff_tokens(&before, &after); assert_eq!( edits[0], - SemanticTokensEdit { - start: 10, - delete_count: 0, - data: Some(vec![from((11, 12, 13, 14, 15))]) - } + SemanticTokensEdit { start: 10, delete_count: 0, data: Some(vec![11, 12, 13, 14, 15]) } ); } @@ -394,11 +391,7 @@ mod tests { let edits = diff_tokens(&before, &after); assert_eq!( edits[0], - SemanticTokensEdit { - start: 0, - delete_count: 0, - data: Some(vec![from((11, 12, 13, 14, 15))]) - } + SemanticTokensEdit { start: 0, delete_count: 0, data: Some(vec![11, 12, 13, 14, 15]) } ); } @@ -418,7 +411,7 @@ mod tests { SemanticTokensEdit { start: 5, delete_count: 0, - data: Some(vec![from((10, 20, 30, 40, 50)), from((60, 70, 80, 90, 100))]) + data: Some(vec![10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) } ); } diff --git a/crates/rust-analyzer/src/lsp/utils.rs b/crates/rust-analyzer/src/lsp/utils.rs index ebec0f990a17..00e94fb50c85 100644 --- a/crates/rust-analyzer/src/lsp/utils.rs +++ b/crates/rust-analyzer/src/lsp/utils.rs @@ -48,6 +48,7 @@ impl GlobalState { message, actions: Some(vec![lsp_types::MessageActionItem { title: "Open server logs".to_owned(), + properties: Default::default(), }]), }, |this, resp| { diff --git a/crates/rust-analyzer/tests/slow-tests/flycheck.rs b/crates/rust-analyzer/tests/slow-tests/flycheck.rs index c6f1f81139d2..7700643f03e7 100644 --- a/crates/rust-analyzer/tests/slow-tests/flycheck.rs +++ b/crates/rust-analyzer/tests/slow-tests/flycheck.rs @@ -2,6 +2,13 @@ use test_utils::skip_slow_tests; use crate::support::Project; +fn message_contains(message: &lsp_types::Message, p: &str) -> bool { + match message { + lsp_types::Message::String(s) => s.contains(p), + lsp_types::Message::MarkupContent(mc) => mc.value.contains(p), + } +} + #[test] fn test_flycheck_diagnostics_for_unused_variable() { if skip_slow_tests() { @@ -29,7 +36,7 @@ fn main() { let diagnostics = server.wait_for_diagnostics(); assert!( - diagnostics.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diagnostics.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diagnostics.diagnostics, ); @@ -63,7 +70,7 @@ fn main() { // Wait for the unused variable diagnostic to appear. let diagnostics = server.wait_for_diagnostics(); assert!( - diagnostics.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diagnostics.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diagnostics.diagnostics, ); @@ -105,7 +112,7 @@ fn main() {} let diagnostics = server.wait_for_diagnostics(); assert!( - diagnostics.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diagnostics.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diagnostics.diagnostics, ); @@ -143,7 +150,7 @@ fn main() {} let diags = server.wait_for_diagnostics(); assert!( - diags.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diags.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diags.diagnostics, ); diff --git a/docs/book/src/contributing/lsp-extensions.md b/docs/book/src/contributing/lsp-extensions.md index 6902bce83e6c..da4a5aaa686c 100644 --- a/docs/book/src/contributing/lsp-extensions.md +++ b/docs/book/src/contributing/lsp-extensions.md @@ -1,5 +1,5 @@