mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
More Sorbet typed: strict
RuboCops
- Some of these I bumped to `typed: strict`, some of them I added intermediary type signatures to some of the methods to make my life easier in the (near, hopefully) future. - Turns out that RuboCop node matchers that end in `?` can return `nil` if they don't match anything, not `false`.
This commit is contained in:
parent
4ee6e96bdf
commit
0fc1eb534b
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
@ -44,6 +44,7 @@ module RuboCop
|
||||
)
|
||||
PATTERN
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).void }
|
||||
def on_or(node)
|
||||
nil_or_empty?(node) do |var1, var2|
|
||||
return if var1 != var2
|
||||
@ -57,14 +58,16 @@ module RuboCop
|
||||
|
||||
private
|
||||
|
||||
sig { params(corrector: RuboCop::Cop::Corrector, node: RuboCop::AST::Node).void }
|
||||
def autocorrect(corrector, node)
|
||||
variable1, _variable2 = nil_or_empty?(node)
|
||||
range = node.source_range
|
||||
corrector.replace(range, replacement(variable1))
|
||||
end
|
||||
|
||||
sig { params(node: T.nilable(RuboCop::AST::Node)).returns(String) }
|
||||
def replacement(node)
|
||||
node.respond_to?(:source) ? "#{node.source}.blank?" : "blank?"
|
||||
node.respond_to?(:source) ? "#{node&.source}.blank?" : "blank?"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -174,12 +174,14 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(nodes: T::Array[RuboCop::AST::SendNode]).returns(T::Array[T.any(String, Symbol)]) }
|
||||
def sha256_order(nodes)
|
||||
nodes.map do |node|
|
||||
sha256_bottle_tag node
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(node: AST::SendNode).returns(T.any(String, Symbol)) }
|
||||
def sha256_bottle_tag(node)
|
||||
hash_pair = node.last_argument.pairs.last
|
||||
if hash_pair.key.sym_type?
|
||||
|
@ -7,6 +7,7 @@ module RuboCop
|
||||
class ArrayAlphabetization < Base
|
||||
extend AutoCorrector
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).void }
|
||||
def on_send(node)
|
||||
return unless [:zap, :uninstall].include?(node.method_name)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -23,6 +23,7 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(checksum: T.nilable(RuboCop::AST::Node)).void }
|
||||
def audit_sha256(checksum)
|
||||
return if checksum.nil?
|
||||
|
||||
@ -37,7 +38,7 @@ module RuboCop
|
||||
|
||||
return unless regex_match_group(checksum, /[^a-f0-9]+/i)
|
||||
|
||||
add_offense(@offensive_source_range, message: "sha256 contains invalid characters")
|
||||
add_offense(T.must(@offensive_source_range), message: "sha256 contains invalid characters")
|
||||
end
|
||||
end
|
||||
|
||||
@ -54,9 +55,9 @@ module RuboCop
|
||||
next unless regex_match_group(checksum, /[A-F]+/)
|
||||
|
||||
add_offense(@offensive_source_range, message: "sha256 should be lowercase") do |corrector|
|
||||
correction = @offensive_node.source.downcase
|
||||
corrector.insert_before(@offensive_node.source_range, correction)
|
||||
corrector.remove(@offensive_node.source_range)
|
||||
correction = T.must(@offensive_node).source.downcase
|
||||
corrector.insert_before(T.must(@offensive_node).source_range, correction)
|
||||
corrector.remove(T.must(@offensive_node).source_range)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -62,6 +62,7 @@ module RuboCop
|
||||
(sym :blank?)))
|
||||
PATTERN
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).void }
|
||||
def on_send(node)
|
||||
return unless bad_method?(node)
|
||||
|
||||
@ -74,6 +75,7 @@ module RuboCop
|
||||
|
||||
private
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).returns(T::Boolean) }
|
||||
def bad_method?(node)
|
||||
return true if reject_with_block_pass?(node)
|
||||
|
||||
@ -93,6 +95,7 @@ module RuboCop
|
||||
arguments.length == 2 && arguments[1].source == receiver_in_block.source
|
||||
end
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).returns(Parser::Source::Range) }
|
||||
def offense_range(node)
|
||||
end_pos = if node.parent&.block_type? && node.parent&.send_node == node
|
||||
node.parent.source_range.end_pos
|
||||
@ -103,6 +106,7 @@ module RuboCop
|
||||
range_between(node.loc.selector.begin_pos, end_pos)
|
||||
end
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).returns(String) }
|
||||
def preferred_method(node)
|
||||
node.method?(:reject) ? "compact_blank" : "compact_blank!"
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -22,7 +22,7 @@ module RuboCop
|
||||
|
||||
reason = parameters(conflicts_with_call).last.values.first
|
||||
offending_node(reason)
|
||||
name = Regexp.new(@formula_name, Regexp::IGNORECASE)
|
||||
name = Regexp.new(T.must(@formula_name), Regexp::IGNORECASE)
|
||||
reason_text = string_content(reason).sub(name, "")
|
||||
first_word = reason_text.split.first
|
||||
|
||||
@ -45,7 +45,7 @@ module RuboCop
|
||||
if !tap_style_exception?(:versioned_formulae_conflicts_allowlist) && method_called_ever?(body_node,
|
||||
:conflicts_with)
|
||||
problem MSG do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "keg_only :versioned_formula")
|
||||
corrector.replace(T.must(@offensive_node).source_range, "keg_only :versioned_formula")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -61,13 +61,13 @@ module RuboCop
|
||||
|
||||
if reason_string.start_with?("it ")
|
||||
problem "Do not start the reason with `it`" do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "\"#{reason_string[3..]}\"")
|
||||
corrector.replace(T.must(@offensive_node).source_range, "\"#{reason_string[3..]}\"")
|
||||
end
|
||||
end
|
||||
|
||||
if PUNCTUATION_MARKS.include?(reason_string[-1])
|
||||
problem "Do not end the reason with a punctuation mark" do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "\"#{reason_string.chop}\"")
|
||||
corrector.replace(T.must(@offensive_node).source_range, "\"#{reason_string.chop}\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -17,7 +17,7 @@ module RuboCop
|
||||
def audit_formula(formula_nodes)
|
||||
body_node = formula_nodes.body_node
|
||||
|
||||
@name = @formula_name
|
||||
@name = T.let(@formula_name, T.nilable(String))
|
||||
desc_call = find_node_method_by_name(body_node, :desc)
|
||||
offending_node(formula_nodes.class_node) if body_node.nil?
|
||||
audit_desc(:formula, @name, desc_call)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/shared/helper_functions"
|
||||
@ -14,9 +14,10 @@ module RuboCop
|
||||
abstract!
|
||||
exclude_from_registry
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
attr_accessor :file_path
|
||||
|
||||
@registry = Registry.global
|
||||
@registry = T.let(Registry.global, RuboCop::Cop::Registry)
|
||||
|
||||
class FormulaNodes < T::Struct
|
||||
prop :node, RuboCop::AST::ClassNode
|
||||
@ -26,15 +27,18 @@ module RuboCop
|
||||
end
|
||||
|
||||
# This method is called by RuboCop and is the main entry point.
|
||||
sig { params(node: RuboCop::AST::ClassNode).void }
|
||||
def on_class(node)
|
||||
@file_path = processed_source.file_path
|
||||
@file_path = T.let(processed_source.file_path, T.nilable(String))
|
||||
return unless file_path_allowed?
|
||||
return unless formula_class?(node)
|
||||
|
||||
class_node, parent_class_node, @body = *node
|
||||
@formula_name = Pathname.new(@file_path).basename(".rb").to_s
|
||||
@tap_style_exceptions = nil
|
||||
audit_formula(FormulaNodes.new(node:, class_node:, parent_class_node:, body_node: @body))
|
||||
class_node, parent_class_node, body = *node
|
||||
@body = T.let(body, T.nilable(RuboCop::AST::Node))
|
||||
|
||||
@formula_name = T.let(Pathname.new(@file_path).basename(".rb").to_s, T.nilable(String))
|
||||
@tap_style_exceptions = T.let(nil, T.nilable(T::Hash[Symbol, T::Array[String]]))
|
||||
audit_formula(FormulaNodes.new(node:, class_node:, parent_class_node:, body_node: T.must(@body)))
|
||||
end
|
||||
|
||||
sig { abstract.params(formula_nodes: FormulaNodes).void }
|
||||
@ -44,7 +48,13 @@ module RuboCop
|
||||
#
|
||||
# @param urls [Array] url/mirror method call nodes
|
||||
# @param regex [Regexp] pattern to match URLs
|
||||
def audit_urls(urls, regex)
|
||||
sig {
|
||||
params(
|
||||
urls: T::Array[RuboCop::AST::Node], regex: Regexp,
|
||||
_block: T.proc.params(arg0: T::Array[RuboCop::AST::Node], arg1: String, arg2: Integer).void
|
||||
).void
|
||||
}
|
||||
def audit_urls(urls, regex, &_block)
|
||||
urls.each_with_index do |url_node, index|
|
||||
url_string_node = parameters(url_node).first
|
||||
url_string = string_content(url_string_node)
|
||||
@ -59,6 +69,7 @@ module RuboCop
|
||||
# Returns if the formula depends on dependency_name.
|
||||
#
|
||||
# @param dependency_name dependency's name
|
||||
sig { params(dependency_name: T.any(String, Symbol), types: Symbol).returns(T::Boolean) }
|
||||
def depends_on?(dependency_name, *types)
|
||||
return false if @body.nil?
|
||||
|
||||
@ -69,13 +80,20 @@ module RuboCop
|
||||
end
|
||||
return false if idx.nil?
|
||||
|
||||
@offensive_node = dependency_nodes[idx]
|
||||
@offensive_node = T.let(dependency_nodes[idx], T.nilable(RuboCop::AST::Node))
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
# Returns true if given dependency name and dependency type exist in given dependency method call node.
|
||||
# TODO: Add case where key of hash is an array
|
||||
sig {
|
||||
params(
|
||||
node: RuboCop::AST::Node, name: T.nilable(T.any(String, Symbol)), type: Symbol,
|
||||
).returns(
|
||||
T::Boolean,
|
||||
)
|
||||
}
|
||||
def depends_on_name_type?(node, name = nil, type = :required)
|
||||
name_match = !name # Match only by type when name is nil
|
||||
|
||||
@ -88,8 +106,8 @@ module RuboCop
|
||||
name_match ||= dependency_name_hash_match?(node, name) if type_match
|
||||
when :any
|
||||
type_match = true
|
||||
name_match ||= required_dependency_name?(node, name)
|
||||
name_match ||= dependency_name_hash_match?(node, name)
|
||||
name_match ||= required_dependency_name?(node, name) || false
|
||||
name_match ||= dependency_name_hash_match?(node, name) || false
|
||||
else
|
||||
type_match = false
|
||||
end
|
||||
@ -115,13 +133,15 @@ module RuboCop
|
||||
EOS
|
||||
|
||||
# Return all the caveats' string nodes in an array.
|
||||
sig { returns(T::Array[RuboCop::AST::Node]) }
|
||||
def caveats_strings
|
||||
return [] if @body.nil?
|
||||
|
||||
find_strings(find_method_def(@body, :caveats))
|
||||
find_strings(find_method_def(@body, :caveats)).to_a
|
||||
end
|
||||
|
||||
# Returns the sha256 str node given a sha256 call node.
|
||||
sig { params(call: RuboCop::AST::Node).returns(T.nilable(RuboCop::AST::Node)) }
|
||||
def get_checksum_node(call)
|
||||
return if parameters(call).empty? || parameters(call).nil?
|
||||
|
||||
@ -144,7 +164,8 @@ module RuboCop
|
||||
end
|
||||
|
||||
# Yields to a block with comment text as parameter.
|
||||
def audit_comments
|
||||
sig { params(_block: T.proc.params(arg0: String).void).void }
|
||||
def audit_comments(&_block)
|
||||
processed_source.comments.each do |comment_node|
|
||||
@offensive_node = comment_node
|
||||
yield comment_node.text
|
||||
@ -152,20 +173,26 @@ module RuboCop
|
||||
end
|
||||
|
||||
# Returns true if the formula is versioned.
|
||||
sig { returns(T::Boolean) }
|
||||
def versioned_formula?
|
||||
return false if @formula_name.nil?
|
||||
|
||||
@formula_name.include?("@")
|
||||
end
|
||||
|
||||
# Returns the formula tap.
|
||||
sig { returns(T.nilable(String)) }
|
||||
def formula_tap
|
||||
return unless (match_obj = @file_path.match(%r{/(homebrew-\w+)/}))
|
||||
return unless (match_obj = @file_path&.match(%r{/(homebrew-\w+)/}))
|
||||
|
||||
match_obj[1]
|
||||
end
|
||||
|
||||
# Returns the style exceptions directory from the file path.
|
||||
sig { returns(T.nilable(String)) }
|
||||
def style_exceptions_dir
|
||||
file_directory = File.dirname(@file_path)
|
||||
file_directory = File.dirname(@file_path) if @file_path
|
||||
return unless file_directory
|
||||
|
||||
# if we're in a sharded subdirectory, look below that.
|
||||
directory_name = File.basename(file_directory)
|
||||
@ -189,6 +216,7 @@ module RuboCop
|
||||
|
||||
# Returns whether the given formula exists in the given style exception list.
|
||||
# Defaults to the current formula being checked.
|
||||
sig { params(list: Symbol, formula: T.nilable(String)).returns(T::Boolean) }
|
||||
def tap_style_exception?(list, formula = nil)
|
||||
if @tap_style_exceptions.nil? && !formula_tap.nil?
|
||||
@tap_style_exceptions = {}
|
||||
@ -209,11 +237,12 @@ module RuboCop
|
||||
return false if @tap_style_exceptions.nil? || @tap_style_exceptions.count.zero?
|
||||
return false unless @tap_style_exceptions.key? list
|
||||
|
||||
@tap_style_exceptions[list].include?(formula || @formula_name)
|
||||
T.must(@tap_style_exceptions[list]).include?(formula || @formula_name)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).returns(T::Boolean) }
|
||||
def formula_class?(node)
|
||||
_, class_node, = *node
|
||||
class_names = %w[
|
||||
@ -223,19 +252,24 @@ module RuboCop
|
||||
AmazonWebServicesFormula
|
||||
]
|
||||
|
||||
class_node && class_names.include?(string_content(class_node))
|
||||
!!(class_node && class_names.include?(string_content(class_node)))
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def file_path_allowed?
|
||||
return true if @file_path.nil? # file_path is nil when source is directly passed to the cop, e.g. in specs
|
||||
|
||||
!@file_path.include?("/Library/Homebrew/test/")
|
||||
end
|
||||
|
||||
sig { returns(T::Array[Symbol]) }
|
||||
def on_system_methods
|
||||
@on_system_methods ||= [:intel, :arm, :macos, :linux, :system, *MacOSVersion::SYMBOLS.keys].map do |m|
|
||||
:"on_#{m}"
|
||||
end
|
||||
@on_system_methods ||= T.let(
|
||||
[:intel, :arm, :macos, :linux, :system, *MacOSVersion::SYMBOLS.keys].map do |m|
|
||||
:"on_#{m}"
|
||||
end,
|
||||
T.nilable(T::Array[Symbol]),
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
@ -10,6 +10,7 @@ module RuboCop
|
||||
|
||||
RESTRICT_ON_SEND = [:read, :readlines].freeze
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).void }
|
||||
def on_send(node)
|
||||
return if node.receiver != s(:const, nil, :IO)
|
||||
return if safe?(node.arguments.first)
|
||||
@ -19,10 +20,11 @@ module RuboCop
|
||||
|
||||
private
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).returns(T::Boolean) }
|
||||
def safe?(node)
|
||||
if node.str_type?
|
||||
!node.str_content.empty? && !node.str_content.start_with?("|")
|
||||
elsif node.dstr_type? || (node.send_type? && node.method?(:+))
|
||||
elsif node.dstr_type? || (node.send_type? && T.cast(node, RuboCop::AST::SendNode).method?(:+))
|
||||
safe?(node.children.first)
|
||||
else
|
||||
false
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -29,24 +29,25 @@ module RuboCop
|
||||
|
||||
reason = parameters(keg_only_node).first
|
||||
offending_node(reason)
|
||||
name = Regexp.new(@formula_name, Regexp::IGNORECASE)
|
||||
name = Regexp.new(T.must(@formula_name), Regexp::IGNORECASE)
|
||||
reason = string_content(reason).sub(name, "")
|
||||
first_word = reason.split.first
|
||||
|
||||
if /\A[A-Z]/.match?(reason) && !reason.start_with?(*allowlist)
|
||||
problem "'#{first_word}' from the `keg_only` reason should be '#{first_word.downcase}'." do |corrector|
|
||||
reason[0] = reason[0].downcase
|
||||
corrector.replace(@offensive_node.source_range, "\"#{reason}\"")
|
||||
corrector.replace(T.must(@offensive_node).source_range, "\"#{reason}\"")
|
||||
end
|
||||
end
|
||||
|
||||
return unless reason.end_with?(".")
|
||||
|
||||
problem "`keg_only` reason should not end with a period." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "\"#{reason.chop}\"")
|
||||
corrector.replace(T.must(@offensive_node).source_range, "\"#{reason.chop}\"")
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).void }
|
||||
def autocorrect(node)
|
||||
lambda do |corrector|
|
||||
reason = string_content(node)
|
||||
|
@ -40,7 +40,7 @@ module RuboCop
|
||||
return if begin_pos-end_pos == 3
|
||||
|
||||
problem "Use a space in class inheritance: " \
|
||||
"class #{@formula_name.capitalize} < #{class_name(parent_class_node)}"
|
||||
"class #{T.must(@formula_name).capitalize} < #{class_name(parent_class_node)}"
|
||||
end
|
||||
end
|
||||
|
||||
@ -181,9 +181,11 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).returns(T::Boolean) }
|
||||
def unless_modifier?(node)
|
||||
return false unless node.if_type?
|
||||
|
||||
node = T.cast(node, RuboCop::AST::IfNode)
|
||||
node.modifier_form? && node.unless?
|
||||
end
|
||||
|
||||
@ -207,8 +209,8 @@ module RuboCop
|
||||
|
||||
find_method_with_args(body_node, :depends_on, "mpich") do
|
||||
problem "Formulae in homebrew/core should use 'depends_on \"open-mpi\"' " \
|
||||
"instead of '#{@offensive_node.source}'." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "depends_on \"open-mpi\"")
|
||||
"instead of '#{T.must(@offensive_node).source}'." do |corrector|
|
||||
corrector.replace(T.must(@offensive_node).source_range, "depends_on \"open-mpi\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -224,17 +226,19 @@ module RuboCop
|
||||
return if (body_node = formula_nodes.body_node).nil?
|
||||
|
||||
find_method_with_args(body_node, :local_npm_install_args) do
|
||||
problem "Use 'std_npm_args' instead of '#{@offensive_node.method_name}'." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "std_npm_args(prefix: false)")
|
||||
problem "Use 'std_npm_args' instead of '#{T.cast(@offensive_node,
|
||||
RuboCop::AST::SendNode).method_name}'." do |corrector|
|
||||
corrector.replace(T.must(@offensive_node).source_range, "std_npm_args(prefix: false)")
|
||||
end
|
||||
end
|
||||
|
||||
find_method_with_args(body_node, :std_npm_install_args) do |method|
|
||||
problem "Use 'std_npm_args' instead of '#{@offensive_node.method_name}'." do |corrector|
|
||||
problem "Use 'std_npm_args' instead of '#{T.cast(@offensive_node,
|
||||
RuboCop::AST::SendNode).method_name}'." do |corrector|
|
||||
if (param = parameters(method).first.source) == "libexec"
|
||||
corrector.replace(@offensive_node.source_range, "std_npm_args")
|
||||
corrector.replace(T.must(@offensive_node).source_range, "std_npm_args")
|
||||
else
|
||||
corrector.replace(@offensive_node.source_range, "std_npm_args(prefix: #{param})")
|
||||
corrector.replace(T.must(@offensive_node).source_range, "std_npm_args(prefix: #{param})")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -264,8 +268,8 @@ module RuboCop
|
||||
|
||||
find_method_with_args(body_node, :depends_on, "quictls") do
|
||||
problem "Formulae in homebrew/core should use 'depends_on \"openssl@3\"' " \
|
||||
"instead of '#{@offensive_node.source}'." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "depends_on \"openssl@3\"")
|
||||
"instead of '#{T.must(@offensive_node).source}'." do |corrector|
|
||||
corrector.replace(T.must(@offensive_node).source_range, "depends_on \"openssl@3\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -281,7 +285,7 @@ module RuboCop
|
||||
return if formula_tap != "homebrew-core"
|
||||
return unless depends_on?("pyoxidizer")
|
||||
|
||||
problem "Formulae in homebrew/core should not use '#{@offensive_node.source}'."
|
||||
problem "Formulae in homebrew/core should not use '#{T.must(@offensive_node).source}'."
|
||||
end
|
||||
end
|
||||
|
||||
@ -307,7 +311,8 @@ module RuboCop
|
||||
find_instance_method_call(body_node, "Utils", unsafe_command) do |method|
|
||||
unless test_methods.include?(method.source_range)
|
||||
problem "Use `Utils.safe_#{unsafe_command}` instead of `Utils.#{unsafe_command}`" do |corrector|
|
||||
corrector.replace(@offensive_node.loc.selector, "safe_#{@offensive_node.method_name}")
|
||||
corrector.replace(T.must(@offensive_node).loc.selector,
|
||||
"safe_#{T.cast(@offensive_node, RuboCop::AST::SendNode).method_name}")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -478,7 +483,10 @@ module RuboCop
|
||||
class MacOSOnLinux < FormulaCop
|
||||
include OnSystemConditionalsHelper
|
||||
|
||||
ON_MACOS_BLOCKS = [:macos, *MACOS_VERSION_OPTIONS].map { |os| :"on_#{os}" }.freeze
|
||||
ON_MACOS_BLOCKS = T.let(
|
||||
[:macos, *MACOS_VERSION_OPTIONS].map { |os| :"on_#{os}" }.freeze,
|
||||
T::Array[Symbol],
|
||||
)
|
||||
|
||||
sig { override.params(formula_nodes: FormulaNodes).void }
|
||||
def audit_formula(formula_nodes)
|
||||
@ -529,8 +537,8 @@ module RuboCop
|
||||
offending_node(node)
|
||||
replacement = "generate_completions_from_executable(#{replacement_args.join(", ")})"
|
||||
|
||||
problem "Use `#{replacement}` instead of `#{@offensive_node.source}`." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, replacement)
|
||||
problem "Use `#{replacement}` instead of `#{T.must(@offensive_node).source}`." do |corrector|
|
||||
corrector.replace(T.must(@offensive_node).source_range, replacement)
|
||||
end
|
||||
end
|
||||
|
||||
@ -539,7 +547,7 @@ module RuboCop
|
||||
next if node.source.match?(/{.*=>.*}/) # skip commands needing custom ENV variables
|
||||
|
||||
offending_node(node)
|
||||
problem "Use `generate_completions_from_executable` DSL instead of `#{@offensive_node.source}`."
|
||||
problem "Use `generate_completions_from_executable` DSL instead of `#{T.must(@offensive_node).source}`."
|
||||
end
|
||||
end
|
||||
|
||||
@ -608,7 +616,7 @@ module RuboCop
|
||||
problem "Use a single `generate_completions_from_executable` " \
|
||||
"call combining all specified shells." do |corrector|
|
||||
# adjust range by -4 and +1 to also include & remove leading spaces and trailing \n
|
||||
corrector.replace(@offensive_node.source_range.adjust(begin_pos: -4, end_pos: 1), "")
|
||||
corrector.replace(T.must(@offensive_node).source_range.adjust(begin_pos: -4, end_pos: 1), "")
|
||||
end
|
||||
end
|
||||
|
||||
@ -616,17 +624,18 @@ module RuboCop
|
||||
|
||||
offending_node(offenses.last)
|
||||
replacement = if (%w[:bash :zsh :fish] - shells).empty?
|
||||
@offensive_node.source.sub(/shells: \[(:bash|:zsh|:fish)\]/, "")
|
||||
.sub(", )", ")") # clean up dangling trailing comma
|
||||
.sub("(, ", "(") # clean up dangling leading comma
|
||||
.sub(", , ", ", ") # clean up dangling enclosed comma
|
||||
T.must(@offensive_node).source
|
||||
.sub(/shells: \[(:bash|:zsh|:fish)\]/, "")
|
||||
.sub(", )", ")") # clean up dangling trailing comma
|
||||
.sub("(, ", "(") # clean up dangling leading comma
|
||||
.sub(", , ", ", ") # clean up dangling enclosed comma
|
||||
else
|
||||
@offensive_node.source.sub(/shells: \[(:bash|:zsh|:fish)\]/,
|
||||
"shells: [#{shells.join(", ")}]")
|
||||
T.must(@offensive_node).source.sub(/shells: \[(:bash|:zsh|:fish)\]/,
|
||||
"shells: [#{shells.join(", ")}]")
|
||||
end
|
||||
|
||||
problem "Use `#{replacement}` instead of `#{@offensive_node.source}`." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, replacement)
|
||||
problem "Use `#{replacement}` instead of `#{T.must(@offensive_node).source}`." do |corrector|
|
||||
corrector.replace(T.must(@offensive_node).source_range, replacement)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -783,7 +792,7 @@ module RuboCop
|
||||
end
|
||||
|
||||
find_method_with_args(body_node, :system, /^(otool|install_name_tool|lipo)/) do
|
||||
problem "Use ruby-macho instead of calling #{@offensive_node.source}"
|
||||
problem "Use ruby-macho instead of calling #{T.must(@offensive_node).source}"
|
||||
end
|
||||
|
||||
problem "Use new-style test definitions (test do)" if find_method_def(body_node, :test)
|
||||
@ -854,10 +863,11 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).returns(T::Boolean) }
|
||||
def modifier?(node)
|
||||
return false unless node.if_type?
|
||||
|
||||
node.modifier_form?
|
||||
T.cast(node, RuboCop::AST::IfNode).modifier_form?
|
||||
end
|
||||
|
||||
def_node_search :conditional_dependencies, <<~EOS
|
||||
@ -892,7 +902,7 @@ module RuboCop
|
||||
|
||||
# Avoid build-time checks in homebrew/core
|
||||
find_every_method_call_by_name(formula_nodes.body_node, :system).each do |method|
|
||||
next if @formula_name.start_with?("lib")
|
||||
next if @formula_name&.start_with?("lib")
|
||||
next if tap_style_exception? :make_check_allowlist
|
||||
|
||||
params = parameters(method)
|
||||
@ -933,8 +943,8 @@ module RuboCop
|
||||
|
||||
find_method_with_args(body_node, :depends_on, "rustup") do
|
||||
problem "Formulae in homebrew/core should use 'depends_on \"rust\"' " \
|
||||
"instead of '#{@offensive_node.source}'." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "depends_on \"rust\"")
|
||||
"instead of '#{T.must(@offensive_node).source}'." do |corrector|
|
||||
corrector.replace(T.must(@offensive_node).source_range, "depends_on \"rust\"")
|
||||
end
|
||||
end
|
||||
|
||||
@ -943,8 +953,8 @@ module RuboCop
|
||||
[:build, [:build, :test], [:test, :build]].each do |type|
|
||||
find_method_with_args(body_node, :depends_on, "rustup" => type) do
|
||||
problem "Formulae in homebrew/core should use 'depends_on \"rust\" => #{type}' " \
|
||||
"instead of '#{@offensive_node.source}'." do |corrector|
|
||||
corrector.replace(@offensive_node.source_range, "depends_on \"rust\" => #{type}")
|
||||
"instead of '#{T.must(@offensive_node).source}'." do |corrector|
|
||||
corrector.replace(T.must(@offensive_node).source_range, "depends_on \"rust\" => #{type}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
@ -12,6 +12,7 @@ module RuboCop
|
||||
(send (const nil? :OS) {:mac? | :linux?})
|
||||
PATTERN
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).void }
|
||||
def on_send(node)
|
||||
return unless os_check?(node)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
@ -32,6 +32,7 @@ module RuboCop
|
||||
(send (send $!nil? :include? $_) :!)
|
||||
PATTERN
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).void }
|
||||
def on_send(node)
|
||||
return unless (receiver, obj = negate_include_call?(node))
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -14,7 +14,7 @@ module RuboCop
|
||||
sig { override.params(formula_nodes: FormulaNodes).void }
|
||||
def audit_formula(formula_nodes)
|
||||
node = formula_nodes.node
|
||||
@full_source_content = source_buffer(node).source
|
||||
@full_source_content = T.let(source_buffer(node).source, T.nilable(String))
|
||||
|
||||
return if (body_node = formula_nodes.body_node).nil?
|
||||
|
||||
@ -43,6 +43,7 @@ module RuboCop
|
||||
|
||||
private
|
||||
|
||||
sig { params(patch_url_node: RuboCop::AST::Node).void }
|
||||
def patch_problems(patch_url_node)
|
||||
patch_url = string_content(patch_url_node)
|
||||
|
||||
@ -103,6 +104,7 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(patch: RuboCop::AST::Node).void }
|
||||
def inline_patch_problems(patch)
|
||||
return if !patch_data?(patch) || patch_end?
|
||||
|
||||
@ -119,13 +121,17 @@ module RuboCop
|
||||
/^__END__$/.match?(@full_source_content)
|
||||
end
|
||||
|
||||
sig { params(node: RuboCop::AST::Node).void }
|
||||
def offending_patch_end_node(node)
|
||||
@offensive_node = node
|
||||
@source_buf = source_buffer(node)
|
||||
@line_no = node.loc.last_line + 1
|
||||
@column = 0
|
||||
@length = 7 # "__END__".size
|
||||
@offense_source_range = source_range(@source_buf, @line_no, @column, @length)
|
||||
@offensive_node = T.let(node, T.nilable(RuboCop::AST::Node))
|
||||
@source_buf = T.let(source_buffer(node), T.nilable(Parser::Source::Buffer))
|
||||
@line_no = T.let(node.loc.last_line + 1, T.nilable(Integer))
|
||||
@column = T.let(0, T.nilable(Integer))
|
||||
@length = T.let(7, T.nilable(Integer)) # "__END__".size
|
||||
@offense_source_range = T.let(
|
||||
source_range(@source_buf, @line_no, @column, @length),
|
||||
T.nilable(Parser::Source::Range),
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -78,6 +78,7 @@ module RuboCop
|
||||
}
|
||||
PATTERN
|
||||
|
||||
sig { params(node: RuboCop::AST::IfNode).void }
|
||||
def on_if(node)
|
||||
return if ignore_if_node?(node)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
@ -37,6 +37,7 @@ module RuboCop
|
||||
)
|
||||
PATTERN
|
||||
|
||||
sig { params(node: RuboCop::AST::AndNode).void }
|
||||
def on_and(node)
|
||||
exists_and_not_empty?(node) do |var1, var2|
|
||||
return if var1 != var2
|
||||
@ -49,6 +50,7 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(node: RuboCop::AST::OrNode).void }
|
||||
def on_or(node)
|
||||
exists_and_not_empty?(node) do |var1, var2|
|
||||
return if var1 != var2
|
||||
@ -59,6 +61,7 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(corrector: RuboCop::Cop::Corrector, node: RuboCop::AST::Node).void }
|
||||
def autocorrect(corrector, node)
|
||||
variable1, _variable2 = exists_and_not_empty?(node)
|
||||
range = node.source_range
|
||||
@ -67,8 +70,9 @@ module RuboCop
|
||||
|
||||
private
|
||||
|
||||
sig { params(node: T.nilable(RuboCop::AST::Node)).returns(String) }
|
||||
def replacement(node)
|
||||
node.respond_to?(:source) ? "#{node.source}.present?" : "present?"
|
||||
node.respond_to?(:source) ? "#{node&.source}.present?" : "present?"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
@ -36,6 +36,7 @@ module RuboCop
|
||||
(if $(csend ... :blank?) ...)
|
||||
PATTERN
|
||||
|
||||
sig { params(node: RuboCop::AST::IfNode).void }
|
||||
def on_if(node)
|
||||
return unless safe_navigation_blank_in_conditional?(node)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -10,14 +10,17 @@ module RuboCop
|
||||
class Service < FormulaCop
|
||||
extend AutoCorrector
|
||||
|
||||
CELLAR_PATH_AUDIT_CORRECTIONS = {
|
||||
bin: :opt_bin,
|
||||
libexec: :opt_libexec,
|
||||
pkgshare: :opt_pkgshare,
|
||||
prefix: :opt_prefix,
|
||||
sbin: :opt_sbin,
|
||||
share: :opt_share,
|
||||
}.freeze
|
||||
CELLAR_PATH_AUDIT_CORRECTIONS = T.let(
|
||||
{
|
||||
bin: :opt_bin,
|
||||
libexec: :opt_libexec,
|
||||
pkgshare: :opt_pkgshare,
|
||||
prefix: :opt_prefix,
|
||||
sbin: :opt_sbin,
|
||||
share: :opt_share,
|
||||
}.freeze,
|
||||
T::Hash[Symbol, Symbol],
|
||||
)
|
||||
|
||||
# At least one of these methods must be defined in a service block.
|
||||
REQUIRED_METHOD_CALLS = [:run, :name].freeze
|
||||
|
@ -17,6 +17,7 @@ module RuboCop
|
||||
macOS
|
||||
].freeze
|
||||
|
||||
sig { params(type: Symbol, name: T.nilable(String), desc_call: T.nilable(RuboCop::AST::Node)).void }
|
||||
def audit_desc(type, name, desc_call)
|
||||
# Check if a desc is present.
|
||||
if desc_call.nil?
|
||||
@ -26,7 +27,7 @@ module RuboCop
|
||||
|
||||
@offensive_node = desc_call
|
||||
|
||||
desc = desc_call.first_argument
|
||||
desc = T.cast(desc_call, RuboCop::AST::SendNode).first_argument
|
||||
|
||||
# Check if the desc is empty.
|
||||
desc_length = string_content(desc).length
|
||||
@ -56,7 +57,7 @@ module RuboCop
|
||||
end
|
||||
|
||||
# Check if the desc starts with the formula's or cask's name.
|
||||
name_regex = name.delete("-").chars.join('[\s\-]?')
|
||||
name_regex = T.must(name).delete("-").chars.join('[\s\-]?')
|
||||
if regex_match_group(desc, /^#{name_regex}\b/i)
|
||||
desc_problem "Description shouldn't start with the #{type} name."
|
||||
end
|
||||
|
@ -32,7 +32,10 @@ module RuboCop
|
||||
@line_no = line_number(node)
|
||||
@source_buf = source_buffer(node)
|
||||
@offensive_node = node
|
||||
@offensive_source_range = source_range(@source_buf, @line_no, @column, @length)
|
||||
@offensive_source_range = T.let(
|
||||
source_range(@source_buf, @line_no, @column, @length),
|
||||
T.nilable(Parser::Source::Range),
|
||||
)
|
||||
match_object
|
||||
end
|
||||
|
||||
@ -53,6 +56,7 @@ module RuboCop
|
||||
end
|
||||
|
||||
# Source buffer is required as an argument to report style violations.
|
||||
sig { params(node: RuboCop::AST::Node).returns(Parser::Source::Buffer) }
|
||||
def source_buffer(node)
|
||||
node.source_range.source_buffer
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/shared/helper_functions"
|
||||
@ -9,8 +9,15 @@ module RuboCop
|
||||
module HomepageHelper
|
||||
include HelperFunctions
|
||||
|
||||
sig {
|
||||
params(
|
||||
type: Symbol, content: String,
|
||||
homepage_node: RuboCop::AST::Node,
|
||||
homepage_parameter_node: RuboCop::AST::Node
|
||||
).void
|
||||
}
|
||||
def audit_homepage(type, content, homepage_node, homepage_parameter_node)
|
||||
@offensive_node = homepage_node
|
||||
@offensive_node = T.let(homepage_node, T.nilable(RuboCop::AST::Node))
|
||||
|
||||
problem "#{type.to_s.capitalize} should have a homepage." if content.empty?
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "macos_version"
|
||||
@ -13,16 +13,23 @@ module RuboCop
|
||||
|
||||
ARCH_OPTIONS = [:arm, :intel].freeze
|
||||
BASE_OS_OPTIONS = [:macos, :linux].freeze
|
||||
MACOS_VERSION_OPTIONS = MacOSVersion::SYMBOLS.keys.freeze
|
||||
ON_SYSTEM_OPTIONS = [*ARCH_OPTIONS, *BASE_OS_OPTIONS, *MACOS_VERSION_OPTIONS, :system].freeze
|
||||
MACOS_VERSION_OPTIONS = T.let(MacOSVersion::SYMBOLS.keys.freeze, T::Array[Symbol])
|
||||
ON_SYSTEM_OPTIONS = T.let(
|
||||
[*ARCH_OPTIONS, *BASE_OS_OPTIONS, *MACOS_VERSION_OPTIONS, :system].freeze,
|
||||
T::Array[Symbol],
|
||||
)
|
||||
MACOS_MODULE_NAMES = ["MacOS", "OS::Mac"].freeze
|
||||
|
||||
MACOS_VERSION_CONDITIONALS = {
|
||||
"==" => nil,
|
||||
"<=" => :or_older,
|
||||
">=" => :or_newer,
|
||||
}.freeze
|
||||
MACOS_VERSION_CONDITIONALS = T.let(
|
||||
{
|
||||
"==" => nil,
|
||||
"<=" => :or_older,
|
||||
">=" => :or_newer,
|
||||
}.freeze,
|
||||
T::Hash[String, T.nilable(Symbol)],
|
||||
)
|
||||
|
||||
sig { params(body_node: RuboCop::AST::Node, parent_name: Symbol).void }
|
||||
def audit_on_system_blocks(body_node, parent_name)
|
||||
parent_string = if body_node.def_type?
|
||||
"def #{parent_name}"
|
||||
@ -77,6 +84,12 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
body_node: RuboCop::AST::Node, allowed_methods: T::Array[Symbol],
|
||||
allowed_blocks: T::Array[Symbol]
|
||||
).void
|
||||
}
|
||||
def audit_arch_conditionals(body_node, allowed_methods: [], allowed_blocks: [])
|
||||
ARCH_OPTIONS.each do |arch_option|
|
||||
else_method = (arch_option == :arm) ? :on_intel : :on_arm
|
||||
@ -100,6 +113,12 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
body_node: RuboCop::AST::Node, allowed_methods: T::Array[Symbol],
|
||||
allowed_blocks: T::Array[Symbol]
|
||||
).void
|
||||
}
|
||||
def audit_base_os_conditionals(body_node, allowed_methods: [], allowed_blocks: [])
|
||||
BASE_OS_OPTIONS.each do |base_os_option|
|
||||
os_method, else_method = if base_os_option == :macos
|
||||
@ -116,12 +135,21 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
body_node: RuboCop::AST::Node,
|
||||
allowed_methods: T::Array[Symbol],
|
||||
allowed_blocks: T::Array[Symbol],
|
||||
recommend_on_system: T::Boolean,
|
||||
).void
|
||||
}
|
||||
def audit_macos_version_conditionals(body_node, allowed_methods: [], allowed_blocks: [],
|
||||
recommend_on_system: true)
|
||||
MACOS_VERSION_OPTIONS.each do |macos_version_option|
|
||||
if_macos_version_node_search(body_node, os_version: macos_version_option) do |if_node, operator, else_node|
|
||||
next if node_is_allowed?(if_node, allowed_methods:, allowed_blocks:)
|
||||
|
||||
else_node = T.let(else_node, T.nilable(RuboCop::AST::Node))
|
||||
autocorrect = else_node.blank? && MACOS_VERSION_CONDITIONALS.key?(operator.to_s)
|
||||
on_system_method_string = if recommend_on_system && operator == :<
|
||||
"on_system"
|
||||
@ -148,6 +176,13 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
body_node: RuboCop::AST::Node,
|
||||
allowed_methods: T::Array[Symbol],
|
||||
allowed_blocks: T::Array[Symbol],
|
||||
).void
|
||||
}
|
||||
def audit_macos_references(body_node, allowed_methods: [], allowed_blocks: [])
|
||||
MACOS_MODULE_NAMES.each do |macos_module_name|
|
||||
find_const(body_node, macos_module_name) do |node|
|
||||
@ -161,6 +196,16 @@ module RuboCop
|
||||
|
||||
private
|
||||
|
||||
sig {
|
||||
params(
|
||||
if_node: RuboCop::AST::IfNode,
|
||||
if_statement_string: String,
|
||||
on_system_method_string: String,
|
||||
else_method: T.nilable(Symbol),
|
||||
else_node: T.nilable(RuboCop::AST::Node),
|
||||
autocorrect: T::Boolean,
|
||||
).void
|
||||
}
|
||||
def if_statement_problem(if_node, if_statement_string, on_system_method_string,
|
||||
else_method: nil, else_node: nil, autocorrect: true)
|
||||
offending_node(if_node)
|
||||
@ -180,6 +225,12 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
node: RuboCop::AST::Node, allowed_methods: T::Array[Symbol],
|
||||
allowed_blocks: T::Array[Symbol]
|
||||
).returns(T::Boolean)
|
||||
}
|
||||
def node_is_allowed?(node, allowed_methods: [], allowed_blocks: [])
|
||||
# TODO: check to see if it's legal
|
||||
valid = T.let(false, T::Boolean)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "extend/array"
|
||||
@ -64,8 +64,12 @@ module RuboCop
|
||||
].freeze
|
||||
private_constant :TARGET_METHODS
|
||||
|
||||
RESTRICT_ON_SEND = TARGET_METHODS.map(&:second).uniq.freeze
|
||||
RESTRICT_ON_SEND = T.let(
|
||||
TARGET_METHODS.map(&:second).uniq.freeze,
|
||||
T::Array[T.nilable(Symbol)],
|
||||
)
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).void }
|
||||
def on_send(node)
|
||||
TARGET_METHODS.each do |target_class, target_method|
|
||||
next if node.method_name != target_method
|
||||
@ -119,6 +123,7 @@ module RuboCop
|
||||
|
||||
RESTRICT_ON_SEND = [:exec].freeze
|
||||
|
||||
sig { params(node: RuboCop::AST::SendNode).void }
|
||||
def on_send(node)
|
||||
return if node.receiver.present? && node.receiver != s(:const, nil, :Kernel)
|
||||
return if node.arguments.count != 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
@ -133,7 +133,7 @@ module RuboCop
|
||||
problem "`env :userpaths` in homebrew/core formulae is deprecated"
|
||||
end
|
||||
|
||||
share_path_starts_with(body_node, @formula_name) do |share_node|
|
||||
share_path_starts_with(body_node, T.must(@formula_name)) do |share_node|
|
||||
offending_node(share_node)
|
||||
problem "Use `pkgshare` instead of `share/\"#{@formula_name}\"`"
|
||||
end
|
||||
@ -162,11 +162,13 @@ module RuboCop
|
||||
|
||||
# Check whether value starts with the formula name and then a "/", " " or EOS.
|
||||
# If we're checking for "#{bin}", we also check for "-" since similar binaries also don't need interpolation.
|
||||
sig { params(path: String, starts_with: String, bin: T::Boolean).returns(T::Boolean) }
|
||||
def path_starts_with?(path, starts_with, bin: false)
|
||||
ending = bin ? "/|-|$" : "/| |$"
|
||||
path.match?(/^#{Regexp.escape(starts_with)}(#{ending})/)
|
||||
end
|
||||
|
||||
sig { params(path: String, starts_with: String).returns(T::Boolean) }
|
||||
def path_starts_with_bin?(path, starts_with)
|
||||
return false if path.include?(" ")
|
||||
|
||||
|
@ -30,7 +30,7 @@ module RuboCop
|
||||
|
||||
# Check for binary URLs
|
||||
audit_urls(urls, /(darwin|macos|osx)/i) do |match, url|
|
||||
next if @formula_name.include?(match.to_s.downcase)
|
||||
next if T.must(@formula_name).include?(match.to_s.downcase)
|
||||
next if url.match?(/.(patch|diff)(\?full_index=1)?$/)
|
||||
next if tap_style_exception? :not_a_binary_url_prefix_allowlist
|
||||
next if tap_style_exception? :binary_bootstrap_formula_urls_allowlist
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula_cop"
|
||||
|
Loading…
x
Reference in New Issue
Block a user