Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/context/analysis.rs')
-rw-r--r--crates/ide-completion/src/context/analysis.rs82
1 files changed, 47 insertions, 35 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index f0a03dedfe..c01b544ff6 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -891,44 +891,53 @@ fn classify_name_ref<'db>(
return Some(make_res(kind));
}
+ let field_expr_handle = |recviver, node| {
+ let receiver = find_opt_node_in_file(original_file, recviver);
+ let receiver_is_ambiguous_float_literal = match &receiver {
+ Some(ast::Expr::Literal(l)) => matches! {
+ l.kind(),
+ ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().is_some_and(|it| it.text().ends_with('.'))
+ },
+ _ => false,
+ };
+
+ let receiver_is_part_of_indivisible_expression = match &receiver {
+ Some(ast::Expr::IfExpr(_)) => {
+ let next_token_kind =
+ next_non_trivia_token(name_ref.syntax().clone()).map(|t| t.kind());
+ next_token_kind == Some(SyntaxKind::ELSE_KW)
+ }
+ _ => false,
+ };
+ if receiver_is_part_of_indivisible_expression {
+ return None;
+ }
+
+ let mut receiver_ty = receiver.as_ref().and_then(|it| sema.type_of_expr(it));
+ if receiver_is_ambiguous_float_literal {
+ // `123.|` is parsed as a float but should actually be an integer.
+ always!(receiver_ty.as_ref().is_none_or(|receiver_ty| receiver_ty.original.is_float()));
+ receiver_ty =
+ Some(TypeInfo { original: hir::BuiltinType::i32().ty(sema.db), adjusted: None });
+ }
+
+ let kind = NameRefKind::DotAccess(DotAccess {
+ receiver_ty,
+ kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
+ receiver,
+ ctx: DotAccessExprCtx {
+ in_block_expr: is_in_block(node),
+ in_breakable: is_in_breakable(node).unzip().0,
+ },
+ });
+ Some(make_res(kind))
+ };
+
let segment = match_ast! {
match parent {
ast::PathSegment(segment) => segment,
ast::FieldExpr(field) => {
- let receiver = find_opt_node_in_file(original_file, field.expr());
- let receiver_is_ambiguous_float_literal = match &receiver {
- Some(ast::Expr::Literal(l)) => matches! {
- l.kind(),
- ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().is_some_and(|it| it.text().ends_with('.'))
- },
- _ => false,
- };
-
- let receiver_is_part_of_indivisible_expression = match &receiver {
- Some(ast::Expr::IfExpr(_)) => {
- let next_token_kind = next_non_trivia_token(name_ref.syntax().clone()).map(|t| t.kind());
- next_token_kind == Some(SyntaxKind::ELSE_KW)
- },
- _ => false
- };
- if receiver_is_part_of_indivisible_expression {
- return None;
- }
-
- let mut receiver_ty = receiver.as_ref().and_then(|it| sema.type_of_expr(it));
- if receiver_is_ambiguous_float_literal {
- // `123.|` is parsed as a float but should actually be an integer.
- always!(receiver_ty.as_ref().is_none_or(|receiver_ty| receiver_ty.original.is_float()));
- receiver_ty = Some(TypeInfo { original: hir::BuiltinType::i32().ty(sema.db), adjusted: None });
- }
-
- let kind = NameRefKind::DotAccess(DotAccess {
- receiver_ty,
- kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
- receiver,
- ctx: DotAccessExprCtx { in_block_expr: is_in_block(field.syntax()), in_breakable: is_in_breakable(field.syntax()).unzip().0 }
- });
- return Some(make_res(kind));
+ return field_expr_handle(field.expr(), field.syntax());
},
ast::ExternCrate(_) => {
let kind = NameRefKind::ExternCrate;
@@ -937,9 +946,12 @@ fn classify_name_ref<'db>(
ast::MethodCallExpr(method) => {
let receiver = find_opt_node_in_file(original_file, method.receiver());
let has_parens = has_parens(&method);
+ if !has_parens && let Some(res) = field_expr_handle(method.receiver(), method.syntax()) {
+ return Some(res)
+ }
let kind = NameRefKind::DotAccess(DotAccess {
receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
- kind: DotAccessKind::Method { has_parens },
+ kind: DotAccessKind::Method,
receiver,
ctx: DotAccessExprCtx { in_block_expr: is_in_block(method.syntax()), in_breakable: is_in_breakable(method.syntax()).unzip().0 }
});