Merge pull request #17651 from samford/audit_formula-struct-arg

This commit is contained in:
Mike McQuaid 2024-07-08 17:35:32 +01:00 committed by GitHub
commit d31150adf3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 204 additions and 128 deletions

View File

@ -10,8 +10,9 @@ module RuboCop
class BottleFormat < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
bottle_node = find_block(body_node, :bottle)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
bottle_node = find_block(formula_nodes.body_node, :bottle)
return if bottle_node.nil?
sha256_nodes = find_method_calls_by_name(bottle_node.body, :sha256)
@ -55,8 +56,9 @@ module RuboCop
class BottleTagIndentation < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
bottle_node = find_block(body_node, :bottle)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
bottle_node = find_block(formula_nodes.body_node, :bottle)
return if bottle_node.nil?
sha256_nodes = find_method_calls_by_name(bottle_node.body, :sha256)
@ -89,8 +91,9 @@ module RuboCop
class BottleDigestIndentation < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
bottle_node = find_block(body_node, :bottle)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
bottle_node = find_block(formula_nodes.body_node, :bottle)
return if bottle_node.nil?
sha256_nodes = find_method_calls_by_name(bottle_node.body, :sha256)
@ -123,8 +126,9 @@ module RuboCop
class BottleOrder < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
bottle_node = find_block(body_node, :bottle)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
bottle_node = find_block(formula_nodes.body_node, :bottle)
return if bottle_node.nil?
return if bottle_node.child_nodes.blank?

View File

@ -26,7 +26,8 @@ module RuboCop
# end
# ```
class Caveats < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, _body_node)
sig { override.params(_formula_nodes: FormulaNodes).void }
def audit_formula(_formula_nodes)
caveats_strings.each do |n|
if regex_match_group(n, /\bsetuid\b/i)
problem "Don't recommend `setuid` in the caveats, suggest `sudo` instead."

View File

@ -8,8 +8,9 @@ module RuboCop
module FormulaAudit
# This cop makes sure that deprecated checksums are not used.
class Checksum < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
problem "MD5 checksums are deprecated, please use SHA-256" if method_called_ever?(body_node, :md5)
@ -44,10 +45,9 @@ module RuboCop
class ChecksumCase < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sha256_calls = find_every_method_call_by_name(body_node, :sha256)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
sha256_calls = find_every_method_call_by_name(formula_nodes.body_node, :sha256)
sha256_calls.each do |sha256_call|
checksum = get_checksum_node(sha256_call)
next if checksum.nil?

View File

