diff options
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r-- | crates/ide_completion/src/context.rs | 65 |
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 | ||