diff --git a/ast.c b/ast.c index 67d121e1ce..031031af95 100644 --- a/ast.c +++ b/ast.c @@ -801,6 +801,11 @@ node_locations(VALUE ast_value, const NODE *node) return rb_ary_new_from_args(2, location_new(nd_code_loc(node)), location_new(&RNODE_VALIAS(node)->keyword_loc)); + case NODE_WHEN: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_WHEN(node)->keyword_loc), + location_new(&RNODE_WHEN(node)->then_keyword_loc)); case NODE_ARGS_AUX: case NODE_LAST: break; diff --git a/node_dump.c b/node_dump.c index ae948eb66e..d97a400a97 100644 --- a/node_dump.c +++ b/node_dump.c @@ -289,6 +289,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) F_NODE(nd_body, RNODE_WHEN, "when body"); LAST_NODE; F_NODE(nd_next, RNODE_WHEN, "next when clause"); + F_LOC(keyword_loc, RNODE_WHEN); + LAST_NODE; + F_LOC(then_keyword_loc, RNODE_WHEN); return; case NODE_IN: diff --git a/parse.y b/parse.y index 42396094be..d78d4586f8 100644 --- a/parse.y +++ b/parse.y @@ -1066,7 +1066,7 @@ static rb_node_unless_t *rb_node_unless_new(struct parser_params *p, NODE *nd_co static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc); static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc); -static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); +static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc); static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc); static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc); @@ -1174,7 +1174,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_CASE(h,b,loc) (NODE *)rb_node_case_new(p,h,b,loc) #define NEW_CASE2(b,loc) (NODE *)rb_node_case2_new(p,b,loc) #define NEW_CASE3(h,b,loc) (NODE *)rb_node_case3_new(p,h,b,loc) -#define NEW_WHEN(c,t,e,loc) (NODE *)rb_node_when_new(p,c,t,e,loc) +#define NEW_WHEN(c,t,e,loc,k_loc,t_loc) (NODE *)rb_node_when_new(p,c,t,e,loc,k_loc,t_loc) #define NEW_IN(c,t,e,loc) (NODE *)rb_node_in_new(p,c,t,e,loc) #define NEW_WHILE(c,b,n,loc) (NODE *)rb_node_while_new(p,c,b,n,loc) #define NEW_UNTIL(c,b,n,loc) (NODE *)rb_node_until_new(p,c,b,n,loc) @@ -5443,7 +5443,7 @@ case_body : k_when case_args then compstmt cases { - $$ = NEW_WHEN($2, $4, $5, &@$); + $$ = NEW_WHEN($2, $4, $5, &@$, &@1, &@3); fixpos($$, $2); /*% ripper: when!($:2, $:4, $:5) %*/ } @@ -11643,12 +11643,14 @@ rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const Y } static rb_node_when_t * -rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc) +rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc) { rb_node_when_t *n = NODE_NEWNODE(NODE_WHEN, rb_node_when_t, loc); n->nd_head = nd_head; n->nd_body = nd_body; n->nd_next = nd_next; + n->keyword_loc = *keyword_loc; + n->then_keyword_loc = *then_keyword_loc; return n; } diff --git a/rubyparser.h b/rubyparser.h index 1a1a1d2b07..5728844827 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -305,6 +305,8 @@ typedef struct RNode_WHEN { struct RNode *nd_head; struct RNode *nd_body; struct RNode *nd_next; + rb_code_location_t keyword_loc; + rb_code_location_t then_keyword_loc; } rb_node_when_t; typedef struct RNode_IN { diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index f03a323ccf..8ecd384d58 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -1375,6 +1375,11 @@ dummy assert_locations(node.children[-1].locations, [[1, 0, 1, 13], [1, 0, 1, 5]]) end + def test_when_locations + node = RubyVM::AbstractSyntaxTree.parse("case a; when 1 then 2; end") + assert_locations(node.children[-1].children[1].locations, [[1, 8, 1, 22], [1, 8, 1, 12], [1, 15, 1, 19]]) + end + private def assert_locations(locations, expected) ary = locations.map {|loc| loc && [loc.first_lineno, loc.first_column, loc.last_lineno, loc.last_column] }