Skip to content

Commit 5f4b1d8

Browse files
nobodywasishereSija
andcommitted
Add Style/HeredocIndent
Co-authored-by: Sijawusz Pur Rahnama <[email protected]>
1 parent e8d0424 commit 5f4b1d8

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
require "../../../spec_helper"
2+
3+
module Ameba::Rule::Style
4+
describe HeredocIndent do
5+
subject = HeredocIndent.new
6+
7+
it "passes if heredoc body indented one level" do
8+
expect_no_issues subject, <<-CRYSTAL
9+
<<-HEREDOC
10+
hello world
11+
HEREDOC
12+
13+
<<-HEREDOC
14+
hello world
15+
HEREDOC
16+
CRYSTAL
17+
end
18+
19+
it "fails if the heredoc body is indented incorrectly" do
20+
expect_issue subject, <<-CRYSTAL
21+
<<-ONE
22+
# ^^^^ error: Heredoc body should be indented by 2 spaces
23+
hello world
24+
ONE
25+
26+
<<-TWO
27+
# ^^^^^^ error: Heredoc body should be indented by 2 spaces
28+
hello world
29+
TWO
30+
31+
<<-THREE
32+
# ^^^^^^^^ error: Heredoc body should be indented by 2 spaces
33+
hello world
34+
THREE
35+
36+
<<-FOUR
37+
# ^^^^^^^ error: Heredoc body should be indented by 2 spaces
38+
hello world
39+
FOUR
40+
CRYSTAL
41+
end
42+
43+
context "properties" do
44+
context "#indent_by" do
45+
rule = HeredocIndent.new
46+
rule.indent_by = 0
47+
48+
it "passes if heredoc body has the same indent level" do
49+
expect_no_issues rule, <<-CRYSTAL
50+
<<-HEREDOC
51+
hello world
52+
HEREDOC
53+
54+
<<-HEREDOC
55+
hello world
56+
HEREDOC
57+
CRYSTAL
58+
end
59+
60+
it "fails if the heredoc body is indented incorrectly" do
61+
expect_issue rule, <<-CRYSTAL
62+
<<-ONE
63+
# ^^^^ error: Heredoc body should be indented by 0 spaces
64+
hello world
65+
ONE
66+
67+
<<-TWO
68+
# ^^^^^^ error: Heredoc body should be indented by 0 spaces
69+
hello world
70+
TWO
71+
72+
<<-FOUR
73+
# ^^^^^^^ error: Heredoc body should be indented by 0 spaces
74+
hello world
75+
FOUR
76+
CRYSTAL
77+
end
78+
end
79+
end
80+
end
81+
end
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
module Ameba::Rule::Style
2+
# A rule that enforces _Heredoc_ bodies be indented one level above the indentation of the
3+
# line they're used on.
4+
#
5+
# For example, this is considered invalid:
6+
#
7+
# ```
8+
# <<-HERERDOC
9+
# hello world
10+
# HEREDOC
11+
#
12+
# <<-HERERDOC
13+
# hello world
14+
# HEREDOC
15+
# ```
16+
#
17+
# And should be written as:
18+
#
19+
# ```
20+
# <<-HERERDOC
21+
# hello world
22+
# HEREDOC
23+
#
24+
# <<-HERERDOC
25+
# hello world
26+
# HEREDOC
27+
# ```
28+
#
29+
# The `IndentBy` configuration option changes the enforced indentation level of the _heredoc_.
30+
#
31+
# ```
32+
# Style/HeredocIndent:
33+
# Enabled: true
34+
# IndentBy: 2
35+
# ```
36+
class HeredocIndent < Base
37+
properties do
38+
since_version "1.7.0"
39+
description "Recommends heredoc bodies are indented consistently"
40+
indent_by 2
41+
end
42+
43+
MSG = "Heredoc body should be indented by %s spaces"
44+
45+
def test(source, node : Crystal::StringInterpolation)
46+
return unless start_location = node.location
47+
48+
start_location_pos = source.pos(start_location)
49+
return unless source.code[start_location_pos..(start_location_pos + 2)]? == "<<-"
50+
51+
correct_indent = line_indent(source, start_location) + indent_by
52+
53+
unless node.heredoc_indent == correct_indent
54+
issue_for node, MSG % indent_by
55+
end
56+
end
57+
58+
private def line_indent(source, start_location) : Int32
59+
line_location = Crystal::Location.new(nil, start_location.line_number, 1)
60+
line_location_pos = source.pos(line_location)
61+
line = source.code[line_location_pos..(line_location_pos + start_location.column_number)]
62+
63+
line.size - line.lstrip.size
64+
end
65+
end
66+
end

0 commit comments

Comments
 (0)