diff --git a/ast.c b/ast.c index ae28db4414..a3490823ae 100644 --- a/ast.c +++ b/ast.c @@ -814,6 +814,10 @@ node_locations(VALUE ast_value, const NODE *node) return rb_ary_new_from_args(2, location_new(nd_code_loc(node)), location_new(&RNODE_REDO(node)->keyword_loc)); + case NODE_RETURN: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_RETURN(node)->keyword_loc)); case NODE_UNDEF: return rb_ary_new_from_args(2, location_new(nd_code_loc(node)), diff --git a/node_dump.c b/node_dump.c index 8f30ed2dce..0555d11cdc 100644 --- a/node_dump.c +++ b/node_dump.c @@ -374,8 +374,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) ANN("return statement"); ANN("format: return [nd_stts]"); ANN("example: return 1"); - LAST_NODE; F_NODE(nd_stts, RNODE_RETURN, "value"); + LAST_NODE; + F_LOC(keyword_loc, RNODE_RETURN); return; case NODE_REDO: diff --git a/parse.y b/parse.y index 17d5749004..aa87d16a09 100644 --- a/parse.y +++ b/parse.y @@ -1103,7 +1103,7 @@ static rb_node_list_t *rb_node_list_new(struct parser_params *p, NODE *nd_head, static rb_node_list_t *rb_node_list_new2(struct parser_params *p, NODE *nd_head, long nd_alen, NODE *nd_next, const YYLTYPE *loc); static rb_node_zlist_t *rb_node_zlist_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_hash_t *rb_node_hash_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); -static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc); +static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc); static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc); static rb_node_lvar_t *rb_node_lvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc); static rb_node_dvar_t *rb_node_dvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc); @@ -1211,7 +1211,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_LIST2(h,l,n,loc) (NODE *)rb_node_list_new2(p,h,l,n,loc) #define NEW_ZLIST(loc) (NODE *)rb_node_zlist_new(p,loc) #define NEW_HASH(a,loc) (NODE *)rb_node_hash_new(p,a,loc) -#define NEW_RETURN(s,loc) (NODE *)rb_node_return_new(p,s,loc) +#define NEW_RETURN(s,loc,k_loc) (NODE *)rb_node_return_new(p,s,loc,k_loc) #define NEW_YIELD(a,loc) (NODE *)rb_node_yield_new(p,a,loc) #define NEW_LVAR(v,loc) (NODE *)rb_node_lvar_new(p,v,loc) #define NEW_DVAR(v,loc) (NODE *)rb_node_dvar_new(p,v,loc) @@ -3531,7 +3531,7 @@ command : fcall command_args %prec tLOWEST } | k_return call_args { - $$ = NEW_RETURN(ret_args(p, $2), &@$); + $$ = NEW_RETURN(ret_args(p, $2), &@$, &@1); /*% ripper: return!($:2) %*/ } | keyword_break call_args @@ -4457,7 +4457,7 @@ primary : literal } | k_return { - $$ = NEW_RETURN(0, &@$); + $$ = NEW_RETURN(0, &@$, &@1); /*% ripper: return0! %*/ } | k_yield '(' call_args rparen @@ -11511,10 +11511,11 @@ rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYP } static rb_node_return_t * -rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc) +rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc) { rb_node_return_t *n = NODE_NEWNODE(NODE_RETURN, rb_node_return_t, loc); n->nd_stts = nd_stts; + n->keyword_loc = *keyword_loc; return n; } diff --git a/rubyparser.h b/rubyparser.h index 6a016155bc..cfa881ac41 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -573,6 +573,7 @@ typedef struct RNode_RETURN { NODE node; struct RNode *nd_stts; + rb_code_location_t keyword_loc; } rb_node_return_t; typedef struct RNode_YIELD { diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index 06fb3c56c0..38c0d56a0f 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -1386,6 +1386,14 @@ dummy assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 11], [1, 7, 1, 11]]) end + def test_return_locations + node = ast_parse("return 1") + assert_locations(node.children[-1].locations, [[1, 0, 1, 8], [1, 0, 1, 6]]) + + node = ast_parse("return") + assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 0, 1, 6]]) + end + def test_unless_locations node = ast_parse("unless cond then 1 else 2 end") assert_locations(node.children[-1].locations, [[1, 0, 1, 29], [1, 0, 1, 6], [1, 12, 1, 16], [1, 26, 1, 29]])