From de05c3d406fb91dea736769c91cbc35f24abf761 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sat, 4 Dec 2021 19:59:05 -0800 Subject: [PATCH 1/3] Refactor away unnecessary Vec --- crates/rust-analyzer/src/diagnostics.rs | 4 ++-- crates/rust-analyzer/src/diagnostics/to_proto.rs | 8 ++++---- crates/rust-analyzer/src/main_loop.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index 2f63c26ce5..c0dab45889 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -43,7 +43,7 @@ impl DiagnosticCollection { &mut self, file_id: FileId, diagnostic: lsp_types::Diagnostic, - fixes: Vec, + fix: Option, ) { let diagnostics = self.check.entry(file_id).or_default(); for existing_diagnostic in diagnostics.iter() { @@ -56,7 +56,7 @@ impl DiagnosticCollection { check_fixes .entry(file_id) .or_default() - .extend(fixes.into_iter().map(|action| Fix { range: diagnostic.range, action })); + .extend(fix.into_iter().map(|action| Fix { range: diagnostic.range, action })); diagnostics.push(diagnostic); self.changes.insert(file_id); } diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index 4739cabae5..48af9c186d 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -192,7 +192,7 @@ fn map_rust_child_diagnostic( pub(crate) struct MappedRustDiagnostic { pub(crate) url: lsp_types::Url, pub(crate) diagnostic: lsp_types::Diagnostic, - pub(crate) fixes: Vec, + pub(crate) fix: Option, } /// Converts a Rust root diagnostic to LSP form @@ -349,7 +349,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( diagnostics.push(MappedRustDiagnostic { url: secondary_location.uri, diagnostic, - fixes: Vec::new(), + fix: None, }); } @@ -378,7 +378,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( tags: if tags.is_empty() { None } else { Some(tags.clone()) }, data: None, }, - fixes: Vec::new(), + fix: None, }); // Emit hint-level diagnostics for all `related_information` entries such as "help"s. @@ -395,7 +395,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( } diagnostics.push(MappedRustDiagnostic { url: sub.related.location.uri.clone(), - fixes: sub.suggested_fix.iter().cloned().collect(), + fix: sub.suggested_fix.clone(), diagnostic: lsp_types::Diagnostic { range: sub.related.location.range, severity: Some(lsp_types::DiagnosticSeverity::Hint), diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 0c48b22bdb..c05a97eeed 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -370,7 +370,7 @@ impl GlobalState { Ok(file_id) => self.diagnostics.add_check_diagnostic( file_id, diag.diagnostic, - diag.fixes, + diag.fix, ), Err(err) => { tracing::error!( From 0d1910c6fb5539330b2464778a1db823aae35aa0 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sat, 4 Dec 2021 20:59:26 -0800 Subject: [PATCH 2/3] Handle multiple cargo check quick fix spans --- crates/rust-analyzer/src/diagnostics.rs | 10 +++--- .../rust-analyzer/src/diagnostics/to_proto.rs | 36 +++++++++++-------- crates/rust-analyzer/src/handlers.rs | 9 +++-- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index c0dab45889..56b3afce98 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -29,7 +29,8 @@ pub(crate) struct DiagnosticCollection { #[derive(Debug, Clone)] pub(crate) struct Fix { - pub(crate) range: lsp_types::Range, + // Fixes may be triggerable from multiple ranges. + pub(crate) ranges: Vec, pub(crate) action: lsp_ext::CodeAction, } @@ -43,7 +44,7 @@ impl DiagnosticCollection { &mut self, file_id: FileId, diagnostic: lsp_types::Diagnostic, - fix: Option, + fix: Option, ) { let diagnostics = self.check.entry(file_id).or_default(); for existing_diagnostic in diagnostics.iter() { @@ -53,10 +54,7 @@ impl DiagnosticCollection { } let check_fixes = Arc::make_mut(&mut self.check_fixes); - check_fixes - .entry(file_id) - .or_default() - .extend(fix.into_iter().map(|action| Fix { range: diagnostic.range, action })); + check_fixes.entry(file_id).or_default().extend(fix); diagnostics.push(diagnostic); self.changes.insert(file_id); } diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index 48af9c186d..51dbc1939b 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -9,7 +9,7 @@ use vfs::{AbsPath, AbsPathBuf}; use crate::{lsp_ext, to_proto::url_from_abs_path}; -use super::DiagnosticsMapConfig; +use super::{DiagnosticsMapConfig, Fix}; /// Determines the LSP severity from a diagnostic fn diagnostic_severity( @@ -114,7 +114,7 @@ fn resolve_path( struct SubDiagnostic { related: lsp_types::DiagnosticRelatedInformation, - suggested_fix: Option, + suggested_fix: Option, } enum MappedRustChildDiagnostic { @@ -171,18 +171,24 @@ fn map_rust_child_diagnostic( location: location(config, workspace_root, spans[0]), message: message.clone(), }, - suggested_fix: Some(lsp_ext::CodeAction { - title: message, - group: None, - kind: Some(lsp_types::CodeActionKind::QUICKFIX), - edit: Some(lsp_ext::SnippetWorkspaceEdit { - // FIXME: there's no good reason to use edit_map here.... - changes: Some(edit_map), - document_changes: None, - change_annotations: None, - }), - is_preferred: Some(true), - data: None, + suggested_fix: Some(Fix { + ranges: spans + .iter() + .map(|&span| location(config, workspace_root, span).range) + .collect(), + action: lsp_ext::CodeAction { + title: message, + group: None, + kind: Some(lsp_types::CodeActionKind::QUICKFIX), + edit: Some(lsp_ext::SnippetWorkspaceEdit { + // FIXME: there's no good reason to use edit_map here.... + changes: Some(edit_map), + document_changes: None, + change_annotations: None, + }), + is_preferred: Some(true), + data: None, + }, }), }) } @@ -192,7 +198,7 @@ fn map_rust_child_diagnostic( pub(crate) struct MappedRustDiagnostic { pub(crate) url: lsp_types::Url, pub(crate) diagnostic: lsp_types::Diagnostic, - pub(crate) fix: Option, + pub(crate) fix: Option, } /// Converts a Rust root diagnostic to LSP form diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index c3583df713..6bc2afc6fe 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1019,8 +1019,13 @@ pub(crate) fn handle_code_action( for fix in snap.check_fixes.get(&frange.file_id).into_iter().flatten() { // FIXME: this mapping is awkward and shouldn't exist. Refactor // `snap.check_fixes` to not convert to LSP prematurely. - let fix_range = from_proto::text_range(&line_index, fix.range); - if fix_range.intersect(frange.range).is_some() { + let intersect_fix_range = fix + .ranges + .iter() + .copied() + .map(|range| from_proto::text_range(&line_index, range)) + .any(|fix_range| fix_range.intersect(frange.range).is_some()); + if intersect_fix_range { res.push(fix.action.clone()); } } From fa2818551efcfe9f5269b2649a5f269749259509 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sat, 4 Dec 2021 21:26:07 -0800 Subject: [PATCH 3/3] Update expected test results --- .../test_data/clippy_pass_by_ref.txt | 114 +++++++------ .../test_data/handles_macro_location.txt | 2 +- .../test_data/macro_compiler_error.txt | 6 +- .../rustc_incompatible_type_for_trait.txt | 2 +- .../test_data/rustc_mismatched_type.txt | 2 +- .../test_data/rustc_unused_variable.txt | 112 +++++++------ .../rustc_unused_variable_as_hint.txt | 112 +++++++------ .../rustc_unused_variable_as_info.txt | 112 +++++++------ .../rustc_wrong_number_of_parameters.txt | 4 +- .../test_data/snap_multi_line_fix.txt | 150 ++++++++++-------- 10 files changed, 348 insertions(+), 268 deletions(-) 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 fd04163de9..4610984acb 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 @@ -114,7 +114,7 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -205,7 +205,7 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -296,55 +296,69 @@ tags: None, data: None, }, - fixes: [ - CodeAction { - title: "consider passing by value instead: `self`", - group: None, - kind: Some( - CodeActionKind( - "quickfix", - ), - ), - edit: Some( - SnippetWorkspaceEdit { - changes: Some( - { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/compiler/mir/tagset.rs", - query: None, - fragment: None, - }: [ - TextEdit { - range: Range { - start: Position { - line: 41, - character: 23, - }, - end: Position { - line: 41, - character: 28, - }, - }, - new_text: "self", - }, - ], - }, - ), - document_changes: None, - change_annotations: None, + fix: Some( + Fix { + ranges: [ + Range { + start: Position { + line: 41, + character: 23, + }, + end: Position { + line: 41, + character: 28, + }, }, - ), - is_preferred: Some( - true, - ), - data: None, + ], + action: CodeAction { + title: "consider passing by value instead: `self`", + group: None, + kind: Some( + CodeActionKind( + "quickfix", + ), + ), + edit: Some( + SnippetWorkspaceEdit { + changes: Some( + { + Url { + scheme: "file", + cannot_be_a_base: false, + username: "", + password: None, + host: None, + port: None, + path: "/test/compiler/mir/tagset.rs", + query: None, + fragment: None, + }: [ + TextEdit { + range: Range { + start: Position { + line: 41, + character: 23, + }, + end: Position { + line: 41, + character: 28, + }, + }, + new_text: "self", + }, + ], + }, + ), + document_changes: None, + change_annotations: None, + }, + ), + is_preferred: Some( + true, + ), + data: None, + }, }, - ], + ), }, ] 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 a7f936a703..989e5cf66d 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 @@ -59,6 +59,6 @@ tags: None, data: None, }, - fixes: [], + fix: 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 8bee4cfe10..fe5cf9b3be 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 @@ -64,7 +64,7 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -131,7 +131,7 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -224,6 +224,6 @@ tags: None, data: None, }, - fixes: [], + fix: 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 afc562a0e2..dc36aa761c 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 @@ -59,6 +59,6 @@ tags: None, data: None, }, - fixes: [], + fix: 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 05074a914b..d557196c2b 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 @@ -59,6 +59,6 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, ] 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 3ded70411d..46d44192c5 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 @@ -72,7 +72,7 @@ ), data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -143,55 +143,69 @@ tags: None, data: None, }, - fixes: [ - CodeAction { - title: "consider prefixing with an underscore: `_foo`", - group: None, - kind: Some( - CodeActionKind( - "quickfix", - ), - ), - edit: Some( - SnippetWorkspaceEdit { - changes: Some( - { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }: [ - TextEdit { - range: Range { - start: Position { - line: 290, - character: 8, - }, - end: Position { - line: 290, - character: 11, - }, - }, - new_text: "_foo", - }, - ], - }, - ), - document_changes: None, - change_annotations: None, + fix: Some( + Fix { + ranges: [ + Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, }, - ), - is_preferred: Some( - true, - ), - data: None, + ], + action: CodeAction { + title: "consider prefixing with an underscore: `_foo`", + group: None, + kind: Some( + CodeActionKind( + "quickfix", + ), + ), + edit: Some( + SnippetWorkspaceEdit { + changes: Some( + { + Url { + scheme: "file", + cannot_be_a_base: false, + username: "", + password: None, + host: None, + port: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }: [ + TextEdit { + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + new_text: "_foo", + }, + ], + }, + ), + document_changes: None, + change_annotations: None, + }, + ), + is_preferred: Some( + true, + ), + data: None, + }, }, - ], + ), }, ] 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 0993aa1af1..b595487e8f 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 @@ -72,7 +72,7 @@ ), data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -143,55 +143,69 @@ tags: None, data: None, }, - fixes: [ - CodeAction { - title: "consider prefixing with an underscore: `_foo`", - group: None, - kind: Some( - CodeActionKind( - "quickfix", - ), - ), - edit: Some( - SnippetWorkspaceEdit { - changes: Some( - { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }: [ - TextEdit { - range: Range { - start: Position { - line: 290, - character: 8, - }, - end: Position { - line: 290, - character: 11, - }, - }, - new_text: "_foo", - }, - ], - }, - ), - document_changes: None, - change_annotations: None, + fix: Some( + Fix { + ranges: [ + Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, }, - ), - is_preferred: Some( - true, - ), - data: None, + ], + action: CodeAction { + title: "consider prefixing with an underscore: `_foo`", + group: None, + kind: Some( + CodeActionKind( + "quickfix", + ), + ), + edit: Some( + SnippetWorkspaceEdit { + changes: Some( + { + Url { + scheme: "file", + cannot_be_a_base: false, + username: "", + password: None, + host: None, + port: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }: [ + TextEdit { + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + new_text: "_foo", + }, + ], + }, + ), + document_changes: None, + change_annotations: None, + }, + ), + is_preferred: Some( + true, + ), + data: None, + }, }, - ], + ), }, ] 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 d7a974ae57..3ee50392a7 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 @@ -72,7 +72,7 @@ ), data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -143,55 +143,69 @@ tags: None, data: None, }, - fixes: [ - CodeAction { - title: "consider prefixing with an underscore: `_foo`", - group: None, - kind: Some( - CodeActionKind( - "quickfix", - ), - ), - edit: Some( - SnippetWorkspaceEdit { - changes: Some( - { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/driver/subcommand/repl.rs", - query: None, - fragment: None, - }: [ - TextEdit { - range: Range { - start: Position { - line: 290, - character: 8, - }, - end: Position { - line: 290, - character: 11, - }, - }, - new_text: "_foo", - }, - ], - }, - ), - document_changes: None, - change_annotations: None, + fix: Some( + Fix { + ranges: [ + Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, }, - ), - is_preferred: Some( - true, - ), - data: None, + ], + action: CodeAction { + title: "consider prefixing with an underscore: `_foo`", + group: None, + kind: Some( + CodeActionKind( + "quickfix", + ), + ), + edit: Some( + SnippetWorkspaceEdit { + changes: Some( + { + Url { + scheme: "file", + cannot_be_a_base: false, + username: "", + password: None, + host: None, + port: None, + path: "/test/driver/subcommand/repl.rs", + query: None, + fragment: None, + }: [ + TextEdit { + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + new_text: "_foo", + }, + ], + }, + ), + document_changes: None, + change_annotations: None, + }, + ), + is_preferred: Some( + true, + ), + data: None, + }, }, - ], + ), }, ] 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 5ea27a1527..8ec92888ce 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 @@ -88,7 +88,7 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -179,6 +179,6 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, ] 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 f77abde515..d7987f65ed 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 @@ -114,7 +114,7 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -205,7 +205,7 @@ tags: None, data: None, }, - fixes: [], + fix: None, }, MappedRustDiagnostic { url: Url { @@ -296,68 +296,92 @@ tags: None, data: None, }, - fixes: [ - CodeAction { - title: "return the expression directly: `(0..10).collect()`", - group: None, - kind: Some( - CodeActionKind( - "quickfix", - ), - ), - edit: Some( - SnippetWorkspaceEdit { - changes: Some( - { - Url { - scheme: "file", - cannot_be_a_base: false, - username: "", - password: None, - host: None, - port: None, - path: "/test/src/main.rs", - query: None, - fragment: None, - }: [ - TextEdit { - range: Range { - start: Position { - line: 2, - character: 4, - }, - end: Position { - line: 2, - character: 30, - }, - }, - new_text: "", - }, - TextEdit { - range: Range { - start: Position { - line: 3, - character: 4, - }, - end: Position { - line: 3, - character: 5, - }, - }, - new_text: "(0..10).collect()", - }, - ], - }, - ), - document_changes: None, - change_annotations: None, + fix: Some( + Fix { + ranges: [ + Range { + start: Position { + line: 2, + character: 4, + }, + end: Position { + line: 2, + character: 30, + }, }, - ), - is_preferred: Some( - true, - ), - data: None, + Range { + start: Position { + line: 3, + character: 4, + }, + end: Position { + line: 3, + character: 5, + }, + }, + ], + action: CodeAction { + title: "return the expression directly: `(0..10).collect()`", + group: None, + kind: Some( + CodeActionKind( + "quickfix", + ), + ), + edit: Some( + SnippetWorkspaceEdit { + changes: Some( + { + Url { + scheme: "file", + cannot_be_a_base: false, + username: "", + password: None, + host: None, + port: None, + path: "/test/src/main.rs", + query: None, + fragment: None, + }: [ + TextEdit { + range: Range { + start: Position { + line: 2, + character: 4, + }, + end: Position { + line: 2, + character: 30, + }, + }, + new_text: "", + }, + TextEdit { + range: Range { + start: Position { + line: 3, + character: 4, + }, + end: Position { + line: 3, + character: 5, + }, + }, + new_text: "(0..10).collect()", + }, + ], + }, + ), + document_changes: None, + change_annotations: None, + }, + ), + is_preferred: Some( + true, + ), + data: None, + }, }, - ], + ), }, ]