aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r--crates/ide_completion/src/context.rs65
1 files changed, 20 insertions, 45 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 7c46c815d..6f685c02f 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -78,11 +78,6 @@ pub(crate) struct CompletionContext<'a> {
78 pub(super) can_be_stmt: bool, 78 pub(super) can_be_stmt: bool,
79 /// `true` if we expect an expression at the cursor position. 79 /// `true` if we expect an expression at the cursor position.
80 pub(super) is_expr: bool, 80 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,
86 /// If this is a call (method or function) in particular, i.e. the () are already there. 81 /// If this is a call (method or function) in particular, i.e. the () are already there.
87 pub(super) is_call: bool, 82 pub(super) is_call: bool,
88 /// Like `is_call`, but for tuple patterns. 83 /// Like `is_call`, but for tuple patterns.
@@ -158,9 +153,6 @@ impl<'a> CompletionContext<'a> {
158 path_qual: None, 153 path_qual: None,
159 can_be_stmt: false, 154 can_be_stmt: false,
160 is_expr: false, 155 is_expr: false,
161 is_new_item: false,
162 dot_receiver: None,
163 dot_receiver_is_ambiguous_float_literal: false,
164 is_call: false, 156 is_call: false,
165 is_pattern_call: false, 157 is_pattern_call: false,
166 is_macro_call: false, 158 is_macro_call: false,
@@ -255,6 +247,22 @@ impl<'a> CompletionContext<'a> {
255 ) 247 )
256 } 248 }
257 249
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
258 pub(crate) fn expects_use_tree(&self) -> bool { 266 pub(crate) fn expects_use_tree(&self) -> bool {
259 matches!(self.completion_location, Some(ImmediateLocation::Use)) 267 matches!(self.completion_location, Some(ImmediateLocation::Use))
260 } 268 }
@@ -267,6 +275,7 @@ impl<'a> CompletionContext<'a> {
267 matches!(self.completion_location, Some(ImmediateLocation::ItemList)) 275 matches!(self.completion_location, Some(ImmediateLocation::ItemList))
268 } 276 }
269 277
278 // fn expects_value(&self) -> bool {
270 pub(crate) fn expects_expression(&self) -> bool { 279 pub(crate) fn expects_expression(&self) -> bool {
271 self.is_expr 280 self.is_expr
272 } 281 }
@@ -540,16 +549,7 @@ impl<'a> CompletionContext<'a> {
540 self.name_ref_syntax = 549 self.name_ref_syntax =
541 find_node_at_offset(original_file, name_ref.syntax().text_range().start()); 550 find_node_at_offset(original_file, name_ref.syntax().text_range().start());
542 551
543 let name_range = name_ref.syntax().text_range(); 552 if matches!(self.completion_location, Some(ImmediateLocation::ItemList)) {
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;
553 return; 553 return;
554 } 554 }
555 555
@@ -623,33 +623,8 @@ impl<'a> CompletionContext<'a> {
623 .unwrap_or(false); 623 .unwrap_or(false);
624 self.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some(); 624 self.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some();
625 } 625 }
626 626 self.is_call |=
627 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 627 matches!(self.completion_location, Some(ImmediateLocation::MethodCall { .. }));
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 }
653 } 628 }
654} 629}
655 630