diff --git a/spec/compiler/semantic/macro_spec.cr b/spec/compiler/semantic/macro_spec.cr index b62dd425348e..3c05097ccc9f 100644 --- a/spec/compiler/semantic/macro_spec.cr +++ b/spec/compiler/semantic/macro_spec.cr @@ -275,13 +275,27 @@ describe "Semantic: macro" do end it "executes raise inside macro" do - assert_error %( + ex = assert_error %( macro foo {{ raise "OH NO" }} end foo ), "OH NO" + + ex.to_s.should_not contain("expanding macro") + end + + it "executes raise inside macro, with node (#5669)" do + ex = assert_error %( + macro foo(x) + {{ x.raise "OH\nNO" }} + end + + foo(1) + ), "OH\nNO" + + ex.to_s.should_not contain("expanding macro") end it "can specify tuple as return type" do diff --git a/src/compiler/crystal/macros/interpreter.cr b/src/compiler/crystal/macros/interpreter.cr index f2f1ff7d5427..63dda71fabe9 100644 --- a/src/compiler/crystal/macros/interpreter.cr +++ b/src/compiler/crystal/macros/interpreter.cr @@ -349,6 +349,8 @@ module Crystal begin @last = receiver.interpret(node.name, args, node.block, self) + rescue ex : MacroRaiseException + raise ex rescue ex : Crystal::Exception node.raise ex.message, inner: ex rescue ex diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index a88387e445ce..c9e99e4880f3 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -160,13 +160,7 @@ module Crystal end def interpret_raise(node) - msg = node.args.map do |arg| - arg.accept self - @last.to_macro_id - end - msg = msg.join " " - - node.raise msg, exception_type: MacroRaiseException + macro_raise(node, node.args, self) end def interpret_run(node) @@ -299,9 +293,7 @@ module Crystal when "class_name" interpret_argless_method("class_name", args) { class_name } when "raise" - interpret_one_arg_method(method, args) do |arg| - raise arg.to_s - end + macro_raise self, args, interpreter when "filename" interpret_argless_method("filename", args) do filename = location.try &.original_filename @@ -2148,6 +2140,16 @@ private def visibility_to_symbol(visibility) Crystal::SymbolLiteral.new(visibility_name) end +private def macro_raise(node, args, interpreter) + msg = args.map do |arg| + arg.accept interpreter + interpreter.last.to_macro_id + end + msg = msg.join " " + + node.raise msg, exception_type: Crystal::MacroRaiseException +end + def filter(object, klass, block, interpreter, keep = true) block_arg = block.args.first?