Add MethodCall and FieldAccess variants to ImmediateLocation

This commit is contained in:
Lukas Wirth 2021-06-02 15:21:18 +02:00
parent dbdfeeeff9
commit 9271941a95
7 changed files with 81 additions and 49 deletions

View file

@ -7,7 +7,7 @@ use syntax::{
ast::{self, LoopBodyOwner},
match_ast, AstNode, Direction, SyntaxElement,
SyntaxKind::*,
SyntaxNode, SyntaxToken, TextSize, T,
SyntaxNode, SyntaxToken, TextRange, TextSize, T,
};
#[cfg(test)]
@ -37,6 +37,15 @@ pub(crate) enum ImmediateLocation {
// Fake file ast node
ModDeclaration(ast::Module),
// Original file ast node
MethodCall {
receiver: Option<ast::Expr>,
},
// Original file ast node
FieldAccess {
receiver: Option<ast::Expr>,
receiver_is_ambiguous_float_literal: bool,
},
// Original file ast node
/// The record expr of the field name we are completing
RecordExpr(ast::RecordExpr),
// Original file ast node
@ -164,12 +173,38 @@ pub(crate) fn determine_location(
Some(TRAIT) => ImmediateLocation::Trait,
_ => return None,
},
ast::Module(it) => if it.item_list().is_none() {
ast::Module(it) => {
if it.item_list().is_none() {
ImmediateLocation::ModDeclaration(it)
} else {
return None
return None;
}
},
ast::Attr(it) => ImmediateLocation::Attribute(it),
ast::FieldExpr(it) => {
let receiver = it
.expr()
.map(|e| e.syntax().text_range())
.and_then(|r| find_node_with_range(original_file, r));
let receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = &receiver {
match l.kind() {
ast::LiteralKind::FloatNumber { .. } => l.token().text().ends_with('.'),
_ => false,
}
} else {
false
};
ImmediateLocation::FieldAccess {
receiver,
receiver_is_ambiguous_float_literal,
}
},
ast::MethodCallExpr(it) => ImmediateLocation::MethodCall {
receiver: it
.receiver()
.map(|e| e.syntax().text_range())
.and_then(|r| find_node_with_range(original_file, r)),
},
_ => return None,
}
};
@ -194,6 +229,10 @@ fn maximize_name_ref(name_ref: &ast::NameRef) -> SyntaxNode {
name_ref.syntax().clone()
}
fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
syntax.covering_element(range).ancestors().find_map(N::cast)
}
pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
// Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`,
// where we only check the first parent with different text range.