diff options
| -rw-r--r-- | Library/.rubocop.yml | 6 | ||||
| -rw-r--r-- | Library/Homebrew/dev-cmd/audit.rb | 21 | ||||
| -rw-r--r-- | Library/Homebrew/rubocops.rb | 1 | ||||
| -rw-r--r-- | Library/Homebrew/rubocops/extend/formula_cop.rb | 19 | ||||
| -rw-r--r-- | Library/Homebrew/rubocops/options_cop.rb | 47 | ||||
| -rw-r--r-- | Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb | 2 | ||||
| -rw-r--r-- | Library/Homebrew/test/rubocops/conflicts_cop_spec.rb | 6 | ||||
| -rw-r--r-- | Library/Homebrew/test/rubocops/options_cop_spec.rb | 105 |
8 files changed, 171 insertions, 36 deletions
diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index 6bfb669fd..bb437f15c 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -21,6 +21,12 @@ FormulaAudit/ChecksumCase: FormulaAudit/Conflicts: Enabled: true +FormulaAudit/Options: + Enabled: true + +FormulaAuditStrict/Options: + Enabled: true + FormulaAuditStrict/BottleBlock: Enabled: true diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 3bbfa461a..e144fc35c 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -554,27 +554,6 @@ class FormulaAuditor end def audit_options - formula.options.each do |o| - if o.name == "32-bit" - problem "macOS has been 64-bit only since 10.6 so 32-bit options are deprecated." - end - - next unless @strict - - if o.name == "universal" - problem "macOS has been 64-bit only since 10.6 so universal options are deprecated." - end - - if o.name !~ /with(out)?-/ && o.name != "c++11" && o.name != "universal" - problem "Options should begin with with/without. Migrate '--#{o.name}' with `deprecated_option`." - end - - next unless o.name =~ /^with(out)?-(?:checks?|tests)$/ - unless formula.deps.any? { |d| d.name == "check" && (d.optional? || d.recommended?) } - problem "Use '--with#{Regexp.last_match(1)}-test' instead of '--#{o.name}'. Migrate '--#{o.name}' with `deprecated_option`." - end - end - return unless @new_formula return if formula.deprecated_options.empty? return if formula.versioned_formula? diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb index 81ea2fcf2..f673720a6 100644 --- a/Library/Homebrew/rubocops.rb +++ b/Library/Homebrew/rubocops.rb @@ -8,3 +8,4 @@ require_relative "./rubocops/caveats_cop" require_relative "./rubocops/checksum_cop" require_relative "./rubocops/legacy_patches_cop" require_relative "./rubocops/conflicts_cop" +require_relative "./rubocops/options_cop" diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb index ddfb507d2..7165ee354 100644 --- a/Library/Homebrew/rubocops/extend/formula_cop.rb +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -102,14 +102,11 @@ module RuboCop # Returns nil if does not depend on dependency_name # args: node - dependency_name - dependency's name - def depends_on?(dependency_name) + def depends_on?(dependency_name, *types) + types = [:required, :build, :optional, :recommended, :run] if types.empty? dependency_nodes = find_every_method_call_by_name(@body, :depends_on) idx = dependency_nodes.index do |n| - depends_on_name_type?(n, dependency_name, :required) || - depends_on_name_type?(n, dependency_name, :build) || - depends_on_name_type?(n, dependency_name, :optional) || - depends_on_name_type?(n, dependency_name, :recommended) || - depends_on_name_type?(n, dependency_name, :run) + types.any? { |type| depends_on_name_type?(n, dependency_name, type) } end return if idx.nil? @offense_source_range = dependency_nodes[idx].source_range @@ -138,6 +135,8 @@ module RuboCop if type_match && !name_match name_match = node_equals?(node.method_args.first.keys.first.children.first, name) end + else + type_match = false end if type_match || name_match @@ -334,11 +333,13 @@ module RuboCop def string_content(node) case node.type when :str - return node.str_content if node.type == :str + node.str_content when :dstr - return node.each_child_node(:str).map(&:str_content).join("") if node.type == :dstr + node.each_child_node(:str).map(&:str_content).join("") when :const - return node.const_name if node.type == :const + node.const_name + when :sym + node.children.first.to_s else "" end diff --git a/Library/Homebrew/rubocops/options_cop.rb b/Library/Homebrew/rubocops/options_cop.rb new file mode 100644 index 000000000..eb2a837be --- /dev/null +++ b/Library/Homebrew/rubocops/options_cop.rb @@ -0,0 +1,47 @@ +require_relative "./extend/formula_cop" + +module RuboCop + module Cop + module FormulaAudit + # This cop audits `options` in Formulae + class Options < FormulaCop + DEPRECATION_MSG = "macOS has been 64-bit only since 10.6 so 32-bit options are deprecated.".freeze + + def audit_formula(_node, _class_node, _parent_class_node, body_node) + option_call_nodes = find_every_method_call_by_name(body_node, :option) + option_call_nodes.each do |option_call| + option = parameters(option_call).first + problem DEPRECATION_MSG if regex_match_group(option, /32-bit/) + end + end + end + end + + module FormulaAuditStrict + class Options < FormulaCop + DEPRECATION_MSG = "macOS has been 64-bit only since 10.6 so universal options are deprecated.".freeze + + def audit_formula(_node, _class_node, _parent_class_node, body_node) + option_call_nodes = find_every_method_call_by_name(body_node, :option) + option_call_nodes.each do |option_call| + offending_node(option_call) + option = string_content(parameters(option_call).first) + problem DEPRECATION_MSG if option == "universal" + + if option !~ /with(out)?-/ && + option != "cxx11" && + option != "universal" + problem "Options should begin with with/without."\ + " Migrate '--#{option}' with `deprecated_option`." + end + + next unless option =~ /^with(out)?-(?:checks?|tests)$/ + next if depends_on?("check", :optional, :recommended) + problem "Use '--with#{Regexp.last_match(1)}-test' instead of '--#{option}'."\ + " Migrate '--#{option}' with `deprecated_option`." + end + end + end + end + end +end diff --git a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb index a775b0b17..563f7ad4b 100644 --- a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb @@ -18,7 +18,7 @@ describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do end EOS - expected_offenses = [{ message: "Use rebuild instead of revision in bottle block", + expected_offenses = [{ message: described_class::MSG, severity: :convention, line: 5, column: 4, diff --git a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb index c3175509a..4fbab6c9e 100644 --- a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb @@ -16,11 +16,7 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do end EOS - msg = <<-EOS.undent - Versioned formulae should not use `conflicts_with`. - Use `keg_only :versioned_formula` instead. - EOS - expected_offenses = [{ message: msg, + expected_offenses = [{ message: described_class::MSG, severity: :convention, line: 3, column: 2, diff --git a/Library/Homebrew/test/rubocops/options_cop_spec.rb b/Library/Homebrew/test/rubocops/options_cop_spec.rb new file mode 100644 index 000000000..161f2a87a --- /dev/null +++ b/Library/Homebrew/test/rubocops/options_cop_spec.rb @@ -0,0 +1,105 @@ +require "rubocop" +require "rubocop/rspec/support" +require_relative "../../extend/string" +require_relative "../../rubocops/options_cop" + +describe RuboCop::Cop::FormulaAudit::Options do + subject(:cop) { described_class.new } + + context "When auditing options" do + it "32-bit" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option "32-bit", "with 32-bit" + end + EOS + + expected_offenses = [{ message: described_class::DEPRECATION_MSG, + severity: :convention, + line: 3, + column: 10, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + end +end + +describe RuboCop::Cop::FormulaAuditStrict::Options do + subject(:cop) { described_class.new } + + context "When auditing options strictly" do + it "with universal" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option :universal + end + EOS + + expected_offenses = [{ message: described_class::DEPRECATION_MSG, + severity: :convention, + line: 3, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "with deprecated options" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option :cxx11 + option "examples", "with-examples" + end + EOS + + MSG_1 = "Options should begin with with/without."\ + " Migrate '--examples' with `deprecated_option`.".freeze + expected_offenses = [{ message: MSG_1, + severity: :convention, + line: 4, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + + it "with misc deprecated options" do + source = <<-EOS.undent + class Foo < Formula + url 'http://example.com/foo-1.0.tgz' + option "without-check" + end + EOS + + MSG_2 = "Use '--without-test' instead of '--without-check'."\ + " Migrate '--without-check' with `deprecated_option`.".freeze + expected_offenses = [{ message: MSG_2, + severity: :convention, + line: 3, + column: 2, + source: source }] + + inspect_source(cop, source) + + expected_offenses.zip(cop.offenses).each do |expected, actual| + expect_offense(expected, actual) + end + end + end +end |
