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.rs42
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)]
33pub(super) enum PathKind {
34 Expr,
35 Type,
36}
37
38#[derive(Debug)]
33pub(crate) struct PathCompletionContext { 39pub(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}