diff options
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r-- | crates/ide_completion/src/context.rs | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 6177caa12..2c2a4aa6b 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -30,19 +30,24 @@ pub(crate) enum PatternRefutability { | |||
30 | } | 30 | } |
31 | 31 | ||
32 | #[derive(Debug)] | 32 | #[derive(Debug)] |
33 | pub(super) enum PathKind { | ||
34 | Expr, | ||
35 | Type, | ||
36 | } | ||
37 | |||
38 | #[derive(Debug)] | ||
33 | pub(crate) struct PathCompletionContext { | 39 | pub(crate) struct PathCompletionContext { |
34 | /// If this is a call with () already there | 40 | /// If this is a call with () already there |
35 | call_kind: Option<CallKind>, | 41 | call_kind: Option<CallKind>, |
36 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. | 42 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. |
37 | pub(super) is_trivial_path: bool, | 43 | pub(super) is_trivial_path: bool, |
38 | /// If not a trivial path, the prefix (qualifier). | 44 | /// If not a trivial path, the prefix (qualifier). |
39 | pub(super) path_qual: Option<ast::Path>, | 45 | pub(super) qualifier: Option<ast::Path>, |
40 | pub(super) is_path_type: bool, | 46 | pub(super) kind: Option<PathKind>, |
47 | /// Whether the path segment has type args or not. | ||
41 | pub(super) has_type_args: bool, | 48 | pub(super) has_type_args: bool, |
42 | /// `true` if we are a statement or a last expr in the block. | 49 | /// `true` if we are a statement or a last expr in the block. |
43 | pub(super) can_be_stmt: bool, | 50 | pub(super) can_be_stmt: bool, |
44 | /// `true` if we expect an expression at the cursor position. | ||
45 | pub(super) is_expr: bool, | ||
46 | pub(super) in_loop_body: bool, | 51 | pub(super) in_loop_body: bool, |
47 | } | 52 | } |
48 | 53 | ||
@@ -308,7 +313,11 @@ impl<'a> CompletionContext<'a> { | |||
308 | } | 313 | } |
309 | 314 | ||
310 | pub(crate) fn expects_expression(&self) -> bool { | 315 | pub(crate) fn expects_expression(&self) -> bool { |
311 | self.path_context.as_ref().map_or(false, |it| it.is_expr) | 316 | matches!(self.path_context, Some(PathCompletionContext { kind: Some(PathKind::Expr), .. })) |
317 | } | ||
318 | |||
319 | pub(crate) fn expects_type(&self) -> bool { | ||
320 | matches!(self.path_context, Some(PathCompletionContext { kind: Some(PathKind::Type), .. })) | ||
312 | } | 321 | } |
313 | 322 | ||
314 | pub(crate) fn path_call_kind(&self) -> Option<CallKind> { | 323 | pub(crate) fn path_call_kind(&self) -> Option<CallKind> { |
@@ -316,11 +325,11 @@ impl<'a> CompletionContext<'a> { | |||
316 | } | 325 | } |
317 | 326 | ||
318 | pub(crate) fn is_trivial_path(&self) -> bool { | 327 | pub(crate) fn is_trivial_path(&self) -> bool { |
319 | self.path_context.as_ref().map_or(false, |it| it.is_trivial_path) | 328 | matches!(self.path_context, Some(PathCompletionContext { is_trivial_path: true, .. })) |
320 | } | 329 | } |
321 | 330 | ||
322 | pub(crate) fn path_qual(&self) -> Option<&ast::Path> { | 331 | pub(crate) fn path_qual(&self) -> Option<&ast::Path> { |
323 | self.path_context.as_ref().and_then(|it| it.path_qual.as_ref()) | 332 | self.path_context.as_ref().and_then(|it| it.qualifier.as_ref()) |
324 | } | 333 | } |
325 | 334 | ||
326 | fn fill_impl_def(&mut self) { | 335 | fn fill_impl_def(&mut self) { |
@@ -573,12 +582,11 @@ impl<'a> CompletionContext<'a> { | |||
573 | let path_ctx = self.path_context.get_or_insert(PathCompletionContext { | 582 | let path_ctx = self.path_context.get_or_insert(PathCompletionContext { |
574 | call_kind: None, | 583 | call_kind: None, |
575 | is_trivial_path: false, | 584 | is_trivial_path: false, |
576 | path_qual: None, | 585 | qualifier: None, |
577 | has_type_args: false, | 586 | has_type_args: false, |
578 | is_path_type: false, | ||
579 | can_be_stmt: false, | 587 | can_be_stmt: false, |
580 | is_expr: false, | ||
581 | in_loop_body: false, | 588 | in_loop_body: false, |
589 | kind: None, | ||
582 | }); | 590 | }); |
583 | path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax()); | 591 | path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax()); |
584 | let path = segment.parent_path(); | 592 | let path = segment.parent_path(); |
@@ -593,11 +601,20 @@ impl<'a> CompletionContext<'a> { | |||
593 | } | 601 | } |
594 | }; | 602 | }; |
595 | } | 603 | } |
596 | path_ctx.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | 604 | |
605 | if let Some(parent) = path.syntax().parent() { | ||
606 | path_ctx.kind = match_ast! { | ||
607 | match parent { | ||
608 | ast::PathType(_it) => Some(PathKind::Type), | ||
609 | ast::PathExpr(_it) => Some(PathKind::Expr), | ||
610 | _ => None, | ||
611 | } | ||
612 | }; | ||
613 | } | ||
597 | path_ctx.has_type_args = segment.generic_arg_list().is_some(); | 614 | path_ctx.has_type_args = segment.generic_arg_list().is_some(); |
598 | 615 | ||
599 | if let Some(path) = path_or_use_tree_qualifier(&path) { | 616 | if let Some(path) = path_or_use_tree_qualifier(&path) { |
600 | path_ctx.path_qual = path | 617 | path_ctx.qualifier = path |
601 | .segment() | 618 | .segment() |
602 | .and_then(|it| { | 619 | .and_then(|it| { |
603 | find_node_with_range::<ast::PathSegment>( | 620 | find_node_with_range::<ast::PathSegment>( |
@@ -635,7 +652,6 @@ impl<'a> CompletionContext<'a> { | |||
635 | None | 652 | None |
636 | }) | 653 | }) |
637 | .unwrap_or(false); | 654 | .unwrap_or(false); |
638 | path_ctx.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some(); | ||
639 | } | 655 | } |
640 | } | 656 | } |
641 | } | 657 | } |