Skip to content

Commit 7d8ed7b

Browse files
additionalTextEdits handling
1 parent 9f3e561 commit 7d8ed7b

File tree

6 files changed

+75
-31
lines changed

6 files changed

+75
-31
lines changed

wasm-demo/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wasm-demo/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ serde-wasm-bindgen = "0.1"
1818

1919
ra_ide_api = { git = "https://github.com/rust-analyzer/rust-analyzer", features = ["wasm"] }
2020
ra_syntax = { git = "https://github.com/rust-analyzer/rust-analyzer" }
21+
ra_text_edit = { git = "https://github.com/rust-analyzer/rust-analyzer" }

wasm-demo/src/conv.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use super::return_types;
2-
use ra_ide_api::{CompletionItemKind, FileId, FilePosition, LineCol, LineIndex};
2+
use ra_ide_api::{
3+
CompletionItem, CompletionItemKind, FileId, FilePosition, InsertTextFormat, LineCol, LineIndex,
4+
};
35
use ra_syntax::TextRange;
6+
use ra_text_edit::AtomTextEdit;
47

58
pub trait Conv {
69
type Output;
@@ -70,3 +73,62 @@ impl Conv for CompletionItemKind {
7073
}
7174
}
7275
}
76+
77+
impl ConvWith<&LineIndex> for &AtomTextEdit {
78+
type Output = return_types::TextEdit;
79+
80+
fn conv_with(self, line_index: &LineIndex) -> Self::Output {
81+
let text = self.insert.clone();
82+
return_types::TextEdit { range: self.delete.conv_with(line_index), text }
83+
}
84+
}
85+
86+
impl ConvWith<&LineIndex> for CompletionItem {
87+
type Output = return_types::CompletionItem;
88+
89+
fn conv_with(self, line_index: &LineIndex) -> Self::Output {
90+
let mut additional_text_edits = Vec::new();
91+
let mut text_edit = None;
92+
// LSP does not allow arbitrary edits in completion, so we have to do a
93+
// non-trivial mapping here.
94+
for atom_edit in self.text_edit().as_atoms() {
95+
if self.source_range().is_subrange(&atom_edit.delete) {
96+
text_edit = Some(if atom_edit.delete == self.source_range() {
97+
atom_edit.conv_with(line_index)
98+
} else {
99+
assert!(self.source_range().end() == atom_edit.delete.end());
100+
let range1 =
101+
TextRange::from_to(atom_edit.delete.start(), self.source_range().start());
102+
let range2 = self.source_range();
103+
let edit1 = AtomTextEdit::replace(range1, String::new());
104+
let edit2 = AtomTextEdit::replace(range2, atom_edit.insert.clone());
105+
additional_text_edits.push(edit1.conv_with(line_index));
106+
edit2.conv_with(line_index)
107+
})
108+
} else {
109+
assert!(self.source_range().intersection(&atom_edit.delete).is_none());
110+
additional_text_edits.push(atom_edit.conv_with(line_index));
111+
}
112+
}
113+
let return_types::TextEdit { range, text } = text_edit.unwrap();
114+
115+
return_types::CompletionItem {
116+
kind: self.kind().unwrap_or(CompletionItemKind::Struct).conv(),
117+
label: self.label().to_string(),
118+
range,
119+
detail: self.detail().map(|it| it.to_string()),
120+
insertText: text,
121+
insertTextRules: match self.insert_text_format() {
122+
InsertTextFormat::PlainText => return_types::CompletionItemInsertTextRule::None,
123+
InsertTextFormat::Snippet => {
124+
return_types::CompletionItemInsertTextRule::InsertAsSnippet
125+
}
126+
},
127+
documentation: self
128+
.documentation()
129+
.map(|doc| return_types::MarkdownString { value: doc.as_str().to_string() }),
130+
filterText: self.lookup().to_string(),
131+
additionalTextEdits: additional_text_edits,
132+
}
133+
}
134+
}

wasm-demo/src/lib.rs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![cfg(target_arch = "wasm32")]
22
#![allow(non_snake_case)]
33

4-
use ra_ide_api::{Analysis, CompletionItemKind, FileId, FilePosition, InsertTextFormat, Severity};
4+
use ra_ide_api::{Analysis, FileId, FilePosition, Severity};
55
use ra_syntax::SyntaxKind;
66
use wasm_bindgen::prelude::*;
77

@@ -82,26 +82,7 @@ impl WorldState {
8282
None => return JsValue::NULL,
8383
};
8484

85-
log::warn!("{:#?}", res);
86-
87-
let items: Vec<_> = res
88-
.into_iter()
89-
.map(|item| CompletionItem {
90-
kind: item.kind().unwrap_or(CompletionItemKind::Struct).conv(),
91-
label: item.label().to_string(),
92-
range: item.source_range().conv_with(&line_index),
93-
detail: item.detail().map(|it| it.to_string()),
94-
insertText: item.text_edit().as_atoms()[0].insert.clone(),
95-
insertTextRules: match item.insert_text_format() {
96-
InsertTextFormat::PlainText => CompletionItemInsertTextRule::None,
97-
InsertTextFormat::Snippet => CompletionItemInsertTextRule::InsertAsSnippet,
98-
},
99-
documentation: item
100-
.documentation()
101-
.map(|doc| MarkdownString { value: doc.as_str().to_string() }),
102-
filterText: item.lookup().to_string(),
103-
})
104-
.collect();
85+
let items: Vec<_> = res.into_iter().map(|item| item.conv_with(&line_index)).collect();
10586
serde_wasm_bindgen::to_value(&items).unwrap()
10687
}
10788

wasm-demo/src/return_types.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub struct CompletionItem {
7777
pub insertTextRules: CompletionItemInsertTextRule,
7878
pub documentation: Option<MarkdownString>,
7979
pub filterText: String,
80+
pub additionalTextEdits: Vec<TextEdit>,
8081
}
8182

8283
#[allow(dead_code)]
@@ -108,7 +109,7 @@ pub enum CompletionItemKind {
108109
Customcolor = 22,
109110
Folder = 23,
110111
TypeParameter = 24,
111-
Snippet = 25
112+
Snippet = 25,
112113
}
113114

114115
#[allow(dead_code)]
@@ -117,12 +118,12 @@ pub enum CompletionItemKind {
117118
pub enum CompletionItemInsertTextRule {
118119
None = 0,
119120
/**
120-
* Adjust whitespace/indentation of multiline insert texts to
121-
* match the current line indentation.
122-
*/
121+
* Adjust whitespace/indentation of multiline insert texts to
122+
* match the current line indentation.
123+
*/
123124
KeepWhitespace = 1,
124125
/**
125-
* `insertText` is a snippet.
126-
*/
126+
* `insertText` is a snippet.
127+
*/
127128
InsertAsSnippet = 4,
128129
}

wasm-demo/www/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,8 @@ monaco.languages.onLanguage(modeId, async () => {
146146
});
147147
monaco.languages.registerCompletionItemProvider(modeId, {
148148
triggerCharacters: [".", ":", "="],
149-
provideCompletionItems(m, pos, ctx) {
150-
console.warn(ctx)
149+
provideCompletionItems(m, pos) {
151150
const suggestions = state.completions(pos.lineNumber, pos.column)
152-
console.warn(suggestions)
153151
return { suggestions }
154152
},
155153
});

0 commit comments

Comments
 (0)