diff options
author | Lukas Wirth <[email protected]> | 2021-06-07 11:29:46 +0100 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2021-06-07 13:08:05 +0100 |
commit | 4eabcb2c01209065a231e616ba646ba63f68f00d (patch) | |
tree | d07a0ccd1232a53d531c6c3eb00b6cf57f68a85c /crates/ide_completion/src/context.rs | |
parent | e475bcdcc671161cf97d86d116a834c540f75f7c (diff) |
Move more things into PathCompletionContext
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r-- | crates/ide_completion/src/context.rs | 71 |
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 { | |||
33 | pub(crate) struct PathCompletionContext { | 33 | pub(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 | } |