aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/completion/completion_item.rs
diff options
context:
space:
mode:
authorgfreezy <[email protected]>2019-01-19 16:38:34 +0000
committergfreezy <[email protected]>2019-01-19 16:38:34 +0000
commit94d96b60f334e662f516bd0f04cc4191d7a804e6 (patch)
tree34ed5b9da22c938a5f7a3cac7a09de5812fa819f /crates/ra_ide_api/src/completion/completion_item.rs
parent64342599ca43fb72d0db8e79802a1018f480b5f5 (diff)
refactor to use `remove_range` and `replace_range` instead of TextEdit
Diffstat (limited to 'crates/ra_ide_api/src/completion/completion_item.rs')
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs110
1 files changed, 36 insertions, 74 deletions
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index f9a266524..da8da94d1 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -1,10 +1,7 @@
1use hir::PerNs; 1use hir::PerNs;
2use ra_text_edit::{
3 AtomTextEdit,
4 TextEdit,
5};
6 2
7use crate::completion::completion_context::CompletionContext; 3use crate::completion::completion_context::CompletionContext;
4use ra_syntax::TextRange;
8 5
9/// `CompletionItem` describes a single completion variant in the editor pop-up. 6/// `CompletionItem` describes a single completion variant in the editor pop-up.
10/// It is basically a POD with various properties. To construct a 7/// It is basically a POD with various properties. To construct a
@@ -18,26 +15,10 @@ pub struct CompletionItem {
18 kind: Option<CompletionItemKind>, 15 kind: Option<CompletionItemKind>,
19 detail: Option<String>, 16 detail: Option<String>,
20 lookup: Option<String>, 17 lookup: Option<String>,
21 /// The format of the insert text. The format applies to both the `insert_text` property 18 insert_text: Option<String>,
22 /// and the `insert` property of a provided `text_edit`.
23 insert_text_format: InsertTextFormat, 19 insert_text_format: InsertTextFormat,
24 /// An edit which is applied to a document when selecting this completion. When an edit is 20 replace_range: TextRange,
25 /// provided the value of `insert_text` is ignored. 21 delete_range: Option<TextRange>,
26 ///
27 /// *Note:* The range of the edit must be a single line range and it must contain the position
28 /// at which completion has been requested.
29 ///
30 /// *Note:* If sending a range that overlaps a string, the string should match the relevant
31 /// part of the replacement text, or be filtered out.
32 text_edit: Option<AtomTextEdit>,
33 /// An optional array of additional text edits that are applied when
34 /// selecting this completion. Edits must not overlap (including the same insert position)
35 /// with the main edit nor with themselves.
36 ///
37 /// Additional text edits should be used to change text unrelated to the current cursor position
38 /// (for example adding an import statement at the top of the file if the completion item will
39 /// insert an unqualified type).
40 additional_text_edits: Option<TextEdit>,
41} 22}
42 23
43#[derive(Debug, Clone, Copy, PartialEq, Eq)] 24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -76,14 +57,14 @@ pub enum InsertTextFormat {
76} 57}
77 58
78impl CompletionItem { 59impl CompletionItem {
79 pub(crate) fn new<'a>( 60 pub(crate) fn new(
80 completion_kind: CompletionKind, 61 completion_kind: CompletionKind,
81 ctx: &'a CompletionContext, 62 replace_range: TextRange,
82 label: impl Into<String>, 63 label: impl Into<String>,
83 ) -> Builder<'a> { 64 ) -> Builder {
84 let label = label.into(); 65 let label = label.into();
85 Builder { 66 Builder {
86 ctx, 67 replace_range,
87 completion_kind, 68 completion_kind,
88 label, 69 label,
89 insert_text: None, 70 insert_text: None,
@@ -91,8 +72,7 @@ impl CompletionItem {
91 detail: None, 72 detail: None,
92 lookup: None, 73 lookup: None,
93 kind: None, 74 kind: None,
94 text_edit: None, 75 delete_range: None,
95 additional_text_edits: None,
96 } 76 }
97 } 77 }
98 /// What user sees in pop-up in the UI. 78 /// What user sees in pop-up in the UI.
@@ -114,22 +94,27 @@ impl CompletionItem {
114 pub fn insert_text_format(&self) -> InsertTextFormat { 94 pub fn insert_text_format(&self) -> InsertTextFormat {
115 self.insert_text_format.clone() 95 self.insert_text_format.clone()
116 } 96 }
117 97 pub fn insert_text(&self) -> String {
98 match &self.insert_text {
99 Some(t) => t.clone(),
100 None => self.label.clone(),
101 }
102 }
118 pub fn kind(&self) -> Option<CompletionItemKind> { 103 pub fn kind(&self) -> Option<CompletionItemKind> {
119 self.kind 104 self.kind
120 } 105 }
121 pub fn text_edit(&mut self) -> Option<&AtomTextEdit> { 106 pub fn delete_range(&self) -> Option<TextRange> {
122 self.text_edit.as_ref() 107 self.delete_range
123 } 108 }
124 pub fn take_additional_text_edits(&mut self) -> Option<TextEdit> { 109 pub fn replace_range(&self) -> TextRange {
125 self.additional_text_edits.take() 110 self.replace_range
126 } 111 }
127} 112}
128 113
129/// A helper to make `CompletionItem`s. 114/// A helper to make `CompletionItem`s.
130#[must_use] 115#[must_use]
131pub(crate) struct Builder<'a> { 116pub(crate) struct Builder {
132 ctx: &'a CompletionContext<'a>, 117 replace_range: TextRange,
133 completion_kind: CompletionKind, 118 completion_kind: CompletionKind,
134 label: String, 119 label: String,
135 insert_text: Option<String>, 120 insert_text: Option<String>,
@@ -137,76 +122,53 @@ pub(crate) struct Builder<'a> {
137 detail: Option<String>, 122 detail: Option<String>,
138 lookup: Option<String>, 123 lookup: Option<String>,
139 kind: Option<CompletionItemKind>, 124 kind: Option<CompletionItemKind>,
140 text_edit: Option<AtomTextEdit>, 125 delete_range: Option<TextRange>,
141 additional_text_edits: Option<TextEdit>,
142} 126}
143 127
144impl<'a> Builder<'a> { 128impl Builder {
145 pub(crate) fn add_to(self, acc: &mut Completions) { 129 pub(crate) fn add_to(self, acc: &mut Completions) {
146 acc.add(self.build()) 130 acc.add(self.build())
147 } 131 }
148 132
149 pub(crate) fn build(self) -> CompletionItem { 133 pub(crate) fn build(self) -> CompletionItem {
150 let self_text_edit = self.text_edit;
151 let self_insert_text = self.insert_text;
152 let text_edit = match (self_text_edit, self_insert_text) {
153 (Some(text_edit), ..) => Some(text_edit),
154 (None, Some(insert_text)) => {
155 Some(AtomTextEdit::replace(self.ctx.leaf_range(), insert_text))
156 }
157 _ => None,
158 };
159
160 CompletionItem { 134 CompletionItem {
135 replace_range: self.replace_range,
161 label: self.label, 136 label: self.label,
162 detail: self.detail, 137 detail: self.detail,
163 insert_text_format: self.insert_text_format, 138 insert_text_format: self.insert_text_format,
164 lookup: self.lookup, 139 lookup: self.lookup,
165 kind: self.kind, 140 kind: self.kind,
166 completion_kind: self.completion_kind, 141 completion_kind: self.completion_kind,
167 text_edit, 142 delete_range: self.delete_range,
168 additional_text_edits: self.additional_text_edits, 143 insert_text: self.insert_text,
169 } 144 }
170 } 145 }
171 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder<'a> { 146 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
172 self.lookup = Some(lookup.into()); 147 self.lookup = Some(lookup.into());
173 self 148 self
174 } 149 }
175 pub(crate) fn insert_text(mut self, insert_text: impl Into<String>) -> Builder<'a> { 150 pub(crate) fn insert_text(mut self, insert_text: impl Into<String>) -> Builder {
176 self.insert_text = Some(insert_text.into()); 151 self.insert_text = Some(insert_text.into());
177 self 152 self
178 } 153 }
179 #[allow(unused)] 154 #[allow(unused)]
180 pub(crate) fn insert_text_format( 155 pub(crate) fn insert_text_format(mut self, insert_text_format: InsertTextFormat) -> Builder {
181 mut self,
182 insert_text_format: InsertTextFormat,
183 ) -> Builder<'a> {
184 self.insert_text_format = insert_text_format; 156 self.insert_text_format = insert_text_format;
185 self 157 self
186 } 158 }
187 pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder<'a> { 159 pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder {
188 self.insert_text_format = InsertTextFormat::Snippet; 160 self.insert_text_format = InsertTextFormat::Snippet;
189 self.insert_text(snippet) 161 self.insert_text(snippet)
190 } 162 }
191 pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder<'a> { 163 pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder {
192 self.kind = Some(kind); 164 self.kind = Some(kind);
193 self 165 self
194 } 166 }
195 #[allow(unused)] 167 #[allow(unused)]
196 pub(crate) fn text_edit(mut self, text_edit: AtomTextEdit) -> Builder<'a> { 168 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder {
197 self.text_edit = Some(text_edit);
198 self
199 }
200 #[allow(unused)]
201 pub(crate) fn additional_text_edits(mut self, additional_text_edits: TextEdit) -> Builder<'a> {
202 self.additional_text_edits = Some(additional_text_edits);
203 self
204 }
205 #[allow(unused)]
206 pub(crate) fn detail(self, detail: impl Into<String>) -> Builder<'a> {
207 self.set_detail(Some(detail)) 169 self.set_detail(Some(detail))
208 } 170 }
209 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder<'a> { 171 pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder {
210 self.detail = detail.map(Into::into); 172 self.detail = detail.map(Into::into);
211 self 173 self
212 } 174 }
@@ -214,7 +176,7 @@ impl<'a> Builder<'a> {
214 mut self, 176 mut self,
215 ctx: &CompletionContext, 177 ctx: &CompletionContext,
216 resolution: &hir::Resolution, 178 resolution: &hir::Resolution,
217 ) -> Builder<'a> { 179 ) -> Builder {
218 let resolved = resolution.def_id.map(|d| d.resolve(ctx.db)); 180 let resolved = resolution.def_id.map(|d| d.resolve(ctx.db));
219 let kind = match resolved { 181 let kind = match resolved {
220 PerNs { 182 PerNs {
@@ -259,7 +221,7 @@ impl<'a> Builder<'a> {
259 mut self, 221 mut self,
260 ctx: &CompletionContext, 222 ctx: &CompletionContext,
261 function: hir::Function, 223 function: hir::Function,
262 ) -> Builder<'a> { 224 ) -> Builder {
263 // If not an import, add parenthesis automatically. 225 // If not an import, add parenthesis automatically.
264 if ctx.use_item_syntax.is_none() && !ctx.is_call { 226 if ctx.use_item_syntax.is_none() && !ctx.is_call {
265 if function.signature(ctx.db).params().is_empty() { 227 if function.signature(ctx.db).params().is_empty() {
@@ -274,7 +236,7 @@ impl<'a> Builder<'a> {
274 } 236 }
275} 237}
276 238
277impl<'a> Into<CompletionItem> for Builder<'a> { 239impl<'a> Into<CompletionItem> for Builder {
278 fn into(self) -> CompletionItem { 240 fn into(self) -> CompletionItem {
279 self.build() 241 self.build()
280 } 242 }