diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index 314467ef0e..41219f2cd3 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -8,7 +8,17 @@ AllCops: require: ./Homebrew/rubocops.rb +Homebrew/FormulaCop: + Enabled: false + Homebrew/CorrectBottleBlock: + Include: + - '**/Taps/homebrew/**/*.rb' + Enabled: true + +Homebrew/FormulaDesc: + Include: + - '**/Taps/homebrew/**/*.rb' Enabled: true Metrics/AbcSize: diff --git a/Library/Homebrew/rubocops/bottle_block_cop.rb b/Library/Homebrew/rubocops/bottle_block_cop.rb index 55eb551524..733c492e88 100644 --- a/Library/Homebrew/rubocops/bottle_block_cop.rb +++ b/Library/Homebrew/rubocops/bottle_block_cop.rb @@ -1,20 +1,31 @@ +require_relative "./extend/formula_cop" + module RuboCop module Cop module Homebrew - class CorrectBottleBlock < Cop + # This cop audits `bottle` block in Formulae + # + # - `rebuild` should be used instead of `revision` in `bottle` block + + class CorrectBottleBlock < FormulaCop MSG = "Use rebuild instead of revision in bottle block".freeze - def on_block(node) - return if block_length(node).zero? - method, _args, body = *node - _keyword, method_name = *method - - return unless method_name == :bottle - check_revision?(body) + def audit_formula(_node, _class_node, _parent_class_node, formula_class_body_node) + check(formula_class_body_node) end private + def check(formula_class_body_node) + formula_class_body_node.each_child_node(:block) do |block_node| + next if block_length(block_node).zero? + method, _args, block_body = *block_node + _keyword, method_name = *method + next unless method_name == :bottle + check_revision?(block_body) + end + end + def autocorrect(node) lambda do |corrector| correction = node.source.sub("revision", "rebuild") diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb new file mode 100644 index 0000000000..cf5d513c93 --- /dev/null +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -0,0 +1,22 @@ +module RuboCop + module Cop + module Homebrew + class FormulaCop < Cop + @registry = Cop.registry + + def on_class(node) + # This method is called by RuboCop and is the main entry point + class_node, parent_class_node, body = *node + return unless a_formula_class?(parent_class_node) + audit_formula(node, class_node, parent_class_node, body) + end + + private + + def a_formula_class?(parent_class_node) + parent_class_node && parent_class_node.const_name == "Formula" + end + end + end + end +end diff --git a/Library/Homebrew/rubocops/formula_desc_cop.rb b/Library/Homebrew/rubocops/formula_desc_cop.rb index 8728c6fc02..dcd928d286 100644 --- a/Library/Homebrew/rubocops/formula_desc_cop.rb +++ b/Library/Homebrew/rubocops/formula_desc_cop.rb @@ -1,12 +1,20 @@ +require_relative "./extend/formula_cop" +require_relative "../extend/string" + module RuboCop module Cop module Homebrew - class FormulaDesc < Cop - def on_class(node) - class_node, parent_class_node, body = *node - formula_name = class_node.const_name - return unless parent_class_node && parent_class_node.const_name == "Formula" && body - check(node, body, formula_name) + # This cop audits `desc` in Formulae + # + # - Checks for existence of `desc` + # - Checks if size of `desc` > 80 + # - Checks if `desc` begins with an article + # - Checks for correct usage of `command-line` in `desc` + # - Checks if `desc` contains the formula name + + class FormulaDesc < FormulaCop + def audit_formula(node, class_node, _parent_class_node, body) + check(node, body, class_node.const_name) end private @@ -14,7 +22,7 @@ module RuboCop def check(node, body, formula_name) body.each_child_node(:send) do |call_node| _receiver, call_name, args = *call_node - next unless call_name == :desc && !args.children[0].empty? + next if call_name != :desc || args.children[0].empty? description = args.children[0] source_buffer = call_node.source_range.source_buffer @@ -27,27 +35,29 @@ module RuboCop column = desc_begin_pos - line_begin_pos length = call_node.children[2].source_range.size sourcerange = source_range(source_buffer, line_number, column, length) - message = <<-EOS.strip_indent - Description is too long. \"name: desc\" should be less than 80 characters. - Length is calculated as #{formula_name} + desc. (currently #{linelength}) - EOS + message = <<-EOS.undent + Description is too long. "name: desc" should be less than 80 characters. + Length is calculated as #{formula_name} + desc. (currently #{linelength}) + EOS add_offense(call_node, sourcerange, message) end - match_object = description.match(/([Cc]ommand ?line)/) + match_object = description.match(/(command ?line)/i) if match_object column = desc_begin_pos+match_object.begin(0)-line_begin_pos+1 length = match_object.to_s.length sourcerange = source_range(source_buffer, line_number, column, length) - add_offense(call_node, sourcerange, "Description should use \"command-line\" instead of \"#{match_object}\"") + message = "Description should use \"command-line\" instead of \"#{match_object}\"" + add_offense(call_node, sourcerange, message) end - match_object = description.match(/^([Aa]n?)\s/) + match_object = description.match(/^(an?)\s/i) if match_object column = desc_begin_pos+match_object.begin(0)-line_begin_pos+1 length = match_object.to_s.length sourcerange = source_range(source_buffer, line_number, column, length) - add_offense(call_node, sourcerange, "Description shouldn't start with an indefinite article (#{match_object})") + message = "Description shouldn't start with an indefinite article (#{match_object})" + add_offense(call_node, sourcerange, message) end match_object = description.match(/^#{formula_name}/i) @@ -55,9 +65,10 @@ module RuboCop column = desc_begin_pos+match_object.begin(0)-line_begin_pos+1 length = match_object.to_s.length sourcerange = source_range(source_buffer, line_number, column, length) - add_offense(call_node, sourcerange, "Description shouldn't include the formula name") + message = "Description shouldn't include the formula name" + add_offense(call_node, sourcerange, message) end - return + return nil end add_offense(node, node.source_range, "Formula should have a desc (Description).") end