aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/patterns.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/patterns.rs')
-rw-r--r--crates/ide_completion/src/patterns.rs49
1 files changed, 44 insertions, 5 deletions
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs
index 26516046b..080898aef 100644
--- a/crates/ide_completion/src/patterns.rs
+++ b/crates/ide_completion/src/patterns.rs
@@ -7,13 +7,13 @@ use syntax::{
7 ast::{self, LoopBodyOwner}, 7 ast::{self, LoopBodyOwner},
8 match_ast, AstNode, Direction, SyntaxElement, 8 match_ast, AstNode, Direction, SyntaxElement,
9 SyntaxKind::*, 9 SyntaxKind::*,
10 SyntaxNode, SyntaxToken, TextSize, T, 10 SyntaxNode, SyntaxToken, TextRange, TextSize, T,
11}; 11};
12 12
13#[cfg(test)] 13#[cfg(test)]
14use crate::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable}; 14use crate::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable};
15 15
16/// Direct parent container of the cursor position 16/// Immediate previous node to what we are completing.
17#[derive(Copy, Clone, Debug, PartialEq, Eq)] 17#[derive(Copy, Clone, Debug, PartialEq, Eq)]
18pub(crate) enum ImmediatePrevSibling { 18pub(crate) enum ImmediatePrevSibling {
19 IfExpr, 19 IfExpr,
@@ -21,7 +21,7 @@ pub(crate) enum ImmediatePrevSibling {
21 ImplDefType, 21 ImplDefType,
22} 22}
23 23
24/// Direct parent container of the cursor position 24/// Direct parent "thing" of what we are currently completing.
25#[derive(Clone, Debug, PartialEq, Eq)] 25#[derive(Clone, Debug, PartialEq, Eq)]
26pub(crate) enum ImmediateLocation { 26pub(crate) enum ImmediateLocation {
27 Use, 27 Use,
@@ -37,6 +37,15 @@ pub(crate) enum ImmediateLocation {
37 // Fake file ast node 37 // Fake file ast node
38 ModDeclaration(ast::Module), 38 ModDeclaration(ast::Module),
39 // Original file ast node 39 // Original file ast node
40 MethodCall {
41 receiver: Option<ast::Expr>,
42 },
43 // Original file ast node
44 FieldAccess {
45 receiver: Option<ast::Expr>,
46 receiver_is_ambiguous_float_literal: bool,
47 },
48 // Original file ast node
40 /// The record expr of the field name we are completing 49 /// The record expr of the field name we are completing
41 RecordExpr(ast::RecordExpr), 50 RecordExpr(ast::RecordExpr),
42 // Original file ast node 51 // Original file ast node
@@ -164,12 +173,38 @@ pub(crate) fn determine_location(
164 Some(TRAIT) => ImmediateLocation::Trait, 173 Some(TRAIT) => ImmediateLocation::Trait,
165 _ => return None, 174 _ => return None,
166 }, 175 },
167 ast::Module(it) => if it.item_list().is_none() { 176 ast::Module(it) => {
177 if it.item_list().is_none() {
168 ImmediateLocation::ModDeclaration(it) 178 ImmediateLocation::ModDeclaration(it)
169 } else { 179 } else {
170 return None 180 return None;
181 }
171 }, 182 },
172 ast::Attr(it) => ImmediateLocation::Attribute(it), 183 ast::Attr(it) => ImmediateLocation::Attribute(it),
184 ast::FieldExpr(it) => {
185 let receiver = it
186 .expr()
187 .map(|e| e.syntax().text_range())
188 .and_then(|r| find_node_with_range(original_file, r));
189 let receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = &receiver {
190 match l.kind() {
191 ast::LiteralKind::FloatNumber { .. } => l.token().text().ends_with('.'),
192 _ => false,
193 }
194 } else {
195 false
196 };
197 ImmediateLocation::FieldAccess {
198 receiver,
199 receiver_is_ambiguous_float_literal,
200 }
201 },
202 ast::MethodCallExpr(it) => ImmediateLocation::MethodCall {
203 receiver: it
204 .receiver()
205 .map(|e| e.syntax().text_range())
206 .and_then(|r| find_node_with_range(original_file, r)),
207 },
173 _ => return None, 208 _ => return None,
174 } 209 }
175 }; 210 };
@@ -194,6 +229,10 @@ fn maximize_name_ref(name_ref: &ast::NameRef) -> SyntaxNode {
194 name_ref.syntax().clone() 229 name_ref.syntax().clone()
195} 230}
196 231
232fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
233 syntax.covering_element(range).ancestors().find_map(N::cast)
234}
235
197pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool { 236pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
198 // Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`, 237 // Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`,
199 // where we only check the first parent with different text range. 238 // where we only check the first parent with different text range.