diff options
-rw-r--r-- | crates/ra_ide/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/ssr.rs | 6 | ||||
-rw-r--r-- | crates/ra_ssr/src/lib.rs | 30 | ||||
-rw-r--r-- | crates/ra_ssr/src/matching.rs | 4 | ||||
-rw-r--r-- | crates/ra_ssr/src/tests.rs | 42 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/ssr.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 5 | ||||
-rw-r--r-- | docs/dev/lsp-extensions.md | 7 | ||||
-rw-r--r-- | editors/code/src/commands.ts | 14 | ||||
-rw-r--r-- | editors/code/src/lsp_ext.ts | 2 |
11 files changed, 88 insertions, 32 deletions
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index dc9192d42..7356e947b 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -505,9 +505,10 @@ impl Analysis { | |||
505 | &self, | 505 | &self, |
506 | query: &str, | 506 | query: &str, |
507 | parse_only: bool, | 507 | parse_only: bool, |
508 | position: FilePosition, | ||
508 | ) -> Cancelable<Result<SourceChange, SsrError>> { | 509 | ) -> Cancelable<Result<SourceChange, SsrError>> { |
509 | self.with_db(|db| { | 510 | self.with_db(|db| { |
510 | let edits = ssr::parse_search_replace(query, parse_only, db)?; | 511 | let edits = ssr::parse_search_replace(query, parse_only, db, position)?; |
511 | Ok(SourceChange::from(edits)) | 512 | Ok(SourceChange::from(edits)) |
512 | }) | 513 | }) |
513 | } | 514 | } |
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs index ca7e0ad86..3e2705d62 100644 --- a/crates/ra_ide/src/ssr.rs +++ b/crates/ra_ide/src/ssr.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | use ra_db::FilePosition; | ||
1 | use ra_ide_db::RootDatabase; | 2 | use ra_ide_db::RootDatabase; |
2 | 3 | ||
3 | use crate::SourceFileEdit; | 4 | use crate::SourceFileEdit; |
@@ -42,12 +43,13 @@ pub fn parse_search_replace( | |||
42 | rule: &str, | 43 | rule: &str, |
43 | parse_only: bool, | 44 | parse_only: bool, |
44 | db: &RootDatabase, | 45 | db: &RootDatabase, |
46 | position: FilePosition, | ||
45 | ) -> Result<Vec<SourceFileEdit>, SsrError> { | 47 | ) -> Result<Vec<SourceFileEdit>, SsrError> { |
46 | let rule: SsrRule = rule.parse()?; | 48 | let rule: SsrRule = rule.parse()?; |
49 | let mut match_finder = MatchFinder::in_context(db, position); | ||
50 | match_finder.add_rule(rule); | ||
47 | if parse_only { | 51 | if parse_only { |
48 | return Ok(Vec::new()); | 52 | return Ok(Vec::new()); |
49 | } | 53 | } |
50 | let mut match_finder = MatchFinder::new(db); | ||
51 | match_finder.add_rule(rule); | ||
52 | Ok(match_finder.edits()) | 54 | Ok(match_finder.edits()) |
53 | } | 55 | } |
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ra_ssr/src/lib.rs index 6d578610b..a0a5c9762 100644 --- a/crates/ra_ssr/src/lib.rs +++ b/crates/ra_ssr/src/lib.rs | |||
@@ -13,11 +13,12 @@ mod errors; | |||
13 | #[cfg(test)] | 13 | #[cfg(test)] |
14 | mod tests; | 14 | mod tests; |
15 | 15 | ||
16 | use crate::errors::bail; | ||
16 | pub use crate::errors::SsrError; | 17 | pub use crate::errors::SsrError; |
17 | pub use crate::matching::Match; | 18 | pub use crate::matching::Match; |
18 | use crate::matching::MatchFailureReason; | 19 | use crate::matching::MatchFailureReason; |
19 | use hir::Semantics; | 20 | use hir::Semantics; |
20 | use ra_db::{FileId, FileRange}; | 21 | use ra_db::{FileId, FilePosition, FileRange}; |
21 | use ra_ide_db::source_change::SourceFileEdit; | 22 | use ra_ide_db::source_change::SourceFileEdit; |
22 | use ra_syntax::{ast, AstNode, SyntaxNode, TextRange}; | 23 | use ra_syntax::{ast, AstNode, SyntaxNode, TextRange}; |
23 | use rustc_hash::FxHashMap; | 24 | use rustc_hash::FxHashMap; |
@@ -51,10 +52,35 @@ pub struct MatchFinder<'db> { | |||
51 | } | 52 | } |
52 | 53 | ||
53 | impl<'db> MatchFinder<'db> { | 54 | impl<'db> MatchFinder<'db> { |
54 | pub fn new(db: &'db ra_ide_db::RootDatabase) -> MatchFinder<'db> { | 55 | /// Constructs a new instance where names will be looked up as if they appeared at |
56 | /// `lookup_context`. | ||
57 | pub fn in_context( | ||
58 | db: &'db ra_ide_db::RootDatabase, | ||
59 | _lookup_context: FilePosition, | ||
60 | ) -> MatchFinder<'db> { | ||
61 | // FIXME: Use lookup_context | ||
55 | MatchFinder { sema: Semantics::new(db), rules: Vec::new() } | 62 | MatchFinder { sema: Semantics::new(db), rules: Vec::new() } |
56 | } | 63 | } |
57 | 64 | ||
65 | /// Constructs an instance using the start of the first file in `db` as the lookup context. | ||
66 | pub fn at_first_file(db: &'db ra_ide_db::RootDatabase) -> Result<MatchFinder<'db>, SsrError> { | ||
67 | use ra_db::SourceDatabaseExt; | ||
68 | use ra_ide_db::symbol_index::SymbolsDatabase; | ||
69 | if let Some(first_file_id) = db | ||
70 | .local_roots() | ||
71 | .iter() | ||
72 | .next() | ||
73 | .and_then(|root| db.source_root(root.clone()).iter().next()) | ||
74 | { | ||
75 | Ok(MatchFinder::in_context( | ||
76 | db, | ||
77 | FilePosition { file_id: first_file_id, offset: 0.into() }, | ||
78 | )) | ||
79 | } else { | ||
80 | bail!("No files to search"); | ||
81 | } | ||
82 | } | ||
83 | |||
58 | /// Adds a rule to be applied. The order in which rules are added matters. Earlier rules take | 84 | /// Adds a rule to be applied. The order in which rules are added matters. Earlier rules take |
59 | /// precedence. If a node is matched by an earlier rule, then later rules won't be permitted to | 85 | /// precedence. If a node is matched by an earlier rule, then later rules won't be permitted to |
60 | /// match to it. | 86 | /// match to it. |
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ra_ssr/src/matching.rs index 005569f6f..a43d57c34 100644 --- a/crates/ra_ssr/src/matching.rs +++ b/crates/ra_ssr/src/matching.rs | |||
@@ -576,8 +576,8 @@ mod tests { | |||
576 | let rule: SsrRule = "foo($x) ==>> bar($x)".parse().unwrap(); | 576 | let rule: SsrRule = "foo($x) ==>> bar($x)".parse().unwrap(); |
577 | let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }"; | 577 | let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }"; |
578 | 578 | ||
579 | let (db, _) = crate::tests::single_file(input); | 579 | let (db, position) = crate::tests::single_file(input); |
580 | let mut match_finder = MatchFinder::new(&db); | 580 | let mut match_finder = MatchFinder::in_context(&db, position); |
581 | match_finder.add_rule(rule); | 581 | match_finder.add_rule(rule); |
582 | let matches = match_finder.matches(); | 582 | let matches = match_finder.matches(); |
583 | assert_eq!(matches.matches.len(), 1); | 583 | assert_eq!(matches.matches.len(), 1); |
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs index 523035b31..63d527894 100644 --- a/crates/ra_ssr/src/tests.rs +++ b/crates/ra_ssr/src/tests.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use crate::{MatchFinder, SsrRule}; | 1 | use crate::{MatchFinder, SsrRule}; |
2 | use expect::{expect, Expect}; | 2 | use expect::{expect, Expect}; |
3 | use ra_db::{salsa::Durability, FileId, SourceDatabaseExt}; | 3 | use ra_db::{salsa::Durability, FileId, FilePosition, SourceDatabaseExt}; |
4 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | use test_utils::mark; | 6 | use test_utils::mark; |
@@ -59,15 +59,21 @@ fn parser_undefined_placeholder_in_replacement() { | |||
59 | ); | 59 | ); |
60 | } | 60 | } |
61 | 61 | ||
62 | pub(crate) fn single_file(code: &str) -> (ra_ide_db::RootDatabase, FileId) { | 62 | /// `code` may optionally contain a cursor marker `<|>`. If it doesn't, then the position will be |
63 | /// the start of the file. | ||
64 | pub(crate) fn single_file(code: &str) -> (ra_ide_db::RootDatabase, FilePosition) { | ||
63 | use ra_db::fixture::WithFixture; | 65 | use ra_db::fixture::WithFixture; |
64 | use ra_ide_db::symbol_index::SymbolsDatabase; | 66 | use ra_ide_db::symbol_index::SymbolsDatabase; |
65 | let (db, file_id) = ra_ide_db::RootDatabase::with_single_file(code); | 67 | let (mut db, position) = if code.contains(test_utils::CURSOR_MARKER) { |
66 | let mut db = db; | 68 | ra_ide_db::RootDatabase::with_position(code) |
69 | } else { | ||
70 | let (db, file_id) = ra_ide_db::RootDatabase::with_single_file(code); | ||
71 | (db, FilePosition { file_id, offset: 0.into() }) | ||
72 | }; | ||
67 | let mut local_roots = FxHashSet::default(); | 73 | let mut local_roots = FxHashSet::default(); |
68 | local_roots.insert(ra_db::fixture::WORKSPACE); | 74 | local_roots.insert(ra_db::fixture::WORKSPACE); |
69 | db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); | 75 | db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); |
70 | (db, file_id) | 76 | (db, position) |
71 | } | 77 | } |
72 | 78 | ||
73 | fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) { | 79 | fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) { |
@@ -75,8 +81,8 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) { | |||
75 | } | 81 | } |
76 | 82 | ||
77 | fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { | 83 | fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { |
78 | let (db, file_id) = single_file(input); | 84 | let (db, position) = single_file(input); |
79 | let mut match_finder = MatchFinder::new(&db); | 85 | let mut match_finder = MatchFinder::in_context(&db, position); |
80 | for rule in rules { | 86 | for rule in rules { |
81 | let rule: SsrRule = rule.parse().unwrap(); | 87 | let rule: SsrRule = rule.parse().unwrap(); |
82 | match_finder.add_rule(rule); | 88 | match_finder.add_rule(rule); |
@@ -85,10 +91,10 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { | |||
85 | if edits.is_empty() { | 91 | if edits.is_empty() { |
86 | panic!("No edits were made"); | 92 | panic!("No edits were made"); |
87 | } | 93 | } |
88 | assert_eq!(edits[0].file_id, file_id); | 94 | assert_eq!(edits[0].file_id, position.file_id); |
89 | // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters | 95 | // Note, db.file_text is not necessarily the same as `input`, since fixture parsing alters |
90 | // stuff. | 96 | // stuff. |
91 | let mut actual = db.file_text(file_id).to_string(); | 97 | let mut actual = db.file_text(position.file_id).to_string(); |
92 | edits[0].edit.apply(&mut actual); | 98 | edits[0].edit.apply(&mut actual); |
93 | expected.assert_eq(&actual); | 99 | expected.assert_eq(&actual); |
94 | } | 100 | } |
@@ -106,34 +112,34 @@ fn print_match_debug_info(match_finder: &MatchFinder, file_id: FileId, snippet: | |||
106 | } | 112 | } |
107 | 113 | ||
108 | fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { | 114 | fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { |
109 | let (db, file_id) = single_file(code); | 115 | let (db, position) = single_file(code); |
110 | let mut match_finder = MatchFinder::new(&db); | 116 | let mut match_finder = MatchFinder::in_context(&db, position); |
111 | match_finder.add_search_pattern(pattern.parse().unwrap()); | 117 | match_finder.add_search_pattern(pattern.parse().unwrap()); |
112 | let matched_strings: Vec<String> = | 118 | let matched_strings: Vec<String> = |
113 | match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); | 119 | match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); |
114 | if matched_strings != expected && !expected.is_empty() { | 120 | if matched_strings != expected && !expected.is_empty() { |
115 | print_match_debug_info(&match_finder, file_id, &expected[0]); | 121 | print_match_debug_info(&match_finder, position.file_id, &expected[0]); |
116 | } | 122 | } |
117 | assert_eq!(matched_strings, expected); | 123 | assert_eq!(matched_strings, expected); |
118 | } | 124 | } |
119 | 125 | ||
120 | fn assert_no_match(pattern: &str, code: &str) { | 126 | fn assert_no_match(pattern: &str, code: &str) { |
121 | let (db, file_id) = single_file(code); | 127 | let (db, position) = single_file(code); |
122 | let mut match_finder = MatchFinder::new(&db); | 128 | let mut match_finder = MatchFinder::in_context(&db, position); |
123 | match_finder.add_search_pattern(pattern.parse().unwrap()); | 129 | match_finder.add_search_pattern(pattern.parse().unwrap()); |
124 | let matches = match_finder.matches().flattened().matches; | 130 | let matches = match_finder.matches().flattened().matches; |
125 | if !matches.is_empty() { | 131 | if !matches.is_empty() { |
126 | print_match_debug_info(&match_finder, file_id, &matches[0].matched_text()); | 132 | print_match_debug_info(&match_finder, position.file_id, &matches[0].matched_text()); |
127 | panic!("Got {} matches when we expected none: {:#?}", matches.len(), matches); | 133 | panic!("Got {} matches when we expected none: {:#?}", matches.len(), matches); |
128 | } | 134 | } |
129 | } | 135 | } |
130 | 136 | ||
131 | fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) { | 137 | fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) { |
132 | let (db, file_id) = single_file(code); | 138 | let (db, position) = single_file(code); |
133 | let mut match_finder = MatchFinder::new(&db); | 139 | let mut match_finder = MatchFinder::in_context(&db, position); |
134 | match_finder.add_search_pattern(pattern.parse().unwrap()); | 140 | match_finder.add_search_pattern(pattern.parse().unwrap()); |
135 | let mut reasons = Vec::new(); | 141 | let mut reasons = Vec::new(); |
136 | for d in match_finder.debug_where_text_equal(file_id, snippet) { | 142 | for d in match_finder.debug_where_text_equal(position.file_id, snippet) { |
137 | if let Some(reason) = d.match_failure_reason() { | 143 | if let Some(reason) = d.match_failure_reason() { |
138 | reasons.push(reason.to_owned()); | 144 | reasons.push(reason.to_owned()); |
139 | } | 145 | } |
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs index 014bc70a4..22f5b4be0 100644 --- a/crates/rust-analyzer/src/cli/ssr.rs +++ b/crates/rust-analyzer/src/cli/ssr.rs | |||
@@ -7,7 +7,7 @@ pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { | |||
7 | use ra_db::SourceDatabaseExt; | 7 | use ra_db::SourceDatabaseExt; |
8 | let (host, vfs) = load_cargo(&std::env::current_dir()?, true, true)?; | 8 | let (host, vfs) = load_cargo(&std::env::current_dir()?, true, true)?; |
9 | let db = host.raw_database(); | 9 | let db = host.raw_database(); |
10 | let mut match_finder = MatchFinder::new(db); | 10 | let mut match_finder = MatchFinder::at_first_file(db)?; |
11 | for rule in rules { | 11 | for rule in rules { |
12 | match_finder.add_rule(rule); | 12 | match_finder.add_rule(rule); |
13 | } | 13 | } |
@@ -30,7 +30,7 @@ pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<Stri | |||
30 | use ra_ide_db::symbol_index::SymbolsDatabase; | 30 | use ra_ide_db::symbol_index::SymbolsDatabase; |
31 | let (host, _vfs) = load_cargo(&std::env::current_dir()?, true, true)?; | 31 | let (host, _vfs) = load_cargo(&std::env::current_dir()?, true, true)?; |
32 | let db = host.raw_database(); | 32 | let db = host.raw_database(); |
33 | let mut match_finder = MatchFinder::new(db); | 33 | let mut match_finder = MatchFinder::at_first_file(db)?; |
34 | for pattern in patterns { | 34 | for pattern in patterns { |
35 | match_finder.add_search_pattern(pattern); | 35 | match_finder.add_search_pattern(pattern); |
36 | } | 36 | } |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 8d8c9442b..cad92c444 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -1026,8 +1026,9 @@ pub(crate) fn handle_ssr( | |||
1026 | params: lsp_ext::SsrParams, | 1026 | params: lsp_ext::SsrParams, |
1027 | ) -> Result<lsp_types::WorkspaceEdit> { | 1027 | ) -> Result<lsp_types::WorkspaceEdit> { |
1028 | let _p = profile("handle_ssr"); | 1028 | let _p = profile("handle_ssr"); |
1029 | let position = from_proto::file_position(&snap, params.position)?; | ||
1029 | let source_change = | 1030 | let source_change = |
1030 | snap.analysis.structural_search_replace(¶ms.query, params.parse_only)??; | 1031 | snap.analysis.structural_search_replace(¶ms.query, params.parse_only, position)??; |
1031 | to_proto::workspace_edit(&snap, source_change) | 1032 | to_proto::workspace_edit(&snap, source_change) |
1032 | } | 1033 | } |
1033 | 1034 | ||
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 13ebb18fb..113e0e070 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -216,6 +216,11 @@ impl Request for Ssr { | |||
216 | pub struct SsrParams { | 216 | pub struct SsrParams { |
217 | pub query: String, | 217 | pub query: String, |
218 | pub parse_only: bool, | 218 | pub parse_only: bool, |
219 | |||
220 | /// File position where SSR was invoked. Paths in `query` will be resolved relative to this | ||
221 | /// position. | ||
222 | #[serde(flatten)] | ||
223 | pub position: lsp_types::TextDocumentPositionParams, | ||
219 | } | 224 | } |
220 | 225 | ||
221 | pub enum StatusNotification {} | 226 | pub enum StatusNotification {} |
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 98d14450b..1be01fd88 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md | |||
@@ -274,6 +274,11 @@ interface SsrParams { | |||
274 | query: string, | 274 | query: string, |
275 | /// If true, only check the syntax of the query and don't compute the actual edit. | 275 | /// If true, only check the syntax of the query and don't compute the actual edit. |
276 | parseOnly: bool, | 276 | parseOnly: bool, |
277 | /// The current text document. This and `position` will be used to determine in what scope | ||
278 | /// paths in `query` should be resolved. | ||
279 | textDocument: lc.TextDocumentIdentifier; | ||
280 | /// Position where SSR was invoked. | ||
281 | position: lc.Position; | ||
277 | } | 282 | } |
278 | ``` | 283 | ``` |
279 | 284 | ||
@@ -285,7 +290,7 @@ WorkspaceEdit | |||
285 | 290 | ||
286 | ### Example | 291 | ### Example |
287 | 292 | ||
288 | SSR with query `foo($a:expr, $b:expr) ==>> ($a).foo($b)` will transform, eg `foo(y + 5, z)` into `(y + 5).foo(z)`. | 293 | SSR with query `foo($a, $b) ==>> ($a).foo($b)` will transform, eg `foo(y + 5, z)` into `(y + 5).foo(z)`. |
289 | 294 | ||
290 | ### Unresolved Question | 295 | ### Unresolved Question |
291 | 296 | ||
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 1f3a7cf7e..3ae995705 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -185,15 +185,21 @@ export function parentModule(ctx: Ctx): Cmd { | |||
185 | 185 | ||
186 | export function ssr(ctx: Ctx): Cmd { | 186 | export function ssr(ctx: Ctx): Cmd { |
187 | return async () => { | 187 | return async () => { |
188 | const editor = vscode.window.activeTextEditor; | ||
188 | const client = ctx.client; | 189 | const client = ctx.client; |
189 | if (!client) return; | 190 | if (!editor || !client) return; |
191 | |||
192 | const position = editor.selection.active; | ||
193 | let textDocument = { uri: editor.document.uri.toString() }; | ||
190 | 194 | ||
191 | const options: vscode.InputBoxOptions = { | 195 | const options: vscode.InputBoxOptions = { |
192 | value: "() ==>> ()", | 196 | value: "() ==>> ()", |
193 | prompt: "Enter request, for example 'Foo($a) ==> Foo::new($a)' ", | 197 | prompt: "Enter request, for example 'Foo($a) ==> Foo::new($a)' ", |
194 | validateInput: async (x: string) => { | 198 | validateInput: async (x: string) => { |
195 | try { | 199 | try { |
196 | await client.sendRequest(ra.ssr, { query: x, parseOnly: true }); | 200 | await client.sendRequest(ra.ssr, { |
201 | query: x, parseOnly: true, textDocument, position, | ||
202 | }); | ||
197 | } catch (e) { | 203 | } catch (e) { |
198 | return e.toString(); | 204 | return e.toString(); |
199 | } | 205 | } |
@@ -208,7 +214,9 @@ export function ssr(ctx: Ctx): Cmd { | |||
208 | title: "Structured search replace in progress...", | 214 | title: "Structured search replace in progress...", |
209 | cancellable: false, | 215 | cancellable: false, |
210 | }, async (_progress, _token) => { | 216 | }, async (_progress, _token) => { |
211 | const edit = await client.sendRequest(ra.ssr, { query: request, parseOnly: false }); | 217 | const edit = await client.sendRequest(ra.ssr, { |
218 | query: request, parseOnly: false, textDocument, position | ||
219 | }); | ||
212 | 220 | ||
213 | await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit)); | 221 | await vscode.workspace.applyEdit(client.protocol2CodeConverter.asWorkspaceEdit(edit)); |
214 | }); | 222 | }); |
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index 5f32cb40e..149f9a0d6 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts | |||
@@ -93,6 +93,8 @@ export const inlayHints = new lc.RequestType<InlayHintsParams, InlayHint[], void | |||
93 | export interface SsrParams { | 93 | export interface SsrParams { |
94 | query: string; | 94 | query: string; |
95 | parseOnly: boolean; | 95 | parseOnly: boolean; |
96 | textDocument: lc.TextDocumentIdentifier; | ||
97 | position: lc.Position; | ||
96 | } | 98 | } |
97 | export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('experimental/ssr'); | 99 | export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('experimental/ssr'); |
98 | 100 | ||