Skip to content

Commit

Permalink
Add Style/HeredocIndent
Browse files Browse the repository at this point in the history
Co-authored-by: Sijawusz Pur Rahnama <[email protected]>
  • Loading branch information
nobodywasishere and Sija committed Feb 3, 2025
1 parent e8d0424 commit 5f4b1d8
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 0 deletions.
81 changes: 81 additions & 0 deletions spec/ameba/rule/style/heredoc_indent_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
require "../../../spec_helper"

module Ameba::Rule::Style
describe HeredocIndent do
subject = HeredocIndent.new

it "passes if heredoc body indented one level" do
expect_no_issues subject, <<-CRYSTAL
<<-HEREDOC
hello world
HEREDOC
<<-HEREDOC
hello world
HEREDOC
CRYSTAL
end

it "fails if the heredoc body is indented incorrectly" do
expect_issue subject, <<-CRYSTAL
<<-ONE
# ^^^^ error: Heredoc body should be indented by 2 spaces
hello world
ONE
<<-TWO
# ^^^^^^ error: Heredoc body should be indented by 2 spaces
hello world
TWO
<<-THREE
# ^^^^^^^^ error: Heredoc body should be indented by 2 spaces
hello world
THREE
<<-FOUR
# ^^^^^^^ error: Heredoc body should be indented by 2 spaces
hello world
FOUR
CRYSTAL
end

context "properties" do
context "#indent_by" do
rule = HeredocIndent.new
rule.indent_by = 0

it "passes if heredoc body has the same indent level" do
expect_no_issues rule, <<-CRYSTAL
<<-HEREDOC
hello world
HEREDOC
<<-HEREDOC
hello world
HEREDOC
CRYSTAL
end

it "fails if the heredoc body is indented incorrectly" do
expect_issue rule, <<-CRYSTAL
<<-ONE
# ^^^^ error: Heredoc body should be indented by 0 spaces
hello world
ONE
<<-TWO
# ^^^^^^ error: Heredoc body should be indented by 0 spaces
hello world
TWO
<<-FOUR
# ^^^^^^^ error: Heredoc body should be indented by 0 spaces
hello world
FOUR
CRYSTAL
end
end
end
end
end
66 changes: 66 additions & 0 deletions src/ameba/rule/style/heredoc_indent.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
module Ameba::Rule::Style
# A rule that enforces _Heredoc_ bodies be indented one level above the indentation of the
# line they're used on.
#
# For example, this is considered invalid:
#
# ```
# <<-HERERDOC
# hello world
# HEREDOC
#
# <<-HERERDOC
# hello world
# HEREDOC
# ```
#
# And should be written as:
#
# ```
# <<-HERERDOC
# hello world
# HEREDOC
#
# <<-HERERDOC
# hello world
# HEREDOC
# ```
#
# The `IndentBy` configuration option changes the enforced indentation level of the _heredoc_.
#
# ```
# Style/HeredocIndent:
# Enabled: true
# IndentBy: 2
# ```
class HeredocIndent < Base
properties do
since_version "1.7.0"
description "Recommends heredoc bodies are indented consistently"
indent_by 2
end

MSG = "Heredoc body should be indented by %s spaces"

def test(source, node : Crystal::StringInterpolation)
return unless start_location = node.location

start_location_pos = source.pos(start_location)
return unless source.code[start_location_pos..(start_location_pos + 2)]? == "<<-"

correct_indent = line_indent(source, start_location) + indent_by

unless node.heredoc_indent == correct_indent
issue_for node, MSG % indent_by
end
end

private def line_indent(source, start_location) : Int32
line_location = Crystal::Location.new(nil, start_location.line_number, 1)
line_location_pos = source.pos(line_location)
line = source.code[line_location_pos..(line_location_pos + start_location.column_number)]

line.size - line.lstrip.size
end
end
end

0 comments on commit 5f4b1d8

Please sign in to comment.