From dd96eb03e4a39dee719f672c8497ad01432c383d Mon Sep 17 00:00:00 2001 From: SAY-5 Date: Sat, 23 May 2026 21:57:46 -0700 Subject: [PATCH] feat(style/heredoc_escape): add autocorrection --- spec/ameba/rule/style/heredoc_escape_spec.cr | 32 +++++++++++++++++--- src/ameba/rule/style/heredoc_escape.cr | 10 ++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/spec/ameba/rule/style/heredoc_escape_spec.cr b/spec/ameba/rule/style/heredoc_escape_spec.cr index a21db75f5..81a0e92b7 100644 --- a/spec/ameba/rule/style/heredoc_escape_spec.cr +++ b/spec/ameba/rule/style/heredoc_escape_spec.cr @@ -45,21 +45,33 @@ module Ameba::Rule::Style end it "fails if a heredoc contains escaped interpolation" do - expect_issue subject, <<-'CRYSTAL' + source = expect_issue subject, <<-'CRYSTAL' <<-HEREDOC # ^^^^^^^^ error: Use an escaped heredoc marker: `<<-'HEREDOC'` foo \#{:bar} HEREDOC CRYSTAL + + expect_correction source, <<-'CRYSTAL' + <<-'HEREDOC' + foo \#{:bar} + HEREDOC + CRYSTAL end it "fails if a heredoc contains escaped interpolation and escaped escape sequences" do - expect_issue subject, <<-'CRYSTAL' + source = expect_issue subject, <<-'CRYSTAL' <<-HEREDOC # ^^^^^^^^ error: Use an escaped heredoc marker: `<<-'HEREDOC'` foo \\t \#{:bar} HEREDOC CRYSTAL + + expect_correction source, <<-'CRYSTAL' + <<-'HEREDOC' + foo \\t \#{:bar} + HEREDOC + CRYSTAL end it "passes if a heredoc contains normal and escaped escape sequences" do @@ -71,12 +83,18 @@ module Ameba::Rule::Style end it "fails if a heredoc contains escaped escape sequences" do - expect_issue subject, <<-'CRYSTAL' + source = expect_issue subject, <<-'CRYSTAL' <<-HEREDOC # ^^^^^^^^ error: Use an escaped heredoc marker: `<<-'HEREDOC'` \\t \\n HEREDOC CRYSTAL + + expect_correction source, <<-'CRYSTAL' + <<-'HEREDOC' + \\t \\n + HEREDOC + CRYSTAL end it "passes if an escaped heredoc contains interpolation" do @@ -123,12 +141,18 @@ module Ameba::Rule::Style end it "fails if an escaped heredoc doesn't contain interpolation" do - expect_issue subject, <<-CRYSTAL + source = expect_issue subject, <<-CRYSTAL <<-'HEREDOC' # ^^^^^^^^^^ error: Use an unescaped heredoc marker: `<<-HEREDOC` foo HEREDOC CRYSTAL + + expect_correction source, <<-CRYSTAL + <<-HEREDOC + foo + HEREDOC + CRYSTAL end end end diff --git a/src/ameba/rule/style/heredoc_escape.cr b/src/ameba/rule/style/heredoc_escape.cr index bc332bc78..bcb3705ab 100644 --- a/src/ameba/rule/style/heredoc_escape.cr +++ b/src/ameba/rule/style/heredoc_escape.cr @@ -48,21 +48,27 @@ module Ameba::Rule::Style return unless code = node_source(node, source.lines) return unless code.starts_with?("<<-") - body = code.lines[1..-2].join('\n') + lines = code.lines + body = lines[1..-2].join('\n') if code.starts_with?("<<-'") return if has_escape_sequence?(expr.value) || has_escaped_escape_sequence?(body) marker = code.lchop("<<-'").match!(/^(\w+)/)[1] msg = MSG_ESCAPE_NOT_NEEDED % marker + corrected_marker = "<<-#{marker}" else return if !has_escape_sequence?(expr.value) || has_escape_sequence?(body) marker = code.lchop("<<-").match!(/^(\w+)/)[1] msg = MSG_ESCAPE_NEEDED % marker + corrected_marker = "<<-'#{marker}'" end - issue_for node, msg + issue_for node, msg do |corrector| + lines[0] = lines[0].sub(/^<<-'?#{marker}'?/, corrected_marker) + corrector.replace(node, lines.join('\n')) + end end private def has_escape_sequence?(value : String)