aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/context.rs
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-06-07 11:29:46 +0100
committerLukas Wirth <[email protected]>2021-06-07 13:08:05 +0100
commit4eabcb2c01209065a231e616ba646ba63f68f00d (patch)
treed07a0ccd1232a53d531c6c3eb00b6cf57f68a85c /crates/ide_completion/src/context.rs
parente475bcdcc671161cf97d86d116a834c540f75f7c (diff)
Move more things into PathCompletionContext
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r--crates/ide_completion/src/context.rs71
1 files changed, 41 insertions, 30 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 6bd67c123..20e033d31 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -33,6 +33,16 @@ pub(crate) enum PatternRefutability {
33pub(crate) struct PathCompletionContext { 33pub(crate) struct PathCompletionContext {
34 /// If this is a call with () already there 34 /// If this is a call with () already there
35 call_kind: Option<CallKind>, 35 call_kind: Option<CallKind>,
36 /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
37 pub(super) is_trivial_path: bool,
38 /// If not a trivial path, the prefix (qualifier).
39 pub(super) path_qual: Option<ast::Path>,
40 pub(super) is_path_type: bool,
41 pub(super) has_type_args: bool,
42 /// `true` if we are a statement or a last expr in the block.
43 pub(super) can_be_stmt: bool,
44 /// `true` if we expect an expression at the cursor position.
45 pub(super) is_expr: bool,
36} 46}
37 47
38#[derive(Copy, Clone, Debug, PartialEq, Eq)] 48#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -83,16 +93,6 @@ pub(crate) struct CompletionContext<'a> {
83 pub(super) path_context: Option<PathCompletionContext>, 93 pub(super) path_context: Option<PathCompletionContext>,
84 /// FIXME: `ActiveParameter` is string-based, which is very very wrong 94 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
85 pub(super) active_parameter: Option<ActiveParameter>, 95 pub(super) active_parameter: Option<ActiveParameter>,
86 /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
87 pub(super) is_trivial_path: bool,
88 /// If not a trivial path, the prefix (qualifier).
89 pub(super) path_qual: Option<ast::Path>,
90 /// `true` if we are a statement or a last expr in the block.
91 pub(super) can_be_stmt: bool,
92 /// `true` if we expect an expression at the cursor position.
93 pub(super) is_expr: bool,
94 pub(super) is_path_type: bool,
95 pub(super) has_type_args: bool,
96 pub(super) locals: Vec<(String, Local)>, 96 pub(super) locals: Vec<(String, Local)>,
97 97
98 pub(super) previous_token: Option<SyntaxToken>, 98 pub(super) previous_token: Option<SyntaxToken>,
@@ -156,13 +156,7 @@ impl<'a> CompletionContext<'a> {
156 is_label_ref: false, 156 is_label_ref: false,
157 is_param: false, 157 is_param: false,
158 is_pat_or_const: None, 158 is_pat_or_const: None,
159 is_trivial_path: false,
160 path_qual: None,
161 can_be_stmt: false,
162 is_expr: false,
163 path_context: None, 159 path_context: None,
164 is_path_type: false,
165 has_type_args: false,
166 previous_token: None, 160 previous_token: None,
167 in_loop_body: false, 161 in_loop_body: false,
168 completion_location: None, 162 completion_location: None,
@@ -280,11 +274,6 @@ impl<'a> CompletionContext<'a> {
280 matches!(self.completion_location, Some(ImmediateLocation::ItemList)) 274 matches!(self.completion_location, Some(ImmediateLocation::ItemList))
281 } 275 }
282 276
283 // fn expects_value(&self) -> bool {
284 pub(crate) fn expects_expression(&self) -> bool {
285 self.is_expr
286 }
287
288 pub(crate) fn has_block_expr_parent(&self) -> bool { 277 pub(crate) fn has_block_expr_parent(&self) -> bool {
289 matches!(self.completion_location, Some(ImmediateLocation::BlockExpr)) 278 matches!(self.completion_location, Some(ImmediateLocation::BlockExpr))
290 } 279 }
@@ -321,10 +310,26 @@ impl<'a> CompletionContext<'a> {
321 ) || self.attribute_under_caret.is_some() 310 ) || self.attribute_under_caret.is_some()
322 } 311 }
323 312
313 pub(crate) fn expects_expression(&self) -> bool {
314 self.path_context.as_ref().map_or(false, |it| it.is_expr)
315 }
316
324 pub(crate) fn path_call_kind(&self) -> Option<CallKind> { 317 pub(crate) fn path_call_kind(&self) -> Option<CallKind> {
325 self.path_context.as_ref().and_then(|it| it.call_kind) 318 self.path_context.as_ref().and_then(|it| it.call_kind)
326 } 319 }
327 320
321 pub(crate) fn is_trivial_path(&self) -> bool {
322 self.path_context.as_ref().map_or(false, |it| it.is_trivial_path)
323 }
324
325 pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
326 self.path_context.as_ref().and_then(|it| it.path_qual.as_ref())
327 }
328
329 pub(crate) fn can_be_stmt(&self) -> bool {
330 self.path_context.as_ref().map_or(false, |it| it.can_be_stmt)
331 }
332
328 fn fill_impl_def(&mut self) { 333 fn fill_impl_def(&mut self) {
329 self.impl_def = self 334 self.impl_def = self
330 .sema 335 .sema
@@ -577,7 +582,15 @@ impl<'a> CompletionContext<'a> {
577 }; 582 };
578 583
579 if let Some(segment) = ast::PathSegment::cast(parent) { 584 if let Some(segment) = ast::PathSegment::cast(parent) {
580 let mut path_ctx = PathCompletionContext { call_kind: None }; 585 let path_ctx = self.path_context.get_or_insert(PathCompletionContext {
586 call_kind: None,
587 is_trivial_path: false,
588 path_qual: None,
589 has_type_args: false,
590 is_path_type: false,
591 can_be_stmt: false,
592 is_expr: false,
593 });
581 let path = segment.parent_path(); 594 let path = segment.parent_path();
582 595
583 if let Some(p) = path.syntax().parent() { 596 if let Some(p) = path.syntax().parent() {
@@ -590,13 +603,11 @@ impl<'a> CompletionContext<'a> {
590 } 603 }
591 }; 604 };
592 } 605 }
593 self.path_context = Some(path_ctx); 606 path_ctx.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
594 dbg!(&self.path_context); 607 path_ctx.has_type_args = segment.generic_arg_list().is_some();
595 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
596 self.has_type_args = segment.generic_arg_list().is_some();
597 608
598 if let Some(path) = path_or_use_tree_qualifier(&path) { 609 if let Some(path) = path_or_use_tree_qualifier(&path) {
599 self.path_qual = path 610 path_ctx.path_qual = path
600 .segment() 611 .segment()
601 .and_then(|it| { 612 .and_then(|it| {
602 find_node_with_range::<ast::PathSegment>( 613 find_node_with_range::<ast::PathSegment>(
@@ -614,11 +625,11 @@ impl<'a> CompletionContext<'a> {
614 } 625 }
615 } 626 }
616 627
617 self.is_trivial_path = true; 628 path_ctx.is_trivial_path = true;
618 629
619 // Find either enclosing expr statement (thing with `;`) or a 630 // Find either enclosing expr statement (thing with `;`) or a
620 // block. If block, check that we are the last expr. 631 // block. If block, check that we are the last expr.
621 self.can_be_stmt = name_ref 632 path_ctx.can_be_stmt = name_ref
622 .syntax() 633 .syntax()
623 .ancestors() 634 .ancestors()
624 .find_map(|node| { 635 .find_map(|node| {
@@ -634,7 +645,7 @@ impl<'a> CompletionContext<'a> {
634 None 645 None
635 }) 646 })
636 .unwrap_or(false); 647 .unwrap_or(false);
637 self.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some(); 648 path_ctx.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some();
638 } 649 }
639 } 650 }
640} 651}