Skip to content

Commit d4128be

Browse files
Avoid turning completion objects into builders
1 parent 4109968 commit d4128be

File tree

9 files changed

+117
-84
lines changed

9 files changed

+117
-84
lines changed

crates/assists/src/utils/insert_use.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use syntax::{
1515
};
1616
use test_utils::mark;
1717

18-
#[derive(Debug)]
18+
#[derive(Debug, Clone)]
1919
pub enum ImportScope {
2020
File(ast::SourceFile),
2121
Module(ast::ItemList),

crates/completion/src/completions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl Completions {
9090
Some(it) => it,
9191
None => return,
9292
};
93-
if let Some(item) = render_macro(RenderContext::new(ctx), name, macro_) {
93+
if let Some(item) = render_macro(RenderContext::new(ctx), None, name, macro_) {
9494
self.add(item);
9595
}
9696
}
@@ -101,7 +101,7 @@ impl Completions {
101101
func: hir::Function,
102102
local_name: Option<String>,
103103
) {
104-
let item = render_fn(RenderContext::new(ctx), local_name, func);
104+
let item = render_fn(RenderContext::new(ctx), None, local_name, func);
105105
self.add(item)
106106
}
107107

@@ -123,7 +123,7 @@ impl Completions {
123123
variant: hir::EnumVariant,
124124
path: ModPath,
125125
) {
126-
let item = render_enum_variant(RenderContext::new(ctx), None, variant, Some(path));
126+
let item = render_enum_variant(RenderContext::new(ctx), None, None, variant, Some(path));
127127
self.add(item);
128128
}
129129

@@ -133,7 +133,7 @@ impl Completions {
133133
variant: hir::EnumVariant,
134134
local_name: Option<String>,
135135
) {
136-
let item = render_enum_variant(RenderContext::new(ctx), local_name, variant, None);
136+
let item = render_enum_variant(RenderContext::new(ctx), None, local_name, variant, None);
137137
self.add(item);
138138
}
139139
}

crates/completion/src/completions/unqualified_path.rs

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
//! Completion of names from the current scope, e.g. locals and imported items.
22
3-
use assists::utils::{insert_use, mod_path_to_ast, ImportScope};
3+
use assists::utils::ImportScope;
44
use either::Either;
55
use hir::{Adt, ModuleDef, ScopeDef, Type};
66
use ide_db::imports_locator;
7-
use syntax::{algo, AstNode};
7+
use syntax::AstNode;
88
use test_utils::mark;
99

1010
use crate::{
11-
render::{render_resolution, RenderContext},
11+
render::{render_resolution_with_import, RenderContext},
1212
CompletionContext, Completions,
1313
};
1414

@@ -95,35 +95,13 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
9595
)),
9696
})
9797
.filter(|(mod_path, _)| mod_path.len() > 1)
98-
.filter_map(|(mod_path, definition)| {
99-
let use_to_insert = mod_path_to_ast(&mod_path);
100-
let mut mod_path_without_last_segment = mod_path;
101-
let name_after_import = mod_path_without_last_segment.segments.pop()?.to_string();
102-
103-
let resolution_with_missing_import =
104-
render_resolution(RenderContext::new(ctx), name_after_import, &definition)?;
105-
let lookup_string = resolution_with_missing_import.lookup().to_owned();
106-
107-
let mut text_edits =
108-
resolution_with_missing_import.text_edit().to_owned().into_builder();
109-
let rewriter = insert_use(&import_scope, use_to_insert, ctx.config.merge);
110-
let old_ast = rewriter.rewrite_root()?;
111-
algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits);
112-
113-
let qualifier_string = mod_path_without_last_segment.to_string();
114-
let qualified_label = if qualifier_string.is_empty() {
115-
resolution_with_missing_import.label().to_owned()
116-
} else {
117-
format!("{}::{}", qualifier_string, resolution_with_missing_import.label())
118-
};
119-
120-
Some(
121-
resolution_with_missing_import
122-
.into_builder()
123-
.text_edit(text_edits.finish())
124-
.label(qualified_label)
125-
.lookup_by(lookup_string)
126-
.build(),
98+
.filter_map(|(import_path, definition)| {
99+
render_resolution_with_import(
100+
RenderContext::new(ctx),
101+
import_path.clone(),
102+
import_scope.clone(),
103+
ctx.config.merge,
104+
&definition,
127105
)
128106
})
129107
.take(20);

crates/completion/src/item.rs

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
33
use std::fmt;
44

5-
use hir::{Documentation, Mutability};
6-
use syntax::TextRange;
5+
use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour};
6+
use hir::{Documentation, ModPath, Mutability};
7+
use syntax::{algo, TextRange};
78
use text_edit::TextEdit;
89

910
use crate::config::SnippetCap;
@@ -200,25 +201,7 @@ impl CompletionItem {
200201
trigger_call_info: None,
201202
score: None,
202203
ref_match: None,
203-
}
204-
}
205-
206-
pub(crate) fn into_builder(self) -> Builder {
207-
Builder {
208-
source_range: self.source_range,
209-
completion_kind: self.completion_kind,
210-
label: self.label,
211-
insert_text: None,
212-
insert_text_format: self.insert_text_format,
213-
detail: self.detail,
214-
documentation: self.documentation,
215-
lookup: self.lookup,
216-
kind: self.kind,
217-
text_edit: Some(self.text_edit),
218-
deprecated: Some(self.deprecated),
219-
trigger_call_info: Some(self.trigger_call_info),
220-
score: self.score,
221-
ref_match: self.ref_match,
204+
import_data: None,
222205
}
223206
}
224207

@@ -278,6 +261,7 @@ impl CompletionItem {
278261
pub(crate) struct Builder {
279262
source_range: TextRange,
280263
completion_kind: CompletionKind,
264+
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
281265
label: String,
282266
insert_text: Option<String>,
283267
insert_text_format: InsertTextFormat,
@@ -294,23 +278,50 @@ pub(crate) struct Builder {
294278

295279
impl Builder {
296280
pub(crate) fn build(self) -> CompletionItem {
297-
let label = self.label;
298-
let text_edit = match self.text_edit {
281+
let mut label = self.label;
282+
let mut lookup = self.lookup;
283+
let mut insert_text = self.insert_text;
284+
let mut text_edits = TextEdit::builder();
285+
286+
if let Some((import_path, import_scope, merge_behaviour)) = self.import_data {
287+
let import = mod_path_to_ast(&import_path);
288+
let mut import_path_without_last_segment = import_path;
289+
let _ = import_path_without_last_segment.segments.pop();
290+
291+
if !import_path_without_last_segment.segments.is_empty() {
292+
if lookup.is_none() {
293+
lookup = Some(label.clone());
294+
}
295+
if insert_text.is_none() {
296+
insert_text = Some(label.clone());
297+
}
298+
label = format!("{}::{}", import_path_without_last_segment, label);
299+
}
300+
301+
let rewriter = insert_use(&import_scope, import, merge_behaviour);
302+
if let Some(old_ast) = rewriter.rewrite_root() {
303+
algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits);
304+
}
305+
}
306+
307+
let original_edit = match self.text_edit {
299308
Some(it) => it,
300-
None => TextEdit::replace(
301-
self.source_range,
302-
self.insert_text.unwrap_or_else(|| label.clone()),
303-
),
309+
None => {
310+
TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone()))
311+
}
304312
};
305313

314+
let mut resulting_edit = text_edits.finish();
315+
resulting_edit.union(original_edit).expect("Failed to unite text edits");
316+
306317
CompletionItem {
307318
source_range: self.source_range,
308319
label,
309320
insert_text_format: self.insert_text_format,
310-
text_edit,
321+
text_edit: resulting_edit,
311322
detail: self.detail,
312323
documentation: self.documentation,
313-
lookup: self.lookup,
324+
lookup,
314325
kind: self.kind,
315326
completion_kind: self.completion_kind,
316327
deprecated: self.deprecated.unwrap_or(false),
@@ -379,6 +390,13 @@ impl Builder {
379390
self.trigger_call_info = Some(true);
380391
self
381392
}
393+
pub(crate) fn import_data(
394+
mut self,
395+
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
396+
) -> Builder {
397+
self.import_data = import_data;
398+
self
399+
}
382400
pub(crate) fn set_ref_match(
383401
mut self,
384402
ref_match: Option<(Mutability, CompletionScore)>,

crates/completion/src/render.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ pub(crate) mod type_alias;
99

1010
mod builder_ext;
1111

12-
use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type};
12+
use assists::utils::{ImportScope, MergeBehaviour};
13+
use hir::{Documentation, HasAttrs, HirDisplay, ModPath, Mutability, ScopeDef, Type};
1314
use ide_db::RootDatabase;
1415
use syntax::TextRange;
1516
use test_utils::mark;
@@ -42,7 +43,22 @@ pub(crate) fn render_resolution<'a>(
4243
local_name: String,
4344
resolution: &ScopeDef,
4445
) -> Option<CompletionItem> {
45-
Render::new(ctx).render_resolution(local_name, resolution)
46+
Render::new(ctx).render_resolution(local_name, None, resolution)
47+
}
48+
49+
pub(crate) fn render_resolution_with_import<'a>(
50+
ctx: RenderContext<'a>,
51+
import: ModPath,
52+
import_scope: ImportScope,
53+
merge_behaviour: Option<MergeBehaviour>,
54+
resolution: &ScopeDef,
55+
) -> Option<CompletionItem> {
56+
let local_name = import.segments.last()?.to_string();
57+
Render::new(ctx).render_resolution(
58+
local_name,
59+
Some((import, import_scope, merge_behaviour)),
60+
resolution,
61+
)
4662
}
4763

4864
/// Interface for data and methods required for items rendering.
@@ -131,6 +147,7 @@ impl<'a> Render<'a> {
131147
fn render_resolution(
132148
self,
133149
local_name: String,
150+
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
134151
resolution: &ScopeDef,
135152
) -> Option<CompletionItem> {
136153
use hir::ModuleDef::*;
@@ -142,15 +159,15 @@ impl<'a> Render<'a> {
142159

143160
let kind = match resolution {
144161
ScopeDef::ModuleDef(Function(func)) => {
145-
let item = render_fn(self.ctx, Some(local_name), *func);
162+
let item = render_fn(self.ctx, import_data, Some(local_name), *func);
146163
return Some(item);
147164
}
148165
ScopeDef::ModuleDef(EnumVariant(var)) => {
149-
let item = render_enum_variant(self.ctx, Some(local_name), *var, None);
166+
let item = render_enum_variant(self.ctx, import_data, Some(local_name), *var, None);
150167
return Some(item);
151168
}
152169
ScopeDef::MacroDef(mac) => {
153-
let item = render_macro(self.ctx, local_name, *mac);
170+
let item = render_macro(self.ctx, import_data, local_name, *mac);
154171
return item;
155172
}
156173

@@ -175,6 +192,7 @@ impl<'a> Render<'a> {
175192
local_name,
176193
)
177194
.kind(CompletionItemKind::UnresolvedReference)
195+
.import_data(import_data)
178196
.build();
179197
return Some(item);
180198
}
@@ -227,7 +245,12 @@ impl<'a> Render<'a> {
227245
}
228246
}
229247

230-
let item = item.kind(kind).set_documentation(docs).set_ref_match(ref_match).build();
248+
let item = item
249+
.kind(kind)
250+
.import_data(import_data)
251+
.set_documentation(docs)
252+
.set_ref_match(ref_match)
253+
.build();
231254
Some(item)
232255
}
233256

crates/completion/src/render/enum_variant.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Renderer for `enum` variants.
22
3+
use assists::utils::{ImportScope, MergeBehaviour};
34
use hir::{HasAttrs, HirDisplay, ModPath, StructKind};
45
use itertools::Itertools;
56
use test_utils::mark;
@@ -11,11 +12,12 @@ use crate::{
1112

1213
pub(crate) fn render_enum_variant<'a>(
1314
ctx: RenderContext<'a>,
15+
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
1416
local_name: Option<String>,
1517
variant: hir::EnumVariant,
1618
path: Option<ModPath>,
1719
) -> CompletionItem {
18-
EnumVariantRender::new(ctx, local_name, variant, path).render()
20+
EnumVariantRender::new(ctx, local_name, variant, path).render(import_data)
1921
}
2022

2123
#[derive(Debug)]
@@ -60,7 +62,10 @@ impl<'a> EnumVariantRender<'a> {
6062
}
6163
}
6264

63-
fn render(self) -> CompletionItem {
65+
fn render(
66+
self,
67+
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
68+
) -> CompletionItem {
6469
let mut builder = CompletionItem::new(
6570
CompletionKind::Reference,
6671
self.ctx.source_range(),
@@ -69,6 +74,7 @@ impl<'a> EnumVariantRender<'a> {
6974
.kind(CompletionItemKind::EnumVariant)
7075
.set_documentation(self.variant.docs(self.ctx.db()))
7176
.set_deprecated(self.ctx.is_deprecated(self.variant))
77+
.import_data(import_data)
7278
.detail(self.detail());
7379

7480
if self.variant_kind == StructKind::Tuple {

crates/completion/src/render/function.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Renderer for function calls.
22
3-
use hir::{HasSource, Type};
3+
use assists::utils::{ImportScope, MergeBehaviour};
4+
use hir::{HasSource, ModPath, Type};
45
use syntax::{ast::Fn, display::function_declaration};
56

67
use crate::{
@@ -10,10 +11,11 @@ use crate::{
1011

1112
pub(crate) fn render_fn<'a>(
1213
ctx: RenderContext<'a>,
14+
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
1315
local_name: Option<String>,
1416
fn_: hir::Function,
1517
) -> CompletionItem {
16-
FunctionRender::new(ctx, local_name, fn_).render()
18+
FunctionRender::new(ctx, local_name, fn_).render(import_data)
1719
}
1820

1921
#[derive(Debug)]
@@ -36,14 +38,18 @@ impl<'a> FunctionRender<'a> {
3638
FunctionRender { ctx, name, fn_, ast_node }
3739
}
3840

39-
fn render(self) -> CompletionItem {
41+
fn render(
42+
self,
43+
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
44+
) -> CompletionItem {
4045
let params = self.params();
4146
CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone())
4247
.kind(self.kind())
4348
.set_documentation(self.ctx.docs(self.fn_))
4449
.set_deprecated(self.ctx.is_deprecated(self.fn_))
4550
.detail(self.detail())
4651
.add_call_parens(self.ctx.completion, self.name, params)
52+
.import_data(import_data)
4753
.build()
4854
}
4955

0 commit comments

Comments
 (0)