1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

SyntaxError message at iseq compile

* iseq.c (rb_iseq_compile_with_option): make the parser in mild
  error.
* load.c (rb_load_internal0): ditto.
* parse.y (yycompile0): return the error message within the error
  to be raised.  [Feature #11951]
* parse.y (parser_compile_error): accumulate error messages in the
  error_buffer.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54189 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2016-03-19 05:46:20 +00:00
parent 22198f9d3c
commit bc343b851d
10 changed files with 103 additions and 73 deletions

View file

@ -1,3 +1,16 @@
Sat Mar 19 14:46:18 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* iseq.c (rb_iseq_compile_with_option): make the parser in mild
error.
* load.c (rb_load_internal0): ditto.
* parse.y (yycompile0): return the error message within the error
to be raised. [Feature #11951]
* parse.y (parser_compile_error): accumulate error messages in the
error_buffer.
Sat Mar 19 03:57:13 2016 NARUSE, Yui <naruse@ruby-lang.org>
* time.c (LOCALTIME): organize #ifdefs.

67
error.c
View file

@ -94,88 +94,53 @@ compile_snprintf(rb_encoding *enc, const char *pre, const char *file, int line,
return str;
}
static void
compile_err_append(VALUE mesg)
VALUE
rb_compile_err_append(VALUE buffer, VALUE mesg)
{
rb_thread_t *th = GET_THREAD();
VALUE err = th->errinfo;
rb_block_t *prev_base_block = th->base_block;
th->base_block = 0;
/* base_block should be zero while normal Ruby execution */
/* after this line, any Ruby code *can* run */
if (th->mild_compile_error) {
if (RTEST(err)) {
VALUE str = rb_obj_as_string(err);
rb_str_cat2(str, "\n");
rb_str_append(str, mesg);
mesg = str;
}
err = rb_exc_new3(rb_eSyntaxError, mesg);
th->errinfo = err;
}
else {
if (!RTEST(err)) {
err = rb_exc_new2(rb_eSyntaxError, "compile error");
th->errinfo = err;
}
if (!buffer) {
rb_str_cat2(mesg, "\n");
rb_write_error_str(mesg);
}
else if (NIL_P(buffer)) {
buffer = mesg;
}
else {
rb_str_cat2(buffer, "\n");
rb_str_append(buffer, mesg);
}
/* returned to the parser world */
th->base_block = prev_base_block;
return buffer;
}
void
rb_compile_error_with_enc(const char *file, int line, void *enc, const char *fmt, ...)
{
va_list args;
VALUE str;
va_start(args, fmt);
str = compile_snprintf(enc, NULL, file, line, fmt, args);
va_end(args);
compile_err_append(str);
}
void
rb_compile_error(const char *file, int line, const char *fmt, ...)
{
va_list args;
VALUE str;
va_start(args, fmt);
str = compile_snprintf(NULL, NULL, file, line, fmt, args);
va_end(args);
compile_err_append(str);
}
void
rb_compile_error_str(VALUE file, int line, void *enc, const char *fmt, ...)
VALUE
rb_error_vsprintf(VALUE file, int line, void *enc, const char *fmt, va_list args)
{
va_list args;
VALUE str;
va_start(args, fmt);
str = compile_snprintf(enc, NULL,
NIL_P(file) ? NULL : RSTRING_PTR(file), line,
fmt, args);
va_end(args);
compile_err_append(str);
return compile_snprintf(enc, NULL,
NIL_P(file) ? NULL : RSTRING_PTR(file), line,
fmt, args);
}
void
rb_compile_error_append(const char *fmt, ...)
{
va_list args;
VALUE str;
va_start(args, fmt);
str = rb_vsprintf(fmt, args);
va_end(args);
compile_err_append(str);
}
static void

View file

@ -1074,6 +1074,8 @@ struct RBasicRaw {
#endif
VALUE rb_parser_get_yydebug(VALUE);
VALUE rb_parser_set_yydebug(VALUE, VALUE);
VALUE rb_parser_mild_error(VALUE parser);
void *rb_parser_load_file(VALUE parser, VALUE name);
int rb_is_const_name(VALUE name);
int rb_is_class_name(VALUE name);
int rb_is_global_name(VALUE name);

4
iseq.c
View file

@ -627,11 +627,13 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE li
const INITIALIZED VALUE label = parent ?
parent->body->location.label :
rb_fstring_cstr("<compiled>");
VALUE parser = rb_parser_new();
rb_parser_mild_error(parser);
th->base_block = base_block;
TH_PUSH_TAG(th);
if ((state = EXEC_TAG()) == 0) {
NODE *node = (*parse)(rb_parser_new(), file, src, ln);
NODE *node = (*parse)(parser, file, src, ln);
if (node) { /* TODO: check err */
iseq = rb_iseq_new_with_opt(node, label, file, absolute_path, line,
parent, type, &option);

9
load.c
View file

@ -583,7 +583,6 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
int state;
volatile VALUE wrapper = th->top_wrapper;
volatile VALUE self = th->top_self;
volatile int mild_compile_error;
#if !defined __GNUC__
rb_thread_t *volatile th0 = th;
#endif
@ -600,7 +599,6 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
rb_extend_object(th->top_self, th->top_wrapper);
}
mild_compile_error = th->mild_compile_error;
TH_PUSH_TAG(th);
state = EXEC_TAG();
if (state == 0) {
@ -611,10 +609,10 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
/* OK */
}
else {
th->mild_compile_error++;
node = (NODE *)rb_load_file_str(fname);
VALUE parser = rb_parser_new();
rb_parser_mild_error(parser);
node = (NODE *)rb_parser_load_file(parser, fname);
iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), NULL);
th->mild_compile_error--;
}
rb_iseq_eval(iseq);
}
@ -624,7 +622,6 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
th = th0;
fname = RB_GC_GUARD(fname);
#endif
th->mild_compile_error = mild_compile_error;
th->top_self = self;
th->top_wrapper = wrapper;

41
parse.y
View file

@ -312,6 +312,7 @@ struct parser_params {
NODE *eval_tree_begin;
NODE *eval_tree;
VALUE error_buffer;
VALUE debug_lines;
VALUE coverage;
#else
@ -740,7 +741,6 @@ static ID id_warn, id_warning;
# define WARNING_ARGS_L(l, fmt,n) WARNING_ARGS(fmt,n)
# define WARNING_CALL rb_funcall
static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
# define rb_compile_error ripper_compile_error
# define compile_error ripper_compile_error
# define PARSER_ARG parser,
#else
@ -753,9 +753,9 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
# define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n)
# define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n)
# define WARNING_CALL rb_compile_warning
# define rb_compile_error rb_compile_error_str
# define compile_error (parser->error_p = 1),rb_compile_error_str
# define PARSER_ARG ruby_sourcefile_string, ruby_sourceline, (void *)current_enc,
static void parser_compile_error(struct parser_params*, const char *fmt, ...);
# define compile_error parser_compile_error
# define PARSER_ARG parser,
#endif
/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
@ -5559,6 +5559,9 @@ yycompile0(VALUE arg)
lex_p = lex_pbeg = lex_pend = 0;
lex_lastline = lex_nextline = 0;
if (parser->error_p) {
VALUE mesg = parser->error_buffer;
if (!mesg) mesg = rb_fstring_cstr("compile error");
rb_set_errinfo(rb_exc_new_str(rb_eSyntaxError, mesg));
return 0;
}
tree = ruby_eval_tree;
@ -10792,6 +10795,8 @@ parser_initialize(struct parser_params *parser)
parser->delayed = Qnil;
parser->result = Qnil;
parser->parsing_thread = Qnil;
#else
parser->error_buffer = Qfalse;
#endif
parser->debug_buffer = Qnil;
parser->enc = rb_utf8_encoding();
@ -10818,6 +10823,7 @@ parser_mark(void *ptr)
rb_gc_mark((VALUE)ruby_eval_tree);
rb_gc_mark(ruby_debug_lines);
rb_gc_mark(parser->compile_option);
rb_gc_mark(parser->error_buffer);
#else
rb_gc_mark(parser->delayed);
rb_gc_mark(parser->value);
@ -10901,6 +10907,16 @@ rb_parser_new(void)
parser_initialize(p);
return parser;
}
VALUE
rb_parser_mild_error(VALUE vparser)
{
struct parser_params *parser;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
parser->error_buffer = Qnil;
return vparser;
}
#endif
#ifdef RIPPER
@ -11069,6 +11085,23 @@ rb_parser_printf(struct parser_params *parser, const char *fmt, ...)
parser->debug_buffer = Qnil;
}
}
extern VALUE rb_error_vsprintf(VALUE, int, void *, const char *, va_list);
extern VALUE rb_compile_err_append(VALUE buffer, VALUE mesg);
static void
parser_compile_error(struct parser_params *parser, const char *fmt, ...)
{
VALUE str;
va_list ap;
parser->error_p = 1;
va_start(ap, fmt);
str = rb_error_vsprintf(ruby_sourcefile_string, ruby_sourceline,
(void *)current_enc, fmt, ap);
va_end(ap);
parser->error_buffer = rb_compile_err_append(parser->error_buffer, str);
}
#endif
#ifdef RIPPER

