diff --git a/spec/compiler/semantic/macro_spec.cr b/spec/compiler/semantic/macro_spec.cr index a5d5dd1286e4..dd1162b4dc9a 100644 --- a/spec/compiler/semantic/macro_spec.cr +++ b/spec/compiler/semantic/macro_spec.cr @@ -1427,4 +1427,12 @@ describe "Semantic: macro" do ), "can't instantiate abstract class Foo" end + + it "doesn't crash on syntax error inside macro (regression, #8038)" do + expect_raises(Crystal::SyntaxException, "unterminated array literal") do + semantic(%( + {% begin %}[{% end %} + )) + end + end end diff --git a/src/compiler/crystal/exception.cr b/src/compiler/crystal/exception.cr index 38e28fa2135e..fcf845708337 100644 --- a/src/compiler/crystal/exception.cr +++ b/src/compiler/crystal/exception.cr @@ -242,22 +242,27 @@ module Crystal def minimize_indentation(source) min_leading_white_space = - source.map do |line| - if match = line.match(/^(\s+)\S/) - spaces = match[1]? - spaces.size if spaces - end - end - .compact - .min + source.min_of? { |line| leading_white_space(line) } || 0 - source = source.map do |line| - replace_leading_tabs_with_spaces(line).lchop(" " * min_leading_white_space) + if min_leading_white_space > 0 + source = source.map do |line| + replace_leading_tabs_with_spaces(line).lchop(" " * min_leading_white_space) + end end {source, min_leading_white_space} end + private def leading_white_space(line) + match = line.match(/^(\s+)\S/) + return 0 unless match + + spaces = match[1]? + return 0 unless spaces + + spaces.size + end + def append_expanded_macro(io, source) line_number = @line_number if @error_trace || !line_number