diff options
author | Aleksey Kladov <[email protected]> | 2019-02-18 09:05:16 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-02-18 09:24:20 +0000 |
commit | 92aa0f9c871a9308ea3db1b1c4b7e42d88348e30 (patch) | |
tree | ce785e530a547e3aede708b7725b4a95e666f45f /crates/ra_ide_api/src/completion/completion_item.rs | |
parent | 79f35cc6992d18e97b0bb9e309a2dc37f6f286e8 (diff) |
Don't use additional_text_edits API internally
Diffstat (limited to 'crates/ra_ide_api/src/completion/completion_item.rs')
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_item.rs | 103 |
1 files changed, 62 insertions, 41 deletions
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 1cdcde211..9aa9768d1 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs | |||
@@ -2,7 +2,7 @@ use std::fmt; | |||
2 | 2 | ||
3 | use hir::{Docs, Documentation, PerNs, Resolution}; | 3 | use hir::{Docs, Documentation, PerNs, Resolution}; |
4 | use ra_syntax::TextRange; | 4 | use ra_syntax::TextRange; |
5 | use ra_text_edit::TextEdit; | 5 | use ra_text_edit::{ TextEditBuilder, TextEdit}; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | 7 | ||
8 | use crate::completion::{ | 8 | use crate::completion::{ |
@@ -17,29 +17,47 @@ use crate::completion::{ | |||
17 | /// `CompletionItem`, use `new` method and the `Builder` struct. | 17 | /// `CompletionItem`, use `new` method and the `Builder` struct. |
18 | pub struct CompletionItem { | 18 | pub struct CompletionItem { |
19 | /// Used only internally in tests, to check only specific kind of | 19 | /// Used only internally in tests, to check only specific kind of |
20 | /// completion. | 20 | /// completion (postfix, keyword, reference, etc). |
21 | #[allow(unused)] | 21 | #[allow(unused)] |
22 | completion_kind: CompletionKind, | 22 | completion_kind: CompletionKind, |
23 | /// Label in the completion pop up which identifies completion. | ||
23 | label: String, | 24 | label: String, |
25 | /// Range of identifier that is being completed. | ||
26 | /// | ||
27 | /// It should be used primarily for UI, but we also use this to convert | ||
28 | /// genetic TextEdit into LSP's completion edit (see conv.rs). | ||
29 | /// | ||
30 | /// `source_range` must contain the completion offset. `insert_text` should | ||
31 | /// start with what `source_range` points to, or VSCode will filter out the | ||
32 | /// completion silently. | ||
33 | source_range: TextRange, | ||
34 | /// What happens when user selects this item. | ||
35 | /// | ||
36 | /// Typically, replaces `source_range` with new identifier. | ||
37 | text_edit: TextEdit, | ||
38 | insert_text_format: InsertTextFormat, | ||
39 | |||
40 | /// What item (struct, function, etc) are we completing. | ||
24 | kind: Option<CompletionItemKind>, | 41 | kind: Option<CompletionItemKind>, |
42 | |||
43 | /// Lookup is used to check if completion item indeed can complete current | ||
44 | /// ident. | ||
45 | /// | ||
46 | /// That is, in `foo.bar<|>` lookup of `abracadabra` will be accepted (it | ||
47 | /// contains `bar` sub sequence), and `quux` will rejected. | ||
25 | lookup: Option<String>, | 48 | lookup: Option<String>, |
49 | |||
50 | /// Additional info to show in the UI pop up. | ||
26 | detail: Option<String>, | 51 | detail: Option<String>, |
27 | documentation: Option<Documentation>, | 52 | documentation: Option<Documentation>, |
28 | insert_text: Option<String>, | ||
29 | insert_text_format: InsertTextFormat, | ||
30 | /// Where completion occurs. `source_range` must contain the completion offset. | ||
31 | /// `insert_text` should start with what `source_range` points to, or VSCode | ||
32 | /// will filter out the completion silently. | ||
33 | source_range: TextRange, | ||
34 | /// Additional text edit, ranges in `text_edit` must never intersect with `source_range`. | ||
35 | /// Or VSCode will drop it silently. | ||
36 | text_edit: Option<TextEdit>, | ||
37 | } | 53 | } |
38 | 54 | ||
39 | impl fmt::Debug for CompletionItem { | 55 | impl fmt::Debug for CompletionItem { |
40 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 56 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
41 | let mut s = f.debug_struct("CompletionItem"); | 57 | let mut s = f.debug_struct("CompletionItem"); |
42 | s.field("label", &self.label()).field("source_range", &self.source_range()); | 58 | s.field("label", &self.label()) |
59 | .field("source_range", &self.source_range()) | ||
60 | .field("text_edit", &self.text_edit); | ||
43 | if let Some(kind) = self.kind().as_ref() { | 61 | if let Some(kind) = self.kind().as_ref() { |
44 | s.field("kind", kind); | 62 | s.field("kind", kind); |
45 | } | 63 | } |
@@ -52,13 +70,6 @@ impl fmt::Debug for CompletionItem { | |||
52 | if let Some(documentation) = self.documentation() { | 70 | if let Some(documentation) = self.documentation() { |
53 | s.field("documentation", &documentation); | 71 | s.field("documentation", &documentation); |
54 | } | 72 | } |
55 | if self.insert_text() != self.label() { | ||
56 | s.field("insert_text", &self.insert_text()) | ||
57 | .field("insert_text_format", &self.insert_text_format()); | ||
58 | } | ||
59 | if let Some(edit) = self.text_edit.as_ref() { | ||
60 | s.field("text_edit", edit); | ||
61 | } | ||
62 | s.finish() | 73 | s.finish() |
63 | } | 74 | } |
64 | } | 75 | } |
@@ -103,12 +114,12 @@ pub enum InsertTextFormat { | |||
103 | impl CompletionItem { | 114 | impl CompletionItem { |
104 | pub(crate) fn new( | 115 | pub(crate) fn new( |
105 | completion_kind: CompletionKind, | 116 | completion_kind: CompletionKind, |
106 | replace_range: TextRange, | 117 | source_range: TextRange, |
107 | label: impl Into<String>, | 118 | label: impl Into<String>, |
108 | ) -> Builder { | 119 | ) -> Builder { |
109 | let label = label.into(); | 120 | let label = label.into(); |
110 | Builder { | 121 | Builder { |
111 | source_range: replace_range, | 122 | source_range, |
112 | completion_kind, | 123 | completion_kind, |
113 | label, | 124 | label, |
114 | insert_text: None, | 125 | insert_text: None, |
@@ -124,6 +135,18 @@ impl CompletionItem { | |||
124 | pub fn label(&self) -> &str { | 135 | pub fn label(&self) -> &str { |
125 | &self.label | 136 | &self.label |
126 | } | 137 | } |
138 | pub fn source_range(&self) -> TextRange { | ||
139 | self.source_range | ||
140 | } | ||
141 | |||
142 | pub fn insert_text_format(&self) -> InsertTextFormat { | ||
143 | self.insert_text_format | ||
144 | } | ||
145 | |||
146 | pub fn text_edit(&self) -> &TextEdit { | ||
147 | &self.text_edit | ||
148 | } | ||
149 | |||
127 | /// Short one-line additional information, like a type | 150 | /// Short one-line additional information, like a type |
128 | pub fn detail(&self) -> Option<&str> { | 151 | pub fn detail(&self) -> Option<&str> { |
129 | self.detail.as_ref().map(|it| it.as_str()) | 152 | self.detail.as_ref().map(|it| it.as_str()) |
@@ -137,24 +160,9 @@ impl CompletionItem { | |||
137 | self.lookup.as_ref().map(|it| it.as_str()).unwrap_or_else(|| self.label()) | 160 | self.lookup.as_ref().map(|it| it.as_str()).unwrap_or_else(|| self.label()) |
138 | } | 161 | } |
139 | 162 | ||
140 | pub fn insert_text_format(&self) -> InsertTextFormat { | ||
141 | self.insert_text_format | ||
142 | } | ||
143 | pub fn insert_text(&self) -> String { | ||
144 | match &self.insert_text { | ||
145 | Some(t) => t.clone(), | ||
146 | None => self.label.clone(), | ||
147 | } | ||
148 | } | ||
149 | pub fn kind(&self) -> Option<CompletionItemKind> { | 163 | pub fn kind(&self) -> Option<CompletionItemKind> { |
150 | self.kind | 164 | self.kind |
151 | } | 165 | } |
152 | pub fn take_text_edit(&mut self) -> Option<TextEdit> { | ||
153 | self.text_edit.take() | ||
154 | } | ||
155 | pub fn source_range(&self) -> TextRange { | ||
156 | self.source_range | ||
157 | } | ||
158 | } | 166 | } |
159 | 167 | ||
160 | /// A helper to make `CompletionItem`s. | 168 | /// A helper to make `CompletionItem`s. |
@@ -178,17 +186,27 @@ impl Builder { | |||
178 | } | 186 | } |
179 | 187 | ||
180 | pub(crate) fn build(self) -> CompletionItem { | 188 | pub(crate) fn build(self) -> CompletionItem { |
189 | let label = self.label; | ||
190 | let text_edit = match self.text_edit { | ||
191 | Some(it) => it, | ||
192 | None => { | ||
193 | let mut builder = TextEditBuilder::default(); | ||
194 | builder | ||
195 | .replace(self.source_range, self.insert_text.unwrap_or_else(|| label.clone())); | ||
196 | builder.finish() | ||
197 | } | ||
198 | }; | ||
199 | |||
181 | CompletionItem { | 200 | CompletionItem { |
182 | source_range: self.source_range, | 201 | source_range: self.source_range, |
183 | label: self.label, | 202 | label, |
203 | insert_text_format: self.insert_text_format, | ||
204 | text_edit, | ||
184 | detail: self.detail, | 205 | detail: self.detail, |
185 | documentation: self.documentation, | 206 | documentation: self.documentation, |
186 | insert_text_format: self.insert_text_format, | ||
187 | lookup: self.lookup, | 207 | lookup: self.lookup, |
188 | kind: self.kind, | 208 | kind: self.kind, |
189 | completion_kind: self.completion_kind, | 209 | completion_kind: self.completion_kind, |
190 | text_edit: self.text_edit, | ||
191 | insert_text: self.insert_text, | ||
192 | } | 210 | } |
193 | } | 211 | } |
194 | pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { | 212 | pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { |
@@ -207,11 +225,14 @@ impl Builder { | |||
207 | self.kind = Some(kind); | 225 | self.kind = Some(kind); |
208 | self | 226 | self |
209 | } | 227 | } |
210 | #[allow(unused)] | ||
211 | pub(crate) fn text_edit(mut self, edit: TextEdit) -> Builder { | 228 | pub(crate) fn text_edit(mut self, edit: TextEdit) -> Builder { |
212 | self.text_edit = Some(edit); | 229 | self.text_edit = Some(edit); |
213 | self | 230 | self |
214 | } | 231 | } |
232 | pub(crate) fn snippet_edit(mut self, edit: TextEdit) -> Builder { | ||
233 | self.insert_text_format = InsertTextFormat::Snippet; | ||
234 | self.text_edit(edit) | ||
235 | } | ||
215 | #[allow(unused)] | 236 | #[allow(unused)] |
216 | pub(crate) fn detail(self, detail: impl Into<String>) -> Builder { | 237 | pub(crate) fn detail(self, detail: impl Into<String>) -> Builder { |
217 | self.set_detail(Some(detail)) | 238 | self.set_detail(Some(detail)) |