8
ruby.c
View file

@ -1948,6 +1948,14 @@ rb_load_file_str(VALUE fname_v)
return load_file(rb_parser_new(), fname_v, 0, cmdline_options_init(&opt));
}
void *
rb_parser_load_file(VALUE parser, VALUE fname_v)
{
struct cmdline_options opt;
return load_file(parser, fname_v, 0, cmdline_options_init(&opt));
}
/*
* call-seq:
* Process.argv0 -> frozen_string

View file

@ -214,4 +214,25 @@ class TestISeq < Test::Unit::TestCase
at_exit { assert_equal([:n, :x], Segfault.new.segfault.sort) }
end;
end
def test_syntax_error_message
feature11951 = '[Feature #11951]'
src, line = <<-'end;', __LINE__+1
def x@;end
def y@;end
end;
e1 = e2 = nil
m1 = EnvUtil.verbose_warning do
e1 = assert_raise(SyntaxError) do
eval(src, nil, __FILE__, line)
end
end
m2 = EnvUtil.verbose_warning do
e2 = assert_raise(SyntaxError) do
ISeq.new(src, __FILE__, __FILE__, line)
end
end
assert_equal([m1, e1.message], [m2, e2.message], feature11951)
end
end

View file

@ -750,12 +750,6 @@ typedef struct rb_thread_struct {
*/
int parse_in_eval;
/*! Thread-local state of compiling context.
*
* If non-zero, the parser does not automatically print error messages to
* stderr. */
int mild_compile_error;
/* storage */
st_table *local_storage;
VALUE local_storage_recursive_hash;

View file

@ -1284,7 +1284,6 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
rb_env_t *env = NULL;
rb_block_t block, *base_block;
volatile int parse_in_eval;
volatile int mild_compile_error;
volatile VALUE file;
volatile int line;
@ -1292,7 +1291,6 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
line = lineno;
parse_in_eval = th->parse_in_eval;
mild_compile_error = th->mild_compile_error;
TH_PUSH_TAG(th);
if ((state = TH_EXEC_TAG()) == 0) {
rb_cref_t *cref = cref_arg;
@ -1343,9 +1341,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
/* make eval iseq */
th->parse_in_eval++;
th->mild_compile_error++;
iseq = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil);
th->mild_compile_error--;
th->parse_in_eval--;
if (!cref && base_block->iseq) {
@ -1373,7 +1369,6 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
result = vm_exec(th);
}
TH_POP_TAG();
th->mild_compile_error = mild_compile_error;
th->parse_in_eval = parse_in_eval;
if (state) {