From 4b495da368162a5b373d078be4ff51e55bffdf69 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 21 May 2020 14:26:44 +0200 Subject: Transition OnEnter to WorkspaceSnippetEdit This also changes our handiling of snippet edits on the client side. `editor.insertSnippet` unfortunately forces indentation, which we really don't want to have to deal with. So, let's just implement our manual hacky way of dealing with a simple subset of snippets we actually use in rust-analyzer --- crates/ra_ide/src/typing/on_enter.rs | 29 +++++----- crates/rust-analyzer/src/lsp_ext.rs | 2 +- crates/rust-analyzer/src/main_loop/handlers.rs | 4 +- crates/rust-analyzer/tests/heavy_tests/main.rs | 68 ++++++++++------------- editors/code/src/commands/index.ts | 75 ++++++++++++++++---------- editors/code/src/commands/on_enter.ts | 5 +- editors/code/src/main.ts | 2 +- editors/code/src/rust-analyzer-api.ts | 2 +- 8 files changed, 97 insertions(+), 90 deletions(-) diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs index 78a40cc94..85be14ad3 100644 --- a/crates/ra_ide/src/typing/on_enter.rs +++ b/crates/ra_ide/src/typing/on_enter.rs @@ -38,17 +38,15 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option bool { @@ -84,7 +82,7 @@ fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option { #[cfg(test)] mod tests { - use test_utils::{add_cursor, assert_eq_text, extract_offset}; + use test_utils::{assert_eq_text, extract_offset}; use crate::mock_analysis::single_file; @@ -98,7 +96,6 @@ mod tests { assert_eq!(result.source_file_edits.len(), 1); let mut actual = before.to_string(); result.source_file_edits[0].edit.apply(&mut actual); - let actual = add_cursor(&actual, result.cursor_position.unwrap().offset); Some(actual) } @@ -121,7 +118,7 @@ fn foo() { ", r" /// Some docs -/// <|> +/// $0 fn foo() { } ", @@ -137,7 +134,7 @@ impl S { r" impl S { /// Some - /// <|> docs. + /// $0 docs. fn foo() {} } ", @@ -151,7 +148,7 @@ fn foo() { ", r" /// -/// <|> Some docs +/// $0 Some docs fn foo() { } ", @@ -175,7 +172,7 @@ fn main() { r" fn main() { // Fix - // <|> me + // $0 me let x = 1 + 1; } ", @@ -195,7 +192,7 @@ fn main() { r" fn main() { // Fix - // <|> + // $0 // me let x = 1 + 1; } diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index f75a26eb7..3c7bd609d 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs @@ -102,7 +102,7 @@ pub enum OnEnter {} impl Request for OnEnter { type Params = lsp_types::TextDocumentPositionParams; - type Result = Option; + type Result = Option; const METHOD: &'static str = "rust-analyzer/onEnter"; } diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index be6a0aece..fcf08cd79 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs @@ -159,12 +159,12 @@ pub fn handle_join_lines( pub fn handle_on_enter( world: WorldSnapshot, params: lsp_types::TextDocumentPositionParams, -) -> Result> { +) -> Result> { let _p = profile("handle_on_enter"); let position = from_proto::file_position(&world, params)?; match world.analysis().on_enter(position)? { None => Ok(None), - Some(source_change) => to_proto::source_change(&world, source_change).map(Some), + Some(source_change) => to_proto::snippet_workspace_edit(&world, source_change).map(Some), } } diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index 74676b3ee..4e94c37e1 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs @@ -474,27 +474,21 @@ fn main() {{}} position: Position { line: 0, character: 5 }, }, json!({ - "cursorPosition": { - "position": { "character": 4, "line": 1 }, - "textDocument": { "uri": "file:///[..]src/m0.rs" } - }, - "label": "On enter", - "workspaceEdit": { - "documentChanges": [ - { - "edits": [ - { - "newText": "\n/// ", - "range": { - "end": { "character": 5, "line": 0 }, - "start": { "character": 5, "line": 0 } - } + "documentChanges": [ + { + "edits": [ + { + "insertTextFormat": 2, + "newText": "\n/// $0", + "range": { + "end": { "character": 5, "line": 0 }, + "start": { "character": 5, "line": 0 } } - ], - "textDocument": { "uri": "file:///[..]src/m0.rs", "version": null } - } - ] - } + } + ], + "textDocument": { "uri": "file:///[..]src/m0.rs", "version": null } + } + ] }), ); let elapsed = start.elapsed(); @@ -526,27 +520,21 @@ version = \"0.0.0\" position: Position { line: 0, character: 8 }, }, json!({ - "cursorPosition": { - "position": { "line": 1, "character": 4 }, - "textDocument": { "uri": "file:///[..]src/main.rs" } - }, - "label": "On enter", - "workspaceEdit": { - "documentChanges": [ - { - "edits": [ - { - "newText": "\r\n/// ", - "range": { - "end": { "line": 0, "character": 8 }, - "start": { "line": 0, "character": 8 } - } + "documentChanges": [ + { + "edits": [ + { + "insertTextFormat": 2, + "newText": "\r\n/// $0", + "range": { + "end": { "line": 0, "character": 8 }, + "start": { "line": 0, "character": 8 } } - ], - "textDocument": { "uri": "file:///[..]src/main.rs", "version": null } - } - ] - } + } + ], + "textDocument": { "uri": "file:///[..]src/main.rs", "version": null } + } + ] }), ); } diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index 0937b495c..e5ed77e32 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts @@ -53,36 +53,57 @@ export function selectAndApplySourceChange(ctx: Ctx): Cmd { }; } -export function applySnippetWorkspaceEdit(_ctx: Ctx): Cmd { +export function applySnippetWorkspaceEditCommand(_ctx: Ctx): Cmd { return async (edit: vscode.WorkspaceEdit) => { - assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`); - const [uri, edits] = edit.entries()[0]; + await applySnippetWorkspaceEdit(edit); + }; +} + +export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) { + assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`); + const [uri, edits] = edit.entries()[0]; - const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString()); - if (!editor) return; + const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString()); + if (!editor) return; - let editWithSnippet: vscode.TextEdit | undefined = undefined; - let lineDelta = 0; - await editor.edit((builder) => { - for (const indel of edits) { - const isSnippet = indel.newText.indexOf('$0') !== -1 || indel.newText.indexOf('${') !== -1; - if (isSnippet) { - editWithSnippet = indel; - } else { - if (!editWithSnippet) { - lineDelta = (indel.newText.match(/\n/g) || []).length - (indel.range.end.line - indel.range.start.line); - } - builder.replace(indel.range, indel.newText); - } + let selection: vscode.Selection | undefined = undefined; + let lineDelta = 0; + await editor.edit((builder) => { + for (const indel of edits) { + const parsed = parseSnippet(indel.newText); + if (parsed) { + const [newText, [placeholderStart, placeholderLength]] = parsed; + const prefix = newText.substr(0, placeholderStart); + const lastNewline = prefix.lastIndexOf('\n'); + + const startLine = indel.range.start.line + lineDelta + countLines(prefix); + const startColumn = lastNewline === -1 ? + indel.range.start.character + placeholderStart + : prefix.length - lastNewline - 1; + const endColumn = startColumn + placeholderLength; + selection = new vscode.Selection( + new vscode.Position(startLine, startColumn), + new vscode.Position(startLine, endColumn), + ); + builder.replace(indel.range, newText); + } else { + lineDelta = countLines(indel.newText) - (indel.range.end.line - indel.range.start.line); + builder.replace(indel.range, indel.newText); } - }); - if (editWithSnippet) { - const snip = editWithSnippet as vscode.TextEdit; - const range = snip.range.with( - snip.range.start.with(snip.range.start.line + lineDelta), - snip.range.end.with(snip.range.end.line + lineDelta), - ); - await editor.insertSnippet(new vscode.SnippetString(snip.newText), range); } - }; + }); + if (selection) editor.selection = selection; +} + +function parseSnippet(snip: string): [string, [number, number]] | undefined { + const m = snip.match(/\$(0|\{0:([^}]*)\})/); + if (!m) return undefined; + const placeholder = m[2] ?? ""; + const range: [number, number] = [m.index!!, placeholder.length]; + const insert = snip.replace(m[0], placeholder); + return [insert, range]; +} + +function countLines(text: string): number { + return (text.match(/\n/g) || []).length; } diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts index 285849db7..a7871c31e 100644 --- a/editors/code/src/commands/on_enter.ts +++ b/editors/code/src/commands/on_enter.ts @@ -1,8 +1,8 @@ import * as vscode from 'vscode'; import * as ra from '../rust-analyzer-api'; -import { applySourceChange } from '../source_change'; import { Cmd, Ctx } from '../ctx'; +import { applySnippetWorkspaceEdit } from '.'; async function handleKeypress(ctx: Ctx) { const editor = ctx.activeRustEditor; @@ -21,7 +21,8 @@ async function handleKeypress(ctx: Ctx) { }); if (!change) return false; - await applySourceChange(ctx, change); + const workspaceEdit = client.protocol2CodeConverter.asWorkspaceEdit(change); + await applySnippetWorkspaceEdit(workspaceEdit); return true; } diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index ac3bb365e..8b0a9d870 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -91,7 +91,7 @@ export async function activate(context: vscode.ExtensionContext) { ctx.registerCommand('debugSingle', commands.debugSingle); ctx.registerCommand('showReferences', commands.showReferences); ctx.registerCommand('applySourceChange', commands.applySourceChange); - ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEdit); + ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand); ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); ctx.pushCleanup(activateTaskProvider(workspaceFolder)); diff --git a/editors/code/src/rust-analyzer-api.ts b/editors/code/src/rust-analyzer-api.ts index 400ac3714..3b83b10e3 100644 --- a/editors/code/src/rust-analyzer-api.ts +++ b/editors/code/src/rust-analyzer-api.ts @@ -69,7 +69,7 @@ export interface JoinLinesParams { export const joinLines = request("joinLines"); -export const onEnter = request>("onEnter"); +export const onEnter = request>("onEnter"); export interface RunnablesParams { textDocument: lc.TextDocumentIdentifier; -- cgit v1.2.3 From ff28c79ebd4c5a9a27542917940def9d4e66eea6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 21 May 2020 14:34:27 +0200 Subject: Remove dead code for handling cursor positions --- crates/ra_assists/src/tests.rs | 9 +- crates/ra_ide/src/diagnostics.rs | 2 - crates/ra_ide/src/lib.rs | 1 - crates/ra_ide/src/references/rename.rs | 3 - crates/ra_ide_db/src/lib.rs | 1 - crates/ra_ide_db/src/line_index_utils.rs | 302 ------------------------------- crates/ra_ide_db/src/source_change.rs | 19 +- crates/rust-analyzer/src/to_proto.rs | 63 +------ 8 files changed, 12 insertions(+), 388 deletions(-) delete mode 100644 crates/ra_ide_db/src/line_index_utils.rs diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs index 373a7f7cc..62dd3547f 100644 --- a/crates/ra_assists/src/tests.rs +++ b/crates/ra_assists/src/tests.rs @@ -7,8 +7,7 @@ use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; use ra_syntax::TextRange; use test_utils::{ - add_cursor, assert_eq_text, extract_offset, extract_range, extract_range_or_offset, - RangeOrOffset, + assert_eq_text, extract_offset, extract_range, extract_range_or_offset, RangeOrOffset, }; use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, Assists}; @@ -103,12 +102,6 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult) { let mut actual = db.file_text(change.file_id).as_ref().to_owned(); change.edit.apply(&mut actual); - - if !source_change.is_snippet { - if let Some(off) = source_change.cursor_position { - actual = add_cursor(&actual, off.offset) - } - } assert_eq_text!(after, &actual); } (Some(assist), ExpectedResult::Target(target)) => { diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index 54c2bcc09..c2819bbf7 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs @@ -628,7 +628,6 @@ mod tests { path: "foo.rs", }, ], - cursor_position: None, is_snippet: false, }, ), @@ -685,7 +684,6 @@ mod tests { }, ], file_system_edits: [], - cursor_position: None, is_snippet: false, }, ), diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 83cb498f7..1d7bacbf6 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -87,7 +87,6 @@ pub use ra_db::{ pub use ra_ide_db::{ change::{AnalysisChange, LibraryData}, line_index::{LineCol, LineIndex}, - line_index_utils::translate_offset_with_edit, search::SearchScope, source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, symbol_index::Query, diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 62ec8d85d..55c3319cb 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -669,7 +669,6 @@ mod tests { dst_path: "bar/foo2.rs", }, ], - cursor_position: None, is_snippet: false, }, }, @@ -722,7 +721,6 @@ mod tests { dst_path: "foo2/mod.rs", }, ], - cursor_position: None, is_snippet: false, }, }, @@ -819,7 +817,6 @@ mod tests { dst_path: "bar/foo2.rs", }, ], - cursor_position: None, is_snippet: false, }, }, diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs index 4f37954bf..1b74e6558 100644 --- a/crates/ra_ide_db/src/lib.rs +++ b/crates/ra_ide_db/src/lib.rs @@ -3,7 +3,6 @@ //! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search. pub mod line_index; -pub mod line_index_utils; pub mod symbol_index; pub mod change; pub mod defs; diff --git a/crates/ra_ide_db/src/line_index_utils.rs b/crates/ra_ide_db/src/line_index_utils.rs deleted file mode 100644 index 7fa6fc448..000000000 --- a/crates/ra_ide_db/src/line_index_utils.rs +++ /dev/null @@ -1,302 +0,0 @@ -//! Code actions can specify desirable final position of the cursor. -//! -//! The position is specified as a `TextSize` in the final file. We need to send -//! it in `(Line, Column)` coordinate though. However, we only have a LineIndex -//! for a file pre-edit! -//! -//! Code in this module applies this "to (Line, Column) after edit" -//! transformation. - -use std::convert::TryInto; - -use ra_syntax::{TextRange, TextSize}; -use ra_text_edit::{Indel, TextEdit}; - -use crate::line_index::{LineCol, LineIndex, Utf16Char}; - -pub fn translate_offset_with_edit( - line_index: &LineIndex, - offset: TextSize, - text_edit: &TextEdit, -) -> LineCol { - let mut state = Edits::from_text_edit(&text_edit); - - let mut res = RunningLineCol::new(); - - macro_rules! test_step { - ($x:ident) => { - match &$x { - Step::Newline(n) => { - if offset < *n { - return res.to_line_col(offset); - } else { - res.add_line(*n); - } - } - Step::Utf16Char(x) => { - if offset < x.end() { - // if the offset is inside a multibyte char it's invalid - // clamp it to the start of the char - let clamp = offset.min(x.start()); - return res.to_line_col(clamp); - } else { - res.adjust_col(*x); - } - } - } - }; - } - - for orig_step in LineIndexStepIter::from(line_index) { - loop { - let translated_step = state.translate_step(&orig_step); - match state.next_steps(&translated_step) { - NextSteps::Use => { - test_step!(translated_step); - break; - } - NextSteps::ReplaceMany(ns) => { - for n in ns { - test_step!(n); - } - break; - } - NextSteps::AddMany(ns) => { - for n in ns { - test_step!(n); - } - } - } - } - } - - loop { - match state.next_inserted_steps() { - None => break, - Some(ns) => { - for n in ns { - test_step!(n); - } - } - } - } - - res.to_line_col(offset) -} - -#[derive(Debug, Clone)] -enum Step { - Newline(TextSize), - Utf16Char(TextRange), -} - -#[derive(Debug)] -struct LineIndexStepIter<'a> { - line_index: &'a LineIndex, - next_newline_idx: usize, - utf16_chars: Option<(TextSize, std::slice::Iter<'a, Utf16Char>)>, -} - -impl LineIndexStepIter<'_> { - fn from(line_index: &LineIndex) -> LineIndexStepIter { - let mut x = LineIndexStepIter { line_index, next_newline_idx: 0, utf16_chars: None }; - // skip first newline since it's not real - x.next(); - x - } -} - -impl Iterator for LineIndexStepIter<'_> { - type Item = Step; - fn next(&mut self) -> Option { - self.utf16_chars - .as_mut() - .and_then(|(newline, x)| { - let x = x.next()?; - Some(Step::Utf16Char(TextRange::new(*newline + x.start, *newline + x.end))) - }) - .or_else(|| { - let next_newline = *self.line_index.newlines.get(self.next_newline_idx)?; - self.utf16_chars = self - .line_index - .utf16_lines - .get(&(self.next_newline_idx as u32)) - .map(|x| (next_newline, x.iter())); - self.next_newline_idx += 1; - Some(Step::Newline(next_newline)) - }) - } -} - -#[derive(Debug)] -struct OffsetStepIter<'a> { - text: &'a str, - offset: TextSize, -} - -impl Iterator for OffsetStepIter<'_> { - type Item = Step; - fn next(&mut self) -> Option { - let (next, next_offset) = self - .text - .char_indices() - .filter_map(|(i, c)| { - let i: TextSize = i.try_into().unwrap(); - let char_len = TextSize::of(c); - if c == '\n' { - let next_offset = self.offset + i + char_len; - let next = Step::Newline(next_offset); - Some((next, next_offset)) - } else { - if !c.is_ascii() { - let start = self.offset + i; - let end = start + char_len; - let next = Step::Utf16Char(TextRange::new(start, end)); - let next_offset = end; - Some((next, next_offset)) - } else { - None - } - } - }) - .next()?; - let next_idx: usize = (next_offset - self.offset).into(); - self.text = &self.text[next_idx..]; - self.offset = next_offset; - Some(next) - } -} - -#[derive(Debug)] -enum NextSteps<'a> { - Use, - ReplaceMany(OffsetStepIter<'a>), - AddMany(OffsetStepIter<'a>), -} - -#[derive(Debug)] -struct TranslatedEdit<'a> { - delete: TextRange, - insert: &'a str, - diff: i64, -} - -struct Edits<'a> { - edits: &'a [Indel], - current: Option>, - acc_diff: i64, -} - -impl<'a> Edits<'a> { - fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> { - let mut x = Edits { edits: text_edit.as_indels(), current: None, acc_diff: 0 }; - x.advance_edit(); - x - } - fn advance_edit(&mut self) { - self.acc_diff += self.current.as_ref().map_or(0, |x| x.diff); - match self.edits.split_first() { - Some((next, rest)) => { - let delete = self.translate_range(next.delete); - let diff = next.insert.len() as i64 - usize::from(next.delete.len()) as i64; - self.current = Some(TranslatedEdit { delete, insert: &next.insert, diff }); - self.edits = rest; - } - None => { - self.current = None; - } - } - } - - fn next_inserted_steps(&mut self) -> Option> { - let cur = self.current.as_ref()?; - let res = Some(OffsetStepIter { offset: cur.delete.start(), text: &cur.insert }); - self.advance_edit(); - res - } - - fn next_steps(&mut self, step: &Step) -> NextSteps { - let step_pos = match *step { - Step::Newline(n) => n, - Step::Utf16Char(r) => r.end(), - }; - match &mut self.current { - Some(edit) => { - if step_pos <= edit.delete.start() { - NextSteps::Use - } else if step_pos <= edit.delete.end() { - let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert }; - // empty slice to avoid returning steps again - edit.insert = &edit.insert[edit.insert.len()..]; - NextSteps::ReplaceMany(iter) - } else { - let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert }; - // empty slice to avoid returning steps again - edit.insert = &edit.insert[edit.insert.len()..]; - self.advance_edit(); - NextSteps::AddMany(iter) - } - } - None => NextSteps::Use, - } - } - - fn translate_range(&self, range: TextRange) -> TextRange { - if self.acc_diff == 0 { - range - } else { - let start = self.translate(range.start()); - let end = self.translate(range.end()); - TextRange::new(start, end) - } - } - - fn translate(&self, x: TextSize) -> TextSize { - if self.acc_diff == 0 { - x - } else { - TextSize::from((usize::from(x) as i64 + self.acc_diff) as u32) - } - } - - fn translate_step(&self, x: &Step) -> Step { - if self.acc_diff == 0 { - x.clone() - } else { - match *x { - Step::Newline(n) => Step::Newline(self.translate(n)), - Step::Utf16Char(r) => Step::Utf16Char(self.translate_range(r)), - } - } - } -} - -#[derive(Debug)] -struct RunningLineCol { - line: u32, - last_newline: TextSize, - col_adjust: TextSize, -} - -impl RunningLineCol { - fn new() -> RunningLineCol { - RunningLineCol { line: 0, last_newline: TextSize::from(0), col_adjust: TextSize::from(0) } - } - - fn to_line_col(&self, offset: TextSize) -> LineCol { - LineCol { - line: self.line, - col_utf16: ((offset - self.last_newline) - self.col_adjust).into(), - } - } - - fn add_line(&mut self, newline: TextSize) { - self.line += 1; - self.last_newline = newline; - self.col_adjust = TextSize::from(0); - } - - fn adjust_col(&mut self, range: TextRange) { - self.col_adjust += range.len() - TextSize::from(1); - } -} diff --git a/crates/ra_ide_db/src/source_change.rs b/crates/ra_ide_db/src/source_change.rs index 94e118dd8..3484f5588 100644 --- a/crates/ra_ide_db/src/source_change.rs +++ b/crates/ra_ide_db/src/source_change.rs @@ -3,7 +3,7 @@ //! //! It can be viewed as a dual for `AnalysisChange`. -use ra_db::{FileId, FilePosition, RelativePathBuf, SourceRootId}; +use ra_db::{FileId, RelativePathBuf, SourceRootId}; use ra_text_edit::TextEdit; #[derive(Debug, Clone)] @@ -12,7 +12,6 @@ pub struct SourceChange { pub label: String, pub source_file_edits: Vec, pub file_system_edits: Vec, - pub cursor_position: Option, pub is_snippet: bool, } @@ -28,7 +27,6 @@ impl SourceChange { label: label.into(), source_file_edits, file_system_edits, - cursor_position: None, is_snippet: false, } } @@ -42,7 +40,6 @@ impl SourceChange { label: label, source_file_edits: edits, file_system_edits: vec![], - cursor_position: None, is_snippet: false, } } @@ -54,7 +51,6 @@ impl SourceChange { label: label.into(), source_file_edits: vec![], file_system_edits: edits, - cursor_position: None, is_snippet: false, } } @@ -80,18 +76,6 @@ impl SourceChange { pub fn file_system_edit>(label: L, edit: FileSystemEdit) -> Self { SourceChange::file_system_edits(label, vec![edit]) } - - /// Sets the cursor position to the given `FilePosition` - pub fn with_cursor(mut self, cursor_position: FilePosition) -> Self { - self.cursor_position = Some(cursor_position); - self - } - - /// Sets the cursor position to the given `FilePosition` - pub fn with_cursor_opt(mut self, cursor_position: Option) -> Self { - self.cursor_position = cursor_position; - self - } } #[derive(Debug, Clone)] @@ -117,7 +101,6 @@ impl SingleFileChange { label: self.label, source_file_edits: vec![SourceFileEdit { file_id, edit: self.edit }], file_system_edits: Vec::new(), - cursor_position: None, is_snippet: false, } } diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index af54f81b7..9a8e9e174 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -1,10 +1,10 @@ //! Conversion of rust-analyzer specific types to lsp_types equivalents. use ra_db::{FileId, FileRange}; use ra_ide::{ - translate_offset_with_edit, Assist, CompletionItem, CompletionItemKind, Documentation, - FileSystemEdit, Fold, FoldKind, FunctionSignature, Highlight, HighlightModifier, HighlightTag, - HighlightedRange, InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, - ReferenceAccess, Severity, SourceChange, SourceFileEdit, + Assist, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, FoldKind, + FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, InlayHint, + InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, Severity, + SourceChange, SourceFileEdit, }; use ra_syntax::{SyntaxKind, TextRange, TextSize}; use ra_text_edit::{Indel, TextEdit}; @@ -375,14 +375,6 @@ pub(crate) fn url(world: &WorldSnapshot, file_id: FileId) -> Result Result { - let res = lsp_types::TextDocumentIdentifier { uri: url(world, file_id)? }; - Ok(res) -} - pub(crate) fn versioned_text_document_identifier( world: &WorldSnapshot, file_id: FileId, @@ -496,30 +488,9 @@ pub(crate) fn source_change( world: &WorldSnapshot, source_change: SourceChange, ) -> Result { - let cursor_position = match source_change.cursor_position { - None => None, - Some(pos) => { - let line_index = world.analysis().file_line_index(pos.file_id)?; - let edit = source_change - .source_file_edits - .iter() - .find(|it| it.file_id == pos.file_id) - .map(|it| &it.edit); - let line_col = match edit { - Some(edit) => translate_offset_with_edit(&*line_index, pos.offset, edit), - None => line_index.line_col(pos.offset), - }; - let position = - lsp_types::Position::new(u64::from(line_col.line), u64::from(line_col.col_utf16)); - Some(lsp_types::TextDocumentPositionParams { - text_document: text_document_identifier(world, pos.file_id)?, - position, - }) - } - }; let label = source_change.label.clone(); let workspace_edit = self::snippet_workspace_edit(world, source_change)?; - Ok(lsp_ext::SourceChange { label, workspace_edit, cursor_position }) + Ok(lsp_ext::SourceChange { label, workspace_edit, cursor_position: None }) } pub(crate) fn snippet_workspace_edit( @@ -639,25 +610,11 @@ fn main() { } pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result { - let res = if assist.source_change.cursor_position.is_none() { - lsp_ext::CodeAction { - title: assist.label, - kind: Some(String::new()), - edit: Some(snippet_workspace_edit(world, assist.source_change)?), - command: None, - } - } else { - assert!(!assist.source_change.is_snippet); - let source_change = source_change(&world, assist.source_change)?; - let arg = serde_json::to_value(source_change)?; - let title = assist.label; - let command = lsp_types::Command { - title: title.clone(), - command: "rust-analyzer.applySourceChange".to_string(), - arguments: Some(vec![arg]), - }; - - lsp_ext::CodeAction { title, kind: Some(String::new()), edit: None, command: Some(command) } + let res = lsp_ext::CodeAction { + title: assist.label, + kind: Some(String::new()), + edit: Some(snippet_workspace_edit(world, assist.source_change)?), + command: None, }; Ok(res) } -- cgit v1.2.3