diff --git a/crates/libeditor/src/scope/fn_scope.rs b/crates/libeditor/src/scope/fn_scope.rs index abc8d34e77..60b8ce919f 100644 --- a/crates/libeditor/src/scope/fn_scope.rs +++ b/crates/libeditor/src/scope/fn_scope.rs @@ -5,7 +5,7 @@ use std::{ use libsyntax2::{ SyntaxNodeRef, SyntaxNode, SmolStr, AstNode, - ast::{self, NameOwner, LoopBodyOwner}, + ast::{self, NameOwner, LoopBodyOwner, ArgListOwner}, algo::{ancestors, generate, walk::preorder} }; @@ -184,10 +184,10 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { } } ast::Expr::CallExpr(e) => { - e.arg_list().into_iter() - .flat_map(|it| it.args()) - .chain(e.expr()) - .for_each(|expr| compute_expr_scopes(expr, scopes, scope)); + compute_call_scopes(e.expr(), e.arg_list(), scopes, scope); + } + ast::Expr::MethodCallExpr(e) => { + compute_call_scopes(e.expr(), e.arg_list(), scopes, scope); } ast::Expr::MatchExpr(e) => { if let Some(expr) = e.expr() { @@ -210,6 +210,17 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { } }; + fn compute_call_scopes( + receiver: Option, + arg_list: Option, + scopes: &mut FnScopes, scope: ScopeId, + ) { + arg_list.into_iter() + .flat_map(|it| it.args()) + .chain(receiver) + .for_each(|expr| compute_expr_scopes(expr, scopes, scope)); + } + fn compute_cond_scopes(cond: ast::Condition, scopes: &mut FnScopes, scope: ScopeId) -> Option { if let Some(expr) = cond.expr() { compute_expr_scopes(expr, scopes, scope); @@ -279,6 +290,16 @@ mod tests { ); } + #[test] + fn test_metod_call_scope() { + do_check(r" + fn quux() { + z.f(|x| <|> ); + }", + &["x"], + ); + } + #[test] fn test_loop_scope() { do_check(r" diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index bdee635ae5..11306a835f 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs @@ -200,12 +200,10 @@ impl<'a> AstNode<'a> for CallExpr<'a> { fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } } +impl<'a> ast::ArgListOwner<'a> for CallExpr<'a> {} impl<'a> CallExpr<'a> {pub fn expr(self) -> Option> { super::child_opt(self) } -pub fn arg_list(self) -> Option> { - super::child_opt(self) - } } // CastExpr @@ -934,7 +932,11 @@ impl<'a> AstNode<'a> for MethodCallExpr<'a> { fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } } -impl<'a> MethodCallExpr<'a> {} +impl<'a> ast::ArgListOwner<'a> for MethodCallExpr<'a> {} +impl<'a> MethodCallExpr<'a> {pub fn expr(self) -> Option> { + super::child_opt(self) + } +} // Module #[derive(Debug, Clone, Copy)] diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs index 49e283f5e4..274996171c 100644 --- a/crates/libsyntax2/src/ast/mod.rs +++ b/crates/libsyntax2/src/ast/mod.rs @@ -26,6 +26,12 @@ pub trait LoopBodyOwner<'a>: AstNode<'a> { } } +pub trait ArgListOwner<'a>: AstNode<'a> { + fn arg_list(self) -> Option> { + child_opt(self) + } +} + pub trait TypeParamsOwner<'a>: AstNode<'a> { fn type_param_list(self) -> Option> { child_opt(self) diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index 798725f7e4..683623a5dc 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron @@ -388,10 +388,14 @@ Grammar( "NamedFieldList": (), "NamedField": (), "CallExpr": ( - options: [ "Expr", "ArgList" ] + traits: ["ArgListOwner"], + options: [ "Expr" ], + ), + "MethodCallExpr": ( + traits: ["ArgListOwner"], + options: [ "Expr" ], ), "IndexExpr": (), - "MethodCallExpr": (), "FieldExpr": (), "TryExpr": (), "CastExpr": (),