Skip to content

Commit

Permalink
Fix cases where Rubocop (so Haml-Lint) indents a line too little (#433)
Browse files Browse the repository at this point in the history
This could happen with multiline scripts.
  • Loading branch information
MaxLap authored Aug 6, 2023
1 parent 81a3b41 commit 821425f
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# HAML-Lint Changelog

* Fix some cases where part of multiline scripts could end up less indented than the
starting line of that script.

### 0.49.2

* Fix handling of interpolation of plain when the plain is spread over multiple lines using pipes
Expand Down
13 changes: 10 additions & 3 deletions lib/haml_lint/ruby_extraction/script_chunk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,22 @@ def self.format_ruby_lines_to_haml_lines(to_ruby_lines, script_output_ruby_prefi
statement_start_line_indexes = find_statement_start_line_indexes(to_ruby_lines)

continued_line_indent_delta = 2
continued_line_min_indent = 2

cur_line_start_index = nil
line_start_indexes_that_need_pipes = []
haml_output_prefix = first_output_haml_prefix
to_haml_lines = to_ruby_lines.map.with_index do |line, i|
to_haml_lines = to_ruby_lines.map.with_index do |line, i| # rubocop:disable Metrics/BlockLength
if line !~ /\S/
# whitespace or empty lines, we don't want any indentation
''
elsif statement_start_line_indexes.include?(i)
cur_line_start_index = i
code_start = line.index(/\S/)
continued_line_min_indent = code_start + 2
if line[code_start..].start_with?(script_output_ruby_prefix)
line = line.sub(script_output_ruby_prefix, '')
# The line may have been too indented because of the "HL.out = " prefix
# The next lines may have been too indented because of the "HL.out = " prefix
continued_line_indent_delta = 2 - script_output_ruby_prefix.size
new_line = "#{line[0...code_start]}#{haml_output_prefix} #{line[code_start..]}"
haml_output_prefix = '='
Expand All @@ -134,7 +136,12 @@ def self.format_ruby_lines_to_haml_lines(to_ruby_lines, script_output_ruby_prefi
line_start_indexes_that_need_pipes << cur_line_start_index
end

HamlLint::Utils.indent(line, continued_line_indent_delta)
line = HamlLint::Utils.indent(line, continued_line_indent_delta)
cur_indent = line[/^ */].size
if cur_indent < continued_line_min_indent
line = HamlLint::Utils.indent(line, continued_line_min_indent - cur_indent)
end
line
end
end

Expand Down
92 changes: 91 additions & 1 deletion spec/haml_lint/linter/rubocop_autocorrect_edge_cases_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,96 @@
end
end

# TO TEST: %tag #{expression}
context 'correct multiline brace layout of new_line with right indentation in silent script' do
let(:config) do
# need to be an instance variable to avoid the TempFile cleaning up too soon
@config_file = Tempfile.new(%w[my-rubo-cop.yml]).tap do |f|
f.write(<<~CONF)
Style/MultilineHashBraceLayout:
Enabled: true
EnforcedStyle: new_line
Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: consistent_comma
CONF
f.close
end
super().merge('config_file' => @config_file.path)
end

let(:start_haml) { <<~HAML }
%tag
- a = render 'something',
locals: {foo: bar,
spam: 'more',}
HAML

let(:end_haml) { <<~HAML }
%tag
- a = render 'something',
locals: { foo: bar,
spam: 'more',
}
HAML

it do
subject.run_or_raise(document, autocorrect: autocorrect)

matcher = eq(end_haml)
document.source.should(
matcher,
-> { "Final HAML is different from expected. #{matcher.failure_message}\n#{format_lints}" }
)

haml_different = start_haml != end_haml
document.source_was_changed.should == haml_different
end
end

context 'correct multiline brace layout of new_line with right indentation in outputting script' do
let(:config) do
# need to be an instance variable to avoid the TempFile cleaning up too soon
@config_file = Tempfile.new(%w[my-rubo-cop.yml]).tap do |f|
f.write(<<~CONF)
Style/MultilineHashBraceLayout:
Enabled: true
EnforcedStyle: new_line
Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: consistent_comma
CONF
f.close
end
super().merge('config_file' => @config_file.path)
end

let(:start_haml) { <<~HAML }
%tag
= render 'something',
locals: {foo: bar,
spam: 'more',}
HAML

let(:end_haml) { <<~HAML }
%tag
= render 'something',
locals: { foo: bar,
spam: 'more',
}
HAML

it do
subject.run_or_raise(document, autocorrect: autocorrect)

matcher = eq(end_haml)
document.source.should(
matcher,
-> { "Final HAML is different from expected. #{matcher.failure_message}\n#{format_lints}" }
)

haml_different = start_haml != end_haml
document.source_was_changed.should == haml_different
end
end
end
end

0 comments on commit 821425f

Please sign in to comment.