method call scope

This commit is contained in:
Aleksey Kladov 2018-09-03 02:01:43 +03:00
parent fdd282ee0c
commit 58480b9190
4 changed files with 44 additions and 11 deletions

View file

@ -5,7 +5,7 @@ use std::{
use libsyntax2::{ use libsyntax2::{
SyntaxNodeRef, SyntaxNode, SmolStr, AstNode, SyntaxNodeRef, SyntaxNode, SmolStr, AstNode,
ast::{self, NameOwner, LoopBodyOwner}, ast::{self, NameOwner, LoopBodyOwner, ArgListOwner},
algo::{ancestors, generate, walk::preorder} 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) => { ast::Expr::CallExpr(e) => {
e.arg_list().into_iter() compute_call_scopes(e.expr(), e.arg_list(), scopes, scope);
.flat_map(|it| it.args()) }
.chain(e.expr()) ast::Expr::MethodCallExpr(e) => {
.for_each(|expr| compute_expr_scopes(expr, scopes, scope)); compute_call_scopes(e.expr(), e.arg_list(), scopes, scope);
} }
ast::Expr::MatchExpr(e) => { ast::Expr::MatchExpr(e) => {
if let Some(expr) = e.expr() { 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<ast::Expr>,
arg_list: Option<ast::ArgList>,
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<ScopeId> { fn compute_cond_scopes(cond: ast::Condition, scopes: &mut FnScopes, scope: ScopeId) -> Option<ScopeId> {
if let Some(expr) = cond.expr() { if let Some(expr) = cond.expr() {
compute_expr_scopes(expr, scopes, scope); 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] #[test]
fn test_loop_scope() { fn test_loop_scope() {
do_check(r" do_check(r"

View file

@ -200,12 +200,10 @@ impl<'a> AstNode<'a> for CallExpr<'a> {
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
} }
impl<'a> ast::ArgListOwner<'a> for CallExpr<'a> {}
impl<'a> CallExpr<'a> {pub fn expr(self) -> Option<Expr<'a>> { impl<'a> CallExpr<'a> {pub fn expr(self) -> Option<Expr<'a>> {
super::child_opt(self) super::child_opt(self)
} }
pub fn arg_list(self) -> Option<ArgList<'a>> {
super::child_opt(self)
}
} }
// CastExpr // CastExpr
@ -934,7 +932,11 @@ impl<'a> AstNode<'a> for MethodCallExpr<'a> {
fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 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<Expr<'a>> {
super::child_opt(self)
}
}
// Module // Module
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]

View file

@ -26,6 +26,12 @@ pub trait LoopBodyOwner<'a>: AstNode<'a> {
} }
} }
pub trait ArgListOwner<'a>: AstNode<'a> {
fn arg_list(self) -> Option<ArgList<'a>> {
child_opt(self)
}
}
pub trait TypeParamsOwner<'a>: AstNode<'a> { pub trait TypeParamsOwner<'a>: AstNode<'a> {
fn type_param_list(self) -> Option<TypeParamList<'a>> { fn type_param_list(self) -> Option<TypeParamList<'a>> {
child_opt(self) child_opt(self)

View file

@ -388,10 +388,14 @@ Grammar(
"NamedFieldList": (), "NamedFieldList": (),
"NamedField": (), "NamedField": (),
"CallExpr": ( "CallExpr": (
options: [ "Expr", "ArgList" ] traits: ["ArgListOwner"],
options: [ "Expr" ],
),
"MethodCallExpr": (
traits: ["ArgListOwner"],
options: [ "Expr" ],
), ),
"IndexExpr": (), "IndexExpr": (),
"MethodCallExpr": (),
"FieldExpr": (), "FieldExpr": (),
"TryExpr": (), "TryExpr": (),
"CastExpr": (), "CastExpr": (),