@ -16,7 +16,10 @@ module RuboCop
AmazonWebServicesFormula
].freeze
def audit_formula(_node, _class_node, parent_class_node, _body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
parent_class_node = formula_nodes.parent_class_node
parent_class = class_name(parent_class_node)
return unless DEPRECATED_CLASSES.include?(parent_class)
@ -30,8 +33,9 @@ module RuboCop
class Test < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
test = find_block(body_node, :test)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
test = find_block(formula_nodes.body_node, :test)
return unless test
if test.body.nil?
@ -69,11 +73,13 @@ module RuboCop
module FormulaAuditStrict
# This cop makes sure that a `test` block exists.
class TestPresent < FormulaCop
def audit_formula(_node, class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
return if find_block(body_node, :test)
return if find_node_method_by_name(body_node, :disable!)
offending_node(class_node) if body_node.nil?
offending_node(formula_nodes.class_node) if body_node.nil?
problem "A `test do` test block should be added"
end
end

View File

@ -14,8 +14,9 @@ module RuboCop
class ComponentsOrder < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
@present_components, @offensive_nodes = check_order(FORMULA_COMPONENT_PRECEDENCE_LIST, body_node)

View File

@ -20,8 +20,9 @@ module RuboCop
STABLE_MSG = "`stable do` should not be present without a `head` spec"
STABLE_BLOCK_METHODS = [:url, :sha256, :mirror, :version].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
urls = find_method_calls_by_name(body_node, :url)

View File

@ -13,8 +13,9 @@ module RuboCop
MSG = "Versioned formulae should not use `conflicts_with`. " \
"Use `keg_only :versioned_formula` instead."
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
find_method_calls_by_name(body_node, :conflicts_with).each do |conflicts_with_call|
next unless parameters(conflicts_with_call).last.respond_to? :values

View File

@ -13,7 +13,10 @@ module RuboCop
class DependencyOrder < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
check_dependency_nodes_order(body_node)
check_uses_from_macos_nodes_order(body_node)
([:head, :stable] + on_system_methods).each do |block_name|

View File

@ -10,7 +10,10 @@ module RuboCop
class DeprecateDisableDate < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
[:deprecate!, :disable!].each do |method|
node = find_node_method_by_name(body_node, method)
@ -39,7 +42,10 @@ module RuboCop
PUNCTUATION_MARKS = %w[. ! ?].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
[:deprecate!, :disable!].each do |method|
node = find_node_method_by_name(body_node, method)

View File

@ -13,10 +13,13 @@ module RuboCop
include DescHelper
extend AutoCorrector
def audit_formula(_node, class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
@name = @formula_name
desc_call = find_node_method_by_name(body_node, :desc)
offending_node(class_node) if body_node.nil?
offending_node(formula_nodes.class_node) if body_node.nil?
audit_desc(:formula, @name, desc_call)
end
end

View File

@ -18,6 +18,13 @@ module RuboCop
@registry = Cop.registry
class FormulaNodes < T::Struct
prop :node, RuboCop::AST::ClassNode
prop :class_node, RuboCop::AST::ConstNode
prop :parent_class_node, RuboCop::AST::ConstNode
prop :body_node, RuboCop::AST::Node
end
# This method is called by RuboCop and is the main entry point.
def on_class(node)
@file_path = processed_source.file_path
@ -27,19 +34,11 @@ module RuboCop
class_node, parent_class_node, @body = *node
@formula_name = Pathname.new(@file_path).basename(".rb").to_s
@tap_style_exceptions = nil
audit_formula(node, class_node, parent_class_node, @body)
audit_formula(FormulaNodes.new(node:, class_node:, parent_class_node:, body_node: @body))
end
sig {
abstract
.params(
node: RuboCop::AST::ClassNode,
class_node: RuboCop::AST::ConstNode,
parent_class_node: RuboCop::AST::ConstNode,
body_node: RuboCop::AST::Node,
).void
}
def audit_formula(node, class_node, parent_class_node, body_node); end
sig { abstract.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes); end
# Yields to block when there is a match.
#

View File

@ -8,13 +8,14 @@ module RuboCop
module FormulaAudit
# This cop makes sure that a formula's file permissions are correct.
class Files < FormulaCop
def audit_formula(node, _class_node, _parent_class_node, _body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return unless file_path
# Codespaces routinely screws up all permissions so don't complain there.
return if ENV["CODESPACES"] || ENV["HOMEBREW_CODESPACES"]
offending_node(node)
offending_node(formula_nodes.node)
actual_mode = File.stat(file_path).mode
# Check that the file is world-readable.
if actual_mode & 0444 != 0444

View File

@ -12,11 +12,13 @@ module RuboCop
include HomepageHelper
extend AutoCorrector
def audit_formula(_node, class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
homepage_node = find_node_method_by_name(body_node, :homepage)
if homepage_node.nil?
offending_node(class_node) if body_node.nil?
offending_node(formula_nodes.class_node) if body_node.nil?
problem "Formula should have a homepage."
return
end

View File

@ -10,8 +10,9 @@ module RuboCop
class KegOnly < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
keg_only_node = find_node_method_by_name(body_node, :keg_only)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
keg_only_node = find_node_method_by_name(formula_nodes.body_node, :keg_only)
return unless keg_only_node
allowlist = %w[

View File

@ -10,7 +10,8 @@ module RuboCop
module FormulaAudit
# This cop checks for various miscellaneous Homebrew coding styles.
class Lines < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, _body_node)
sig { override.params(_formula_nodes: FormulaNodes).void }
def audit_formula(_formula_nodes)
[:automake, :ant, :autoconf, :emacs, :expat, :libtool, :mysql, :perl,
:postgresql, :python, :python3, :rbenv, :ruby].each do |dependency|
next unless depends_on?(dependency)
@ -31,9 +32,11 @@ module RuboCop
# This cop makes sure that a space is used for class inheritance.
class ClassInheritance < FormulaCop
def audit_formula(_node, class_node, parent_class_node, _body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
parent_class_node = formula_nodes.parent_class_node
begin_pos = start_column(parent_class_node)
end_pos = end_column(class_node)
end_pos = end_column(formula_nodes.class_node)
return if begin_pos-end_pos == 3
problem "Use a space in class inheritance: " \
@ -43,7 +46,8 @@ module RuboCop
# This cop makes sure that template comments are removed.
class Comments < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, _body_node)
sig { override.params(_formula_nodes: FormulaNodes).void }
def audit_formula(_formula_nodes)
audit_comments do |comment|
[
"# PLEASE REMOVE",
@ -82,8 +86,9 @@ module RuboCop
# This cop makes sure that idiomatic `assert_*` statements are used.
class AssertStatements < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
find_every_method_call_by_name(body_node, :assert).each do |method|
if method_called_ever?(method, :include?) && !method_called_ever?(method, :!)
@ -107,8 +112,9 @@ module RuboCop
# This cop makes sure that `option`s are used idiomatically.
class OptionDeclarations < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
problem "Use new-style option definitions" if find_method_def(body_node, :options)
@ -192,8 +198,9 @@ module RuboCop
class MpiCheck < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
# Enforce use of OpenMPI for MPI dependency in core
return if formula_tap != "homebrew-core"
@ -211,8 +218,9 @@ module RuboCop
class QuicTLSCheck < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
# Enforce use of OpenSSL for TLS dependency in core
return if formula_tap != "homebrew-core"
@ -229,8 +237,9 @@ module RuboCop
# This cop makes sure that formulae do not depend on `pyoxidizer` at build-time
# or run-time.
class PyoxidizerCheck < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if formula_nodes.body_node.nil?
# Disallow use of PyOxidizer as a dependency in core
return if formula_tap != "homebrew-core"
return unless depends_on?("pyoxidizer")
@ -243,8 +252,9 @@ module RuboCop
class SafePopenCommands < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
test = find_block(body_node, :test)
@ -272,8 +282,9 @@ module RuboCop
class ShellVariables < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
popen_commands = [
:popen,
@ -302,8 +313,9 @@ module RuboCop
class LicenseArrays < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
license_node = find_node_method_by_name(body_node, :license)
return unless license_node
@ -319,8 +331,9 @@ module RuboCop
# This cop makes sure that nested `license` declarations are split onto multiple lines.
class Licenses < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
license_node = find_node_method_by_name(body_node, :license)
return unless license_node
@ -342,8 +355,9 @@ module RuboCop
class PythonVersions < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
python_formula_node = find_every_method_call_by_name(body_node, :depends_on).find do |dep|
string_content(parameters(dep).first).start_with? "python@"
@ -390,7 +404,10 @@ module RuboCop
NO_ON_SYSTEM_METHOD_NAMES = [:install, :post_install].freeze
NO_ON_SYSTEM_BLOCK_NAMES = [:service, :test].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
NO_ON_SYSTEM_METHOD_NAMES.each do |formula_method_name|
method_node = find_method_def(body_node, formula_method_name)
audit_on_system_blocks(method_node, formula_method_name) if method_node
@ -427,8 +444,9 @@ module RuboCop
ON_MACOS_BLOCKS = [:macos, *MACOS_VERSION_OPTIONS].map { |os| :"on_#{os}" }.freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
audit_macos_references(body_node,
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
audit_macos_references(formula_nodes.body_node,
allowed_methods: OnSystemConditionals::NO_ON_SYSTEM_METHOD_NAMES,
allowed_blocks: OnSystemConditionals::NO_ON_SYSTEM_BLOCK_NAMES + ON_MACOS_BLOCKS)
end
@ -438,8 +456,9 @@ module RuboCop
class GenerateCompletionsDSL < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
install = find_method_def(body_node, :install)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
install = find_method_def(formula_nodes.body_node, :install)
return if install.blank?
correctable_shell_completion_node(install) do |node, shell, base_name, executable, subcmd, shell_parameter|
@ -519,8 +538,9 @@ module RuboCop
class SingleGenerateCompletionsDSLCall < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
install = find_method_def(body_node, :install)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
install = find_method_def(formula_nodes.body_node, :install)
return if install.blank?
methods = find_every_method_call_by_name(install, :generate_completions_from_executable)
@ -577,8 +597,9 @@ module RuboCop
# This cop checks for other miscellaneous style violations.
class Miscellaneous < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
# FileUtils is included in Formula
# encfs modifies a file with this name, so check for some leading characters
@ -846,11 +867,12 @@ module RuboCop
module FormulaAuditStrict
# This cop makes sure that no build-time checks are performed.
class MakeCheck < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if formula_tap != "homebrew-core"
# Avoid build-time checks in homebrew/core
find_every_method_call_by_name(body_node, :system).each do |method|
find_every_method_call_by_name(formula_nodes.body_node, :system).each do |method|
next if @formula_name.start_with?("lib")
next if tap_style_exception? :make_check_allowlist
@ -870,7 +892,8 @@ module RuboCop
# This cop ensures that new formulae depending on removed Requirements are not used
class Requirements < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, _body_node)
sig { override.params(_formula_nodes: FormulaNodes).void }
def audit_formula(_formula_nodes)
problem "Formulae should depend on a versioned `openjdk` instead of :java" if depends_on? :java
problem "Formulae should depend on specific X libraries instead of :x11" if depends_on? :x11
problem "Formulae should not depend on :osxfuse" if depends_on? :osxfuse
@ -882,8 +905,9 @@ module RuboCop
class RustCheck < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
# Enforce use of `rust` for rust dependency in core
return if formula_tap != "homebrew-core"

View File

@ -11,8 +11,9 @@ module RuboCop
class LivecheckSkip < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
livecheck_node = find_block(formula_nodes.body_node, :livecheck)
return if livecheck_node.blank?
skip = find_every_method_call_by_name(livecheck_node, :skip).first
@ -39,8 +40,9 @@ module RuboCop
# This cop ensures that a `url` is specified in the `livecheck` block.
class LivecheckUrlProvided < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
livecheck_node = find_block(formula_nodes.body_node, :livecheck)
return unless livecheck_node
url_node = find_every_method_call_by_name(livecheck_node, :url).first
@ -62,7 +64,9 @@ module RuboCop
class LivecheckUrlSymbol < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
body_node = formula_nodes.body_node
livecheck_node = find_block(body_node, :livecheck)
return if livecheck_node.blank?
@ -117,8 +121,9 @@ module RuboCop
class LivecheckRegexParentheses < FormulaCop
extend AutoCorrector
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
livecheck_node = find_block(formula_nodes.body_node, :livecheck)
return if livecheck_node.blank?
skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
@ -144,8 +149,9 @@ module RuboCop
TAR_PATTERN = /\\?\.t(ar|(g|l|x)z$|[bz2]{2,4}$)(\\?\.((g|l|x)z)|[bz2]{2,4}|Z)?$/i
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
livecheck_node = find_block(formula_nodes.body_node, :livecheck)
return if livecheck_node.blank?
skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
@ -171,8 +177,9 @@ module RuboCop
# This cop ensures that a `regex` is provided when `strategy :page_match` is specified
# in the `livecheck` block.
class LivecheckRegexIfPageMatch < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
livecheck_node = find_block(body_node, :livecheck)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
livecheck_node = find_block(formula_nodes.body_node, :livecheck)
return if livecheck_node.blank?
skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?
@ -199,10 +206,11 @@ module RuboCop
MSG = "Regexes should be case-insensitive unless sensitivity is explicitly required for proper matching."
def audit_formula(_node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if tap_style_exception? :regex_case_sensitive_allowlist
livecheck_node = find_block(body_node, :livecheck)
livecheck_node = find_block(formula_nodes.body_node, :livecheck)
return if livecheck_node.blank?
skip = find_every_method_call_by_name(livecheck_node, :skip).first.present?

View File

@ -14,8 +14,9 @@ module RuboCop
DEP_OPTION = "Formulae in homebrew/core should not use `deprecated_option`."
OPTION = "Formulae in homebrew/core should not use `option`."
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
option_call_nodes = find_every_method_call_by_name(body_node, :option)
option_call_nodes.each do |option_call|

View File

@ -11,19 +11,21 @@ module RuboCop
class Patches < FormulaCop
extend AutoCorrector
def audit_formula(node, _class_node, _parent_class_node, body)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
node = formula_nodes.node
@full_source_content = source_buffer(node).source
return if body.nil?
return if (body_node = formula_nodes.body_node).nil?
external_patches = find_all_blocks(body, :patch)
external_patches = find_all_blocks(body_node, :patch)
external_patches.each do |patch_block|
url_node = find_every_method_call_by_name(patch_block, :url).first
url_string = parameters(url_node).first
patch_problems(url_string)
end
inline_patches = find_every_method_call_by_name(body, :patch)
inline_patches = find_every_method_call_by_name(body_node, :patch)
inline_patches.each { |patch| inline_patch_problems(patch) }
if inline_patches.empty? && patch_end?
@ -31,7 +33,7 @@ module RuboCop
add_offense(@offense_source_range, message: "patch is missing 'DATA'")
end
patches_node = find_method_def(body, :patches)
patches_node = find_method_def(body_node, :patches)
return if patches_node.nil?
legacy_patches = find_strings(patches_node)

View File

@ -10,8 +10,9 @@ module RuboCop
# to ensure that they also have the correct `uses_from_macos`
# dependencies.
class ResourceRequiresDependencies < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
resource_nodes = find_every_method_call_by_name(body_node, :resource)
return if resource_nodes.empty?

View File

@ -22,8 +22,9 @@ module RuboCop
# At least one of these methods must be defined in a service block.
REQUIRED_METHOD_CALLS = [:run, :name].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
service_node = find_block(body_node, :service)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
service_node = find_block(formula_nodes.body_node, :service)
return if service_node.blank?
method_calls = service_node.each_descendant(:send).group_by(&:method_name)

View File

@ -10,7 +10,9 @@ module RuboCop
class Text < FormulaCop
extend AutoCorrector
def audit_formula(node, _class_node, _parent_class_node, body_node)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
node = formula_nodes.node
full_source_content = source_buffer(node).source
if (match = full_source_content.match(/^require ['"]formula['"]$/))
@ -20,7 +22,7 @@ module RuboCop
end
end
return if body_node.nil?
return if (body_node = formula_nodes.body_node).nil?
if find_method_def(body_node, :plist)
problem "`def plist` is deprecated. Please use services instead: https://docs.brew.sh/Formula-Cookbook#service-files"
@ -113,8 +115,9 @@ module RuboCop
module FormulaAuditStrict
# This cop contains stricter checks for various problems in a formula's source code.
class Text < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
find_method_with_args(body_node, :go_resource) do
problem "`go_resource`s are deprecated. Please ask upstream to implement Go vendoring"

View File

@ -11,8 +11,9 @@ module RuboCop
class Urls < FormulaCop
include UrlHelper
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
urls = find_every_func_call_by_name(body_node, :url)
mirrors = find_every_func_call_by_name(body_node, :mirror)
@ -42,8 +43,9 @@ module RuboCop
# This cop makes sure that the correct format for PyPI URLs is used.
class PyPiUrls < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
urls = find_every_func_call_by_name(body_node, :url)
mirrors = find_every_func_call_by_name(body_node, :mirror)
@ -72,8 +74,9 @@ module RuboCop
# This cop makes sure that git URLs have a `revision`.
class GitUrls < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
return if formula_tap != "homebrew-core"
find_method_calls_by_name(body_node, :url).each do |url|
@ -94,8 +97,9 @@ module RuboCop
module FormulaAuditStrict
# This cop makes sure that git URLs have a `tag`.
class GitUrls < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
return if formula_tap != "homebrew-core"
find_method_calls_by_name(body_node, :url).each do |url|

View File

@ -59,8 +59,9 @@ module RuboCop
zlib
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
find_method_with_args(body_node, :keg_only, :provided_by_macos) do
return if PROVIDED_BY_MACOS_FORMULAE.include? @formula_name
@ -95,8 +96,9 @@ module RuboCop
zsh
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
return if body_node.nil?
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
return if (body_node = formula_nodes.body_node).nil?
depends_on_linux = depends_on?(:linux)

View File

@ -8,8 +8,9 @@ module RuboCop
module FormulaAudit
# This cop makes sure that a `version` is in the correct format.
class Version < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body_node)
version_node = find_node_method_by_name(body_node, :version)
sig { override.params(formula_nodes: FormulaNodes).void }
def audit_formula(formula_nodes)
version_node = find_node_method_by_name(formula_nodes.body_node, :version)
return unless version_node
version = string_content(parameters(version_node).first)