summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2022-11-20 22:59:52 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2022-12-01 17:05:41 +0900
commit4e68b594314760611d0926c3de70a4cad26802cd (patch)
tree58254a7288d2402fbe5baa41426a8e8c4d027470
parent5752d11f1f33d277356373da749db111e03c96b5 (diff)
downloadruby-4e68b594314760611d0926c3de70a4cad26802cd.tar.gz
[Feature #19138] Add `SyntaxError#path`
-rw-r--r--NEWS.md4
-rw-r--r--error.c38
-rw-r--r--test/ruby/test_exception.rb23
3 files changed, 55 insertions, 10 deletions
diff --git a/NEWS.md b/NEWS.md
index b879a47a78..da15f8167d 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -300,6 +300,9 @@ Note: We're only listing outstanding class updates.
* Time#deconstruct_keys is added, allowing to use Time instances
in pattern-matching expressions [[Feature #19071]]
+* SyntaxError
+ * SyntaxError#path has been added. [[Bug #19138]]
+
* TracePoint
* TracePoint#binding now returns `nil` for `c_call`/`c_return` TracePoints.
@@ -551,3 +554,4 @@ The following deprecated APIs are removed.
[Feature #19071]: https://bugs.ruby-lang.org/issues/19071
[Bug #19100]: https://bugs.ruby-lang.org/issues/19100
[Feature #19135]: https://bugs.ruby-lang.org/issues/19135
+[Feature #19138]: https://bugs.ruby-lang.org/issues/19138
diff --git a/error.c b/error.c
index 0ff4b8d6d8..ad1bc6ee8d 100644
--- a/error.c
+++ b/error.c
@@ -125,6 +125,8 @@ err_vcatf(VALUE str, const char *pre, const char *file, int line,
return str;
}
+static VALUE syntax_error_with_path(VALUE, VALUE, VALUE*, rb_encoding*);
+
VALUE
rb_syntax_error_append(VALUE exc, VALUE file, int line, int column,
rb_encoding *enc, const char *fmt, va_list args)
@@ -138,15 +140,7 @@ rb_syntax_error_append(VALUE exc, VALUE file, int line, int column,
}
else {
VALUE mesg;
- if (NIL_P(exc)) {
- mesg = rb_enc_str_new(0, 0, enc);
- exc = rb_class_new_instance(1, &mesg, rb_eSyntaxError);
- }
- else {
- mesg = rb_attr_get(exc, idMesg);
- if (RSTRING_LEN(mesg) > 0 && *(RSTRING_END(mesg)-1) != '\n')
- rb_str_cat_cstr(mesg, "\n");
- }
+ exc = syntax_error_with_path(exc, file, &mesg, enc);
err_vcatf(mesg, NULL, fn, line, fmt, args);
}
@@ -2353,6 +2347,25 @@ syntax_error_initialize(int argc, VALUE *argv, VALUE self)
return rb_call_super(argc, argv);
}
+static VALUE
+syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
+{
+ if (NIL_P(exc)) {
+ *mesg = rb_enc_str_new(0, 0, enc);
+ exc = rb_class_new_instance(1, mesg, rb_eSyntaxError);
+ rb_ivar_set(exc, id_i_path, path);
+ }
+ else {
+ if (rb_attr_get(exc, id_i_path) != path) {
+ rb_raise(rb_eArgError, "SyntaxError#path changed");
+ }
+ VALUE s = *mesg = rb_attr_get(exc, idMesg);
+ if (RSTRING_LEN(s) > 0 && *(RSTRING_END(s)-1) != '\n')
+ rb_str_cat_cstr(s, "\n");
+ }
+ return exc;
+}
+
/*
* Document-module: Errno
*
@@ -3011,9 +3024,14 @@ Init_Exception(void)
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
rb_define_method(rb_eSyntaxError, "initialize", syntax_error_initialize, -1);
+ ID id_path = rb_intern_const("path");
+
+ /* the path failed to parse */
+ rb_attr(rb_eSyntaxError, id_path, TRUE, FALSE, FALSE);
+
rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
/* the path failed to load */
- rb_attr(rb_eLoadError, rb_intern_const("path"), TRUE, FALSE, FALSE);
+ rb_attr(rb_eLoadError, id_path, TRUE, FALSE, FALSE);
rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 36f778975b..9bed2c76cd 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -1487,4 +1487,27 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
end
end
+
+ def test_syntax_error_path
+ e = assert_raise(SyntaxError) {
+ eval("1+", nil, "test_syntax_error_path.rb")
+ }
+ assert_equal("test_syntax_error_path.rb", e.path)
+
+ Dir.mktmpdir do |dir|
+ lib = File.join(dir, "syntax_error-path.rb")
+ File.write(lib, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class SyntaxError
+ def detailed_message(**)
+ STDERR.puts "\n""path=#{path}\n"
+ super
+ end
+ end
+ end;
+ main = File.join(dir, "syntax_error.rb")
+ File.write(main, "1+\n")
+ assert_in_out_err(%W[-r#{lib} #{main}], "", [], [:*, "\n""path=#{main}\n", :*])
+ end
+ end
end