diff --git a/Gemfile.lock b/Gemfile.lock index eecdbe3..1d6d837 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - erblint-github (0.4.0) + erblint-github (0.4.1) GEM remote: https://rubygems.org/ @@ -44,7 +44,7 @@ GEM nokogiri (>= 1.12.0) mini_portile2 (2.8.2) minitest (5.18.0) - mocha (2.0.2) + mocha (2.0.4) ruby2_keywords (>= 0.0.5) nokogiri (1.15.2) mini_portile2 (~> 2.8.2) diff --git a/erblint-github.gemspec b/erblint-github.gemspec index 0fc6c4d..7ee6e32 100644 --- a/erblint-github.gemspec +++ b/erblint-github.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = "erblint-github" - s.version = "0.4.0" + s.version = "0.4.1" s.summary = "erblint GitHub" s.description = "Template style checking for GitHub Ruby repositories" s.homepage = "https://github.com/github/erblint-github" diff --git a/lib/erblint-github/linters/custom_helpers.rb b/lib/erblint-github/linters/custom_helpers.rb index 8563a59..ff953b5 100644 --- a/lib/erblint-github/linters/custom_helpers.rb +++ b/lib/erblint-github/linters/custom_helpers.rb @@ -27,6 +27,39 @@ def possible_attribute_values(tag, attr_name) [value].compact end + def counter_correct?(processed_source) + comment_node = nil + expected_count = 0 + rule_name = self.class.name.gsub("ERBLint::Linters::", "") + offenses_count = @offenses.length + + processed_source.parser.ast.descendants(:erb).each do |node| + indicator_node, _, code_node, = *node + indicator = indicator_node&.loc&.source + comment = code_node&.loc&.source&.strip + + if indicator == "#" && comment.start_with?("erblint:counter") && comment.match(rule_name) + comment_node = node + expected_count = comment.match(/\s(\d+)\s?$/)[1].to_i + end + end + + if offenses_count.zero? + # have to adjust to get `\n` so we delete the whole line + add_offense(processed_source.to_source_range(comment_node.loc.adjust(end_pos: 1)), "Unused erblint:counter comment for #{rule_name}", "") if comment_node + return + end + + first_offense = @offenses[0] + + if comment_node.nil? + add_offense(processed_source.to_source_range(first_offense.source_range), "#{rule_name}: If you must, add <%# erblint:counter #{rule_name} #{offenses_count} %> to bypass this check.", "<%# erblint:counter #{rule_name} #{offenses_count} %>") + else + clear_offenses + add_offense(processed_source.to_source_range(comment_node.loc), "Incorrect erblint:counter number for #{rule_name}. Expected: #{expected_count}, actual: #{offenses_count}.", "<%# erblint:counter #{rule_name} #{offenses_count} %>") if expected_count != offenses_count + end + end + # Map possible values from condition def basic_conditional_code_check(code) conditional_match = code.match(/["'](.+)["']\sif|unless\s.+/) || code.match(/.+\s?\s["'](.+)["']\s:\s["'](.+)["']/)