Skip to content

Commit

Permalink
Fix bug in UnnecessaryInterpolation
Browse files Browse the repository at this point in the history
The UnnecessaryInterpolation linter would incorrectly report a lint for
tags with content that contained interpolation at the beginning, e.g.

  %tag #{interpolation} -- #{more_interpolation}

This was due to the really naive way we were checking if a string only
contained interpolation (only check if the first two characters were
`#{`).

Solve this by using the `extract_interpolated_values` helper originally
defined in the `ScriptExtractor`, but is now pulled out into the
`HamlLint::Utils` module.

Change-Id: I6eb1b2c06b4df0a3f6dc896e089636c853464bb1
Reviewed-on: http://gerrit.causes.com/42566
Tested-by: jenkins <[email protected]>
Reviewed-by: Shane da Silva <[email protected]>
  • Loading branch information
sds committed Sep 14, 2014
1 parent 84b3681 commit 3052573
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 25 deletions.
20 changes: 10 additions & 10 deletions lib/haml_lint/linter/unnecessary_interpolation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ class Linter::UnnecessaryInterpolation < Linter
include LinterRegistry

def visit_tag(node)
inline_content = node.script
return if inline_content.empty?
return if node.script.empty?

if contains_interpolation?(inline_content) &&
only_interpolation?(inline_content)
count = 0
chars = 2 # Include surrounding quote chars
HamlLint::Utils.extract_interpolated_values(node.script) do |interpolated_code|
count += 1
return if count > 1
chars += interpolated_code.length + 3
end

if chars == node.script.length
add_lint(node, '`%... \#{expression}` can be written without ' \
'interpolation as `%...= expression`')
end
end

private

def only_interpolation?(content)
content.lstrip.start_with?('"#{')
end
end
end
16 changes: 1 addition & 15 deletions lib/haml_lint/script_extractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def visit_filter(node)
add_line(line, node.line + index + 1)
end
else
extract_interpolated_values(node.text) do |interpolated_code|
HamlLint::Utils.extract_interpolated_values(node.text) do |interpolated_code|
add_line(interpolated_code, node)
end
end
Expand Down Expand Up @@ -150,19 +150,5 @@ def block_keyword(text)
return unless keyword = text.scan(Haml::Parser::BLOCK_KEYWORD_REGEX)[0]
keyword[0] || keyword[1]
end

# Yields interpolated values within a block of filter text.
def extract_interpolated_values(filter_text)
Haml::Util.handle_interpolation(filter_text.dump) do |scan|
escape_count = (scan[2].size - 1) / 2
scan.matched[0...-3 - escape_count]
if escape_count.even?
dumped_interpolated_str = Haml::Util.balance(scan, '{', '}', 1)[0][0...-1]

# Hacky way to turn a dumped string back into a regular string
yield eval('"' + dumped_interpolated_str + '"') # rubocop:disable Eval
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/haml_lint/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ def extract_files_from(list)
files.uniq
end

# Yields interpolated values within a block of filter text.
def extract_interpolated_values(filter_text)
Haml::Util.handle_interpolation(filter_text.dump) do |scan|
escape_count = (scan[2].size - 1) / 2
scan.matched[0...-3 - escape_count]
if escape_count.even?
dumped_interpolated_str = Haml::Util.balance(scan, '{', '}', 1)[0][0...-1]

# Hacky way to turn a dumped string back into a regular string
yield eval('"' + dumped_interpolated_str + '"') # rubocop:disable Eval
end
end
end

# Converts a string containing underscores/hyphens/spaces into CamelCase.
def camel_case(str)
str.split(/_|-| /).map { |part| part.sub(/^\w/) { |c| c.upcase } }.join
Expand Down
5 changes: 5 additions & 0 deletions spec/haml_lint/linter/unnecessary_interpolation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
it { should_not report_lint }
end

context 'when tag contains inline text with interpolation at the start' do
let(:haml) { '%tag #{interpolation} -- #{more_interpolation}' }
it { should_not report_lint }
end

context 'when tag contains inline text with only interpolation' do
let(:haml) { '%tag #{only_interpolation}' }
it { should report_lint }
Expand Down

0 comments on commit 3052573

Please sign in to comment.