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