summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast.c6
-rw-r--r--node_dump.c5
-rw-r--r--parse.y39
-rw-r--r--rubyparser.h3
-rw-r--r--test/ruby/test_ast.rb8
5 files changed, 53 insertions, 8 deletions
diff --git a/ast.c b/ast.c
index 861785871a..45559b6fd1 100644
--- a/ast.c
+++ b/ast.c
@@ -812,6 +812,12 @@ node_locations(VALUE ast_value, const NODE *node)
location_new(nd_code_loc(node)),
location_new(&RNODE_EVSTR(node)->opening_loc),
location_new(&RNODE_EVSTR(node)->closing_loc));
+ case NODE_LAMBDA:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_LAMBDA(node)->operator_loc),
+ location_new(&RNODE_LAMBDA(node)->opening_loc),
+ location_new(&RNODE_LAMBDA(node)->closing_loc));
case NODE_IF:
return rb_ary_new_from_args(4,
location_new(nd_code_loc(node)),
diff --git a/node_dump.c b/node_dump.c
index cff7cdb433..52c924a9d0 100644
--- a/node_dump.c
+++ b/node_dump.c
@@ -1113,8 +1113,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("lambda expression");
ANN("format: -> [nd_body]");
ANN("example: -> { foo }");
- LAST_NODE;
F_NODE(nd_body, RNODE_LAMBDA, "lambda clause");
+ F_LOC(operator_loc, RNODE_LAMBDA);
+ F_LOC(opening_loc, RNODE_LAMBDA);
+ LAST_NODE;
+ F_LOC(closing_loc, RNODE_LAMBDA);
return;
case NODE_OPT_ARG:
diff --git a/parse.y b/parse.y
index 75698de666..a7dd705d80 100644
--- a/parse.y
+++ b/parse.y
@@ -437,6 +437,13 @@ struct local_vars {
NODE *it;
};
+typedef struct rb_locations_lambda_body_t {
+ NODE *node;
+ YYLTYPE loc;
+ YYLTYPE opening_loc;
+ YYLTYPE closing_loc;
+} rb_locations_lambda_body_t;
+
enum {
ORDINAL_PARAM = -1,
NO_PARAM = 0,
@@ -1155,7 +1162,7 @@ static rb_node_postexe_t *rb_node_postexe_new(struct parser_params *p, NODE *nd_
static rb_node_sym_t *rb_node_sym_new(struct parser_params *p, VALUE str, const YYLTYPE *loc);
static rb_node_dsym_t *rb_node_dsym_new(struct parser_params *p, rb_parser_string_t *string, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
static rb_node_attrasgn_t *rb_node_attrasgn_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
-static rb_node_lambda_t *rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_lambda_t *rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc);
static rb_node_aryptn_t *rb_node_aryptn_new(struct parser_params *p, NODE *pre_args, NODE *rest_arg, NODE *post_args, const YYLTYPE *loc);
static rb_node_hshptn_t *rb_node_hshptn_new(struct parser_params *p, NODE *nd_pconst, NODE *nd_pkwargs, NODE *nd_pkwrestarg, const YYLTYPE *loc);
static rb_node_fndptn_t *rb_node_fndptn_new(struct parser_params *p, NODE *pre_rest_arg, NODE *args, NODE *post_rest_arg, const YYLTYPE *loc);
@@ -1263,7 +1270,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_SYM(str,loc) (NODE *)rb_node_sym_new(p,str,loc)
#define NEW_DSYM(s,l,n,loc) (NODE *)rb_node_dsym_new(p,s,l,n,loc)
#define NEW_ATTRASGN(r,m,a,loc) (NODE *)rb_node_attrasgn_new(p,r,m,a,loc)
-#define NEW_LAMBDA(a,b,loc) (NODE *)rb_node_lambda_new(p,a,b,loc)
+#define NEW_LAMBDA(a,b,loc,op_loc,o_loc,c_loc) (NODE *)rb_node_lambda_new(p,a,b,loc,op_loc,o_loc,c_loc)
#define NEW_ARYPTN(pre,r,post,loc) (NODE *)rb_node_aryptn_new(p,pre,r,post,loc)
#define NEW_HSHPTN(c,kw,kwrest,loc) (NODE *)rb_node_hshptn_new(p,c,kw,kwrest,loc)
#define NEW_FNDPTN(pre,a,post,loc) (NODE *)rb_node_fndptn_new(p,pre,a,post,loc)
@@ -1486,6 +1493,8 @@ static NODE *heredoc_dedent(struct parser_params*,NODE*);
static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYPE *loc);
+static rb_locations_lambda_body_t* new_locations_lambda_body(struct parser_params *p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc);
+
#ifdef RIPPER
#define get_value(idx) (rb_ary_entry(p->s_value_stack, idx))
#define set_value(val) (p->s_lvalue = val)
@@ -2670,6 +2679,7 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
rb_node_masgn_t *node_masgn;
rb_node_def_temp_t *node_def_temp;
rb_node_exits_t *node_exits;
+ struct rb_locations_lambda_body_t *locations_lambda_body;
ID id;
int num;
st_table *tbl;
@@ -2776,7 +2786,8 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
%type <node_args> block_param opt_block_param block_param_def
%type <node_kw_arg> f_kw f_block_kw
%type <id> bv_decls opt_bv_decl bvar
-%type <node> lambda lambda_body brace_body do_body
+%type <node> lambda brace_body do_body
+%type <locations_lambda_body> lambda_body
%type <node_args> f_larglist
%type <node> brace_block cmd_brace_block do_block lhs none fitem
%type <node> mlhs_head mlhs_item mlhs_node mlhs_post
@@ -5183,7 +5194,7 @@ lambda : tLAMBDA[lpar]
$args = args_with_numbered(p, $args, max_numparam, it_id);
{
YYLTYPE loc = code_loc_gen(&@args, &@body);
- $$ = NEW_LAMBDA($args, $body, &loc);
+ $$ = NEW_LAMBDA($args, $body->node, &loc, &@lpar, &$body->opening_loc, &$body->closing_loc);
nd_set_line(RNODE_LAMBDA($$)->nd_body, @body.end_pos.lineno);
nd_set_line($$, @args.end_pos.lineno);
nd_set_first_loc($$, @1.beg_pos);
@@ -5213,7 +5224,7 @@ f_larglist : '(' f_args opt_bv_decl ')'
lambda_body : tLAMBEG compstmt '}'
{
token_info_pop(p, "}", &@3);
- $$ = $2;
+ $$ = new_locations_lambda_body(p, $2, &@2, &@1, &@3);
/*% ripper: $:2 %*/
}
| keyword_do_LAMBDA
@@ -5222,7 +5233,7 @@ lambda_body : tLAMBEG compstmt '}'
}
bodystmt k_end
{
- $$ = $3;
+ $$ = new_locations_lambda_body(p, $3, &@3, &@1, &@4);
/*% ripper: $:3 %*/
}
;
@@ -11588,12 +11599,15 @@ rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body
}
static rb_node_lambda_t *
-rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc)
+rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
{
/* Keep the order of node creation */
NODE *scope = NEW_SCOPE(nd_args, nd_body, loc);
rb_node_lambda_t *n = NODE_NEWNODE(NODE_LAMBDA, rb_node_lambda_t, loc);
n->nd_body = scope;
+ n->operator_loc = *operator_loc;
+ n->opening_loc = *opening_loc;
+ n->closing_loc = *closing_loc;
return n;
}
@@ -12894,6 +12908,17 @@ new_command_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *a
return ret;
}
+static rb_locations_lambda_body_t*
+new_locations_lambda_body(struct parser_params* p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
+{
+ rb_locations_lambda_body_t *body = xcalloc(1, sizeof(rb_locations_lambda_body_t));
+ body->node = node;
+ body->loc = *loc;
+ body->opening_loc = *opening_loc;
+ body->closing_loc = *closing_loc;
+ return body;
+}
+
#define nd_once_body(node) (nd_type_p((node), NODE_ONCE) ? RNODE_ONCE(node)->nd_body : node)
static NODE*
diff --git a/rubyparser.h b/rubyparser.h
index 155b8d8760..cd1e88ff6c 100644
--- a/rubyparser.h
+++ b/rubyparser.h
@@ -968,6 +968,9 @@ typedef struct RNode_LAMBDA {
NODE node;
struct RNode *nd_body;
+ rb_code_location_t operator_loc;
+ rb_code_location_t opening_loc;
+ rb_code_location_t closing_loc;
} rb_node_lambda_t;
typedef struct RNode_ARYPTN {
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index e456f5b7b5..d509cc26c6 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -1384,6 +1384,14 @@ dummy
assert_locations(node.children[-1].children[1].locations, [[1, 0, 1, 5], [1, 1, 1, 2], nil])
end
+ def test_lambda_locations
+ node = ast_parse("-> (a, b) { foo }")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 17], [1, 0, 1, 2], [1, 10, 1, 11], [1, 16, 1, 17]])
+
+ node = ast_parse("-> (a, b) do foo end")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 20], [1, 0, 1, 2], [1, 10, 1, 12], [1, 17, 1, 20]])
+ end
+
def test_if_locations
node = ast_parse("if cond then 1 else 2 end")
assert_locations(node.children[-1].locations, [[1, 0, 1, 25], [1, 0, 1, 2], [1, 8, 1, 12], [1, 22, 1, 25]])