diff --git a/Library/Homebrew/rubocops/resource_requires_dependencies.rb b/Library/Homebrew/rubocops/resource_requires_dependencies.rb index c067208e10..f24c7f342f 100644 --- a/Library/Homebrew/rubocops/resource_requires_dependencies.rb +++ b/Library/Homebrew/rubocops/resource_requires_dependencies.rb @@ -6,7 +6,7 @@ require "rubocops/extend/formula_cop" module RuboCop module Cop module FormulaAudit - # This cop audits Python formulae that include the "lxml" resource + # This cop audits Python formulae that include certain resources # to ensure that they also have the correct `uses_from_macos` # dependencies. # @@ -16,15 +16,31 @@ module RuboCop return if body_node.nil? resource_nodes = find_every_method_call_by_name(body_node, :resource) - lxml = resource_nodes.find { |node| node.arguments.first.str_content == "lxml" } - return unless lxml + return if resource_nodes.empty? - uses_from_macos_nodes = find_every_method_call_by_name(body_node, :uses_from_macos) - dependencies = uses_from_macos_nodes.map { |node| node.arguments.first.str_content } - return if dependencies.include?("libxml2") && dependencies.include?("libxslt") + %w[lxml pyyaml].each do |resource_name| + found = resource_nodes.find { |node| node.arguments.first.str_content == resource_name } + next unless found - offending_node(lxml) - problem "Add `uses_from_macos` lines above for `\"libxml2\"` and `\"libxslt\"`." + uses_from_macos_nodes = find_every_method_call_by_name(body_node, :uses_from_macos) + uses_from_macos = uses_from_macos_nodes.map { |node| node.arguments.first.str_content } + + depends_on_nodes = find_every_method_call_by_name(body_node, :depends_on) + depends_on = depends_on_nodes.map { |node| node.arguments.first.str_content } + + required_deps = case resource_name + when "lxml" + kind = "uses_from_macos" + ["libxml2", "libxslt"] + when "pyyaml" + kind = "depends_on" + ["libyaml"] + end + next if required_deps.all? { |dep| uses_from_macos.include?(dep) || depends_on.include?(dep) } + + offending_node(found) + problem "Add `#{kind}` lines above for #{required_deps.map { |req| "`\"#{req}\"`" }.join(" and ")}." + end end end end diff --git a/Library/Homebrew/test/rubocops/resource_requires_dependencies_spec.rb b/Library/Homebrew/test/rubocops/resource_requires_dependencies_spec.rb index 581c5e6c3e..989918c7bd 100644 --- a/Library/Homebrew/test/rubocops/resource_requires_dependencies_spec.rb +++ b/Library/Homebrew/test/rubocops/resource_requires_dependencies_spec.rb @@ -5,6 +5,19 @@ require "rubocops/resource_requires_dependencies" RSpec.describe RuboCop::Cop::FormulaAudit::ResourceRequiresDependencies do subject(:cop) { described_class.new } + context "when a formula does not have any resources" do + it "does not report offenses" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + homepage "https://brew.sh" + + uses_from_macos "libxml2" + end + RUBY + end + end + context "when a formula does not have the lxml resource" do it "does not report offenses" do expect_no_offenses(<<~RUBY) @@ -59,4 +72,84 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ResourceRequiresDependencies do RUBY end end + + context "when a formula does not have the pyyaml resource" do + it "does not report offenses" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + homepage "https://brew.sh" + + uses_from_macos "libxml2" + + resource "not-pyyaml" do + url "blah" + sha256 "blah" + end + end + RUBY + end + end + + context "when a formula has the pyyaml resource" do + it "does not report offenses if the dependencies are present" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + homepage "https://brew.sh" + + depends_on "libyaml" + + resource "pyyaml" do + url "blah" + sha256 "blah" + end + end + RUBY + end + + it "reports offenses if missing a dependency" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + homepage "https://brew.sh" + + depends_on "not_libyaml" + + resource "pyyaml" do + ^^^^^^^^^^^^^^^^^ FormulaAudit/ResourceRequiresDependencies: Add `depends_on` lines above for `"libyaml"`. + url "blah" + sha256 "blah" + end + end + RUBY + end + end + + context "when a formula has multiple resources" do + it "reports offenses for each resource that is missing a dependency" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + homepage "https://brew.sh" + + uses_from_macos "one" + uses_from_macos "two" + depends_on "three" + + resource "lxml" do + ^^^^^^^^^^^^^^^ FormulaAudit/ResourceRequiresDependencies: Add `uses_from_macos` lines above for `"libxml2"` and `"libxslt"`. + url "blah" + sha256 "blah" + end + + resource "pyyaml" do + ^^^^^^^^^^^^^^^^^ FormulaAudit/ResourceRequiresDependencies: Add `depends_on` lines above for `"libyaml"`. + url "blah" + sha256 "blah" + end + end + RUBY + end + end end