From ff1ef25815b4094320b8fdb709429e9aa1fee6f9 Mon Sep 17 00:00:00 2001 From: Kazue Urabe Date: Wed, 10 Jan 2024 09:46:09 +0900 Subject: [PATCH] Fix Linter ControlStatementSpacing raise incorrect = (#164) This commit is to resolve issue https://github.com/sds/slim-lint/issues/101 . I'm not familiar with OSS, so I apologize if I'm being impolite. I'm also using machine translation for English. --- .../linter/control_statement_spacing.rb | 34 ++++++- .../linter/control_statement_spacing_spec.rb | 98 +++++++++++++++++++ 2 files changed, 130 insertions(+), 2 deletions(-) diff --git a/lib/slim_lint/linter/control_statement_spacing.rb b/lib/slim_lint/linter/control_statement_spacing.rb index 964ff4d..977fc81 100644 --- a/lib/slim_lint/linter/control_statement_spacing.rb +++ b/lib/slim_lint/linter/control_statement_spacing.rb @@ -9,8 +9,14 @@ class Linter::ControlStatementSpacing < Linter on [:html, :tag, anything, [], [:slim, :output, anything, capture(:ruby, anything)]] do |sexp| - # Fetch original Slim code that contains an element with a control statement. - line = document.source_lines[sexp.line - 1] + # Process original slim code so that multi-line attributes become single line. + # And store the correction line count + source = merge_multiline_attributes(document.source_lines) + + # Fetch processed Slim code that contains an element with a control statement. + line = source[sexp.line - 1][:line] + # Apply correction to the line count. + sexp.line += source[sexp.line - 1][:line_count] # Remove any Ruby code, because our regexp below must not match inside Ruby. ruby = captures[:ruby] @@ -20,5 +26,29 @@ class Linter::ControlStatementSpacing < Linter report_lint(sexp, MESSAGE) end + + private + + def merge_multiline_attributes(source_lines) + result = [] + memo = '' + correction_line_count = 0 + + source_lines.each do |line| + memo += line.chomp('\\') + + # Lines ending in a backslash are concatenated with the next line + # And count the number of lines to correct the sexp line count. + if line.match?(/\\$/) + correction_line_count += 1 + next + end + + # Add merged rows and correction line count to the result and reset the memo + result << { line: memo, line_count: correction_line_count } + memo = '' + end + result + end end end diff --git a/spec/slim_lint/linter/control_statement_spacing_spec.rb b/spec/slim_lint/linter/control_statement_spacing_spec.rb index 81cc771..f9d2279 100644 --- a/spec/slim_lint/linter/control_statement_spacing_spec.rb +++ b/spec/slim_lint/linter/control_statement_spacing_spec.rb @@ -175,6 +175,104 @@ it { should_not report_lint } end + context 'when an element has a multi-line attribute' do + # OK + context 'when it is simple' do + let(:slim) { <<-'SLIM' } + div class='one \ + two' + div = some_method + SLIM + + it { should_not report_lint } + end + + context 'when it is more than two lines' do + let(:slim) { <<-'SLIM' } + div class='one \ + two three four \ + five six seven \ + eight nine ten eleven twelve' + div = some_method + SLIM + + it { should_not report_lint } + end + + context 'when it has more than two locations' do + let(:slim) { <<-'SLIM' } + div class='one \ + two' + div class='one \ + two three four five six seven \ + eight nine ten eleven twelve' + div class='one \ + two three four five six seven \ + eight nine ten eleven twelve' + div = some_method + SLIM + + it { should_not report_lint } + end + + # NG + context 'when it is simple' do + let(:slim) { <<-'SLIM' } + div class='one \ + two' + div= some_method + SLIM + + it { should report_lint line: 3 } + end + + context 'when it is more than two lines' do + let(:slim) { <<-'SLIM' } + div class='one \ + two three four \ + five six seven \ + eight nine ten eleven twelve' + div =some_method + SLIM + + it { should report_lint line: 5 } + end + + context 'when it has more than two locations' do + let(:slim) { <<-'SLIM' } + div class='one \ + two' + div class='one \ + two three four five six seven \ + eight nine ten eleven twelve' + div class='one \ + two three four five six seven \ + eight nine ten eleven twelve' + div=some_method + SLIM + + it { should report_lint line: 9 } + end + + context 'when it has more than two locations and verify the correctness of the line count.' do + let(:slim) { <<-'SLIM' } + div class='one \ + two' + div class='one \ + two three four five six seven \ + eight nine ten eleven twelve' + div=some_method_one + div class='one \ + two three four five six seven \ + eight nine ten eleven twelve' + div=some_method_two + SLIM + + it { should report_lint line: 6 } + it { should report_lint line: 10 } + end + end + context 'when leading whitespace (=<) is used' do context 'and it has appropriate spacing' do let(:slim) { 'title =< "Something"' }