Skip to content

Commit 9d73437

Browse files
bors[bot]Veykril
andauthored
Merge #9110
9110: internal: simplify r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
2 parents dbdfeee + 76fd1b3 commit 9d73437

File tree

9 files changed

+86
-66
lines changed

9 files changed

+86
-66
lines changed

crates/ide_completion/src/completions/dot.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{context::CompletionContext, Completions};
88

99
/// Complete dot accesses, i.e. fields or methods.
1010
pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
11-
let dot_receiver = match &ctx.dot_receiver {
11+
let dot_receiver = match ctx.dot_receiver() {
1212
Some(expr) => expr,
1313
_ => return complete_undotted_self(acc, ctx),
1414
};
@@ -30,7 +30,10 @@ pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
3030
}
3131

3232
fn complete_undotted_self(acc: &mut Completions, ctx: &CompletionContext) {
33-
if !ctx.is_trivial_path || !ctx.config.enable_self_on_the_fly {
33+
if !ctx.config.enable_self_on_the_fly {
34+
return;
35+
}
36+
if !ctx.is_trivial_path || ctx.is_path_disallowed() {
3437
return;
3538
}
3639
ctx.scope.process_all_names(&mut |name, def| {

crates/ide_completion/src/completions/flyimport.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,19 @@ pub(crate) fn position_for_import<'a>(
162162
Some(match import_candidate {
163163
Some(ImportCandidate::Path(_)) => ctx.name_ref_syntax.as_ref()?.syntax(),
164164
Some(ImportCandidate::TraitAssocItem(_)) => ctx.path_qual.as_ref()?.syntax(),
165-
Some(ImportCandidate::TraitMethod(_)) => ctx.dot_receiver.as_ref()?.syntax(),
165+
Some(ImportCandidate::TraitMethod(_)) => ctx.dot_receiver()?.syntax(),
166166
None => ctx
167167
.name_ref_syntax
168168
.as_ref()
169169
.map(|name_ref| name_ref.syntax())
170170
.or_else(|| ctx.path_qual.as_ref().map(|path| path.syntax()))
171-
.or_else(|| ctx.dot_receiver.as_ref().map(|expr| expr.syntax()))?,
171+
.or_else(|| ctx.dot_receiver().map(|expr| expr.syntax()))?,
172172
})
173173
}
174174

175175
fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
176176
let current_module = ctx.scope.module()?;
177-
if let Some(dot_receiver) = &ctx.dot_receiver {
177+
if let Some(dot_receiver) = ctx.dot_receiver() {
178178
ImportAssets::for_fuzzy_method_call(
179179
current_module,
180180
ctx.sema.type_of_expr(dot_receiver)?,

crates/ide_completion/src/completions/keyword.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
3131
}
3232

3333
// Suggest .await syntax for types that implement Future trait
34-
if let Some(receiver) = &ctx.dot_receiver {
34+
if let Some(receiver) = ctx.dot_receiver() {
3535
if let Some(ty) = ctx.sema.type_of_expr(receiver) {
3636
if ty.impls_future(ctx.db) {
3737
let mut item = kw_completion("await");

crates/ide_completion/src/completions/macro_in_item_position.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{CompletionContext, Completions};
55
// Ideally this should be removed and moved into `(un)qualified_path` respectively
66
pub(crate) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
77
// Show only macros in top level.
8-
if !ctx.is_new_item {
8+
if !ctx.expects_item() {
99
return;
1010
}
1111

crates/ide_completion/src/completions/postfix.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::{
1414
completions::postfix::format_like::add_format_like_completions,
1515
context::CompletionContext,
1616
item::{Builder, CompletionKind},
17+
patterns::ImmediateLocation,
1718
CompletionItem, CompletionItemKind, Completions,
1819
};
1920

@@ -22,13 +23,16 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
2223
return;
2324
}
2425

25-
let dot_receiver = match &ctx.dot_receiver {
26-
Some(it) => it,
27-
None => return,
26+
let (dot_receiver, receiver_is_ambiguous_float_literal) = match &ctx.completion_location {
27+
Some(ImmediateLocation::MethodCall { receiver: Some(it) }) => (it, false),
28+
Some(ImmediateLocation::FieldAccess {
29+
receiver: Some(it),
30+
receiver_is_ambiguous_float_literal,
31+
}) => (it, *receiver_is_ambiguous_float_literal),
32+
_ => return,
2833
};
2934

30-
let receiver_text =
31-
get_receiver_text(dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);
35+
let receiver_text = get_receiver_text(dot_receiver, receiver_is_ambiguous_float_literal);
3236

3337
let receiver_ty = match ctx.sema.type_of_expr(&dot_receiver) {
3438
Some(it) => it,
@@ -123,8 +127,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
123127
// The rest of the postfix completions create an expression that moves an argument,
124128
// so it's better to consider references now to avoid breaking the compilation
125129
let dot_receiver = include_references(dot_receiver);
126-
let receiver_text =
127-
get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);
130+
let receiver_text = get_receiver_text(&dot_receiver, receiver_is_ambiguous_float_literal);
128131

129132
match try_enum {
130133
Some(try_enum) => match try_enum {

crates/ide_completion/src/completions/snippet.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte
2929
}
3030

3131
pub(crate) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
32-
if !ctx.is_new_item {
32+
if !ctx.expects_item() {
3333
return;
3434
}
3535
let cap = match ctx.config.snippet_cap {

crates/ide_completion/src/context.rs

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,6 @@ pub(crate) struct CompletionContext<'a> {
7878
pub(super) can_be_stmt: bool,
7979
/// `true` if we expect an expression at the cursor position.
8080
pub(super) is_expr: bool,
81-
/// Something is typed at the "top" level, in module or impl/trait.
82-
pub(super) is_new_item: bool,
83-
/// The receiver if this is a field or method access, i.e. writing something.$0
84-
pub(super) dot_receiver: Option<ast::Expr>,
85-
pub(super) dot_receiver_is_ambiguous_float_literal: bool,
8681
/// If this is a call (method or function) in particular, i.e. the () are already there.
8782
pub(super) is_call: bool,
8883
/// Like `is_call`, but for tuple patterns.
@@ -158,9 +153,6 @@ impl<'a> CompletionContext<'a> {
158153
path_qual: None,
159154
can_be_stmt: false,
160155
is_expr: false,
161-
is_new_item: false,
162-
dot_receiver: None,
163-
dot_receiver_is_ambiguous_float_literal: false,
164156
is_call: false,
165157
is_pattern_call: false,
166158
is_macro_call: false,
@@ -255,6 +247,22 @@ impl<'a> CompletionContext<'a> {
255247
)
256248
}
257249

250+
pub(crate) fn has_dot_receiver(&self) -> bool {
251+
matches!(
252+
&self.completion_location,
253+
Some(ImmediateLocation::FieldAccess { receiver, .. }) | Some(ImmediateLocation::MethodCall { receiver })
254+
if receiver.is_some()
255+
)
256+
}
257+
258+
pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> {
259+
match &self.completion_location {
260+
Some(ImmediateLocation::MethodCall { receiver })
261+
| Some(ImmediateLocation::FieldAccess { receiver, .. }) => receiver.as_ref(),
262+
_ => None,
263+
}
264+
}
265+
258266
pub(crate) fn expects_use_tree(&self) -> bool {
259267
matches!(self.completion_location, Some(ImmediateLocation::Use))
260268
}
@@ -267,6 +275,7 @@ impl<'a> CompletionContext<'a> {
267275
matches!(self.completion_location, Some(ImmediateLocation::ItemList))
268276
}
269277

278+
// fn expects_value(&self) -> bool {
270279
pub(crate) fn expects_expression(&self) -> bool {
271280
self.is_expr
272281
}
@@ -540,16 +549,7 @@ impl<'a> CompletionContext<'a> {
540549
self.name_ref_syntax =
541550
find_node_at_offset(original_file, name_ref.syntax().text_range().start());
542551

543-
let name_range = name_ref.syntax().text_range();
544-
let top_node = name_ref
545-
.syntax()
546-
.ancestors()
547-
.take_while(|it| it.text_range() == name_range)
548-
.last()
549-
.unwrap();
550-
551-
if matches!(top_node.parent().map(|it| it.kind()), Some(SOURCE_FILE) | Some(ITEM_LIST)) {
552-
self.is_new_item = true;
552+
if matches!(self.completion_location, Some(ImmediateLocation::ItemList)) {
553553
return;
554554
}
555555

@@ -623,33 +623,8 @@ impl<'a> CompletionContext<'a> {
623623
.unwrap_or(false);
624624
self.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some();
625625
}
626-
627-
if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
628-
// The receiver comes before the point of insertion of the fake
629-
// ident, so it should have the same range in the non-modified file
630-
self.dot_receiver = field_expr
631-
.expr()
632-
.map(|e| e.syntax().text_range())
633-
.and_then(|r| find_node_with_range(original_file, r));
634-
self.dot_receiver_is_ambiguous_float_literal =
635-
if let Some(ast::Expr::Literal(l)) = &self.dot_receiver {
636-
match l.kind() {
637-
ast::LiteralKind::FloatNumber { .. } => l.token().text().ends_with('.'),
638-
_ => false,
639-
}
640-
} else {
641-
false
642-
};
643-
}
644-
645-
if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) {
646-
// As above
647-
self.dot_receiver = method_call_expr
648-
.receiver()
649-
.map(|e| e.syntax().text_range())
650-
.and_then(|r| find_node_with_range(original_file, r));
651-
self.is_call = true;
652-
}
626+
self.is_call |=
627+
matches!(self.completion_location, Some(ImmediateLocation::MethodCall { .. }));
653628
}
654629
}
655630

crates/ide_completion/src/patterns.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@ use syntax::{
77
ast::{self, LoopBodyOwner},
88
match_ast, AstNode, Direction, SyntaxElement,
99
SyntaxKind::*,
10-
SyntaxNode, SyntaxToken, TextSize, T,
10+
SyntaxNode, SyntaxToken, TextRange, TextSize, T,
1111
};
1212

1313
#[cfg(test)]
1414
use crate::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable};
1515

16-
/// Direct parent container of the cursor position
16+
/// Immediate previous node to what we are completing.
1717
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1818
pub(crate) enum ImmediatePrevSibling {
1919
IfExpr,
2020
TraitDefName,
2121
ImplDefType,
2222
}
2323

24-
/// Direct parent container of the cursor position
24+
/// Direct parent "thing" of what we are currently completing.
2525
#[derive(Clone, Debug, PartialEq, Eq)]
2626
pub(crate) enum ImmediateLocation {
2727
Use,
@@ -37,6 +37,15 @@ pub(crate) enum ImmediateLocation {
3737
// Fake file ast node
3838
ModDeclaration(ast::Module),
3939
// Original file ast node
40+
MethodCall {
41+
receiver: Option<ast::Expr>,
42+
},
43+
// Original file ast node
44+
FieldAccess {
45+
receiver: Option<ast::Expr>,
46+
receiver_is_ambiguous_float_literal: bool,
47+
},
48+
// Original file ast node
4049
/// The record expr of the field name we are completing
4150
RecordExpr(ast::RecordExpr),
4251
// Original file ast node
@@ -164,12 +173,38 @@ pub(crate) fn determine_location(
164173
Some(TRAIT) => ImmediateLocation::Trait,
165174
_ => return None,
166175
},
167-
ast::Module(it) => if it.item_list().is_none() {
176+
ast::Module(it) => {
177+
if it.item_list().is_none() {
168178
ImmediateLocation::ModDeclaration(it)
169179
} else {
170-
return None
180+
return None;
181+
}
171182
},
172183
ast::Attr(it) => ImmediateLocation::Attribute(it),
184+
ast::FieldExpr(it) => {
185+
let receiver = it
186+
.expr()
187+
.map(|e| e.syntax().text_range())
188+
.and_then(|r| find_node_with_range(original_file, r));
189+
let receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = &receiver {
190+
match l.kind() {
191+
ast::LiteralKind::FloatNumber { .. } => l.token().text().ends_with('.'),
192+
_ => false,
193+
}
194+
} else {
195+
false
196+
};
197+
ImmediateLocation::FieldAccess {
198+
receiver,
199+
receiver_is_ambiguous_float_literal,
200+
}
201+
},
202+
ast::MethodCallExpr(it) => ImmediateLocation::MethodCall {
203+
receiver: it
204+
.receiver()
205+
.map(|e| e.syntax().text_range())
206+
.and_then(|r| find_node_with_range(original_file, r)),
207+
},
173208
_ => return None,
174209
}
175210
};
@@ -194,6 +229,10 @@ fn maximize_name_ref(name_ref: &ast::NameRef) -> SyntaxNode {
194229
name_ref.syntax().clone()
195230
}
196231

232+
fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
233+
syntax.covering_element(range).ancestors().find_map(N::cast)
234+
}
235+
197236
pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
198237
// Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`,
199238
// where we only check the first parent with different text range.

crates/ide_completion/src/render/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ impl<'a> FunctionRender<'a> {
154154
};
155155

156156
let mut params_pats = Vec::new();
157-
let params_ty = if self.ctx.completion.dot_receiver.is_some() || self.receiver.is_some() {
157+
let params_ty = if self.ctx.completion.has_dot_receiver() || self.receiver.is_some() {
158158
self.func.method_params(self.ctx.db()).unwrap_or_default()
159159
} else {
160160
if let Some(s) = ast_params.self_param() {

0 commit comments

Comments
 (0)