Skip to content

Commit

Permalink
Fix block_keyword method returning keywords used as arguments of me…
Browse files Browse the repository at this point in the history
…thod call (#505)

* Fix `block_keyword` method returning keywords used as arguments of methods

* Fix linter errors

* Replace block keyword regex by custom regex to correctly handle newlines

Co-authored-by: Maxime Lapointe <maxhlap@gmail.com>

---------

Co-authored-by: Maxime Lapointe <maxhlap@gmail.com>
  • Loading branch information
Adrian-Hirt and MaxLap committed Apr 27, 2024
1 parent ba2a693 commit 5c464eb
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
6 changes: 5 additions & 1 deletion lib/haml_lint/ruby_extraction/chunk_extractor.rb
Expand Up @@ -17,6 +17,10 @@ class ChunkExtractor
::Haml::Parser.new('', {})
end

# HAML strips newlines when handling multi-line statements (using pipes or trailing comma)
# We don't. So the regex must be fixed to correctly detect the start of the string.
BLOCK_KEYWORD_REGEX = Regexp.new(Haml::Parser::BLOCK_KEYWORD_REGEX.source.sub('^', '\A'))

def initialize(document, script_output_prefix:)
@document = document
@script_output_prefix = script_output_prefix
Expand Down Expand Up @@ -692,7 +696,7 @@ def self.block_keyword(code)
return keyword
end

return unless keyword = code.scan(Haml::Parser::BLOCK_KEYWORD_REGEX)[0]
return unless keyword = code.scan(BLOCK_KEYWORD_REGEX)[0]
keyword[0] || keyword[1]
end
end
Expand Down
69 changes: 69 additions & 0 deletions spec/haml_lint/ruby_extraction/chunk_extractor_spec.rb
Expand Up @@ -213,4 +213,73 @@ def do_test
end
end
end

describe '.block_keyword' do
it 'should work for empty strings' do
expect(described_class.block_keyword('')).to eq(nil)
expect(described_class.block_keyword(' ')).to eq(nil)
end

it 'should extract keywords from simple input' do
# Cases where we can use `<keyword> value`
%w[if unless case].each do |keyword|
input = <<~HAML
- #{keyword} foobar
= foo
HAML

expect(described_class.block_keyword(input)).to eq(keyword)
end

# Case for the `begin` keyword
begin_input = <<~HAML
- begin
HAML

expect(described_class.block_keyword(begin_input)).to eq('begin')

# Case for the `for` keyword
for_input = <<~HAML
for user in User.all do
HAML

expect(described_class.block_keyword(for_input)).to eq('for')

# Cases where we can use `<keyword> value do`
%w[until while].each do |keyword|
input = <<~HAML
#{keyword} foobar do
HAML

expect(described_class.block_keyword(input)).to eq(keyword)
end
end

it 'should not raise exception when keyword is used as keyword argument' do
# Everything on single line, should work
input_single_line = '= helper foo: true, bar: true, if: false'
expect(described_class.block_keyword(input_single_line)).to eq(nil)

# Keyword as symbol not first on new line should work
input_multiline1 = <<~HAML
= helper foo: true,
bar: true, if: false
HAML
expect(described_class.block_keyword(input_multiline1)).to eq(nil)

# Keyword as symbol first on new line should also work
input_multiline2 = <<~HAML
= helper foo: true, bar: true,
if: false
HAML
expect(described_class.block_keyword(input_multiline2)).to eq(nil)

# Testing with another keyword
input_multiline3 = <<~HAML
= helper foo: true, bar: true,
for: User.first
HAML
expect(described_class.block_keyword(input_multiline3)).to eq(nil)
end
end
end

0 comments on commit 5c464eb

Please sign in to comment.