From 0fc1eb534ba942c19cfbbbe02f74fdb9b12c6651 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sat, 1 Feb 2025 23:54:35 +0000 Subject: [PATCH] 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`. --- Library/Homebrew/rubocops/blank.rb | 7 +- Library/Homebrew/rubocops/bottle.rb | 4 +- .../rubocops/cask/array_alphabetization.rb | 1 + Library/Homebrew/rubocops/checksum.rb | 11 +-- Library/Homebrew/rubocops/compact_blank.rb | 4 + Library/Homebrew/rubocops/conflicts.rb | 6 +- .../Homebrew/rubocops/deprecate_disable.rb | 6 +- Library/Homebrew/rubocops/desc.rb | 4 +- .../Homebrew/rubocops/extend/formula_cop.rb | 74 ++++++++++++++----- Library/Homebrew/rubocops/io_read.rb | 6 +- Library/Homebrew/rubocops/keg_only.rb | 9 ++- Library/Homebrew/rubocops/lines.rb | 74 +++++++++++-------- .../Homebrew/rubocops/move_to_extend_os.rb | 3 +- Library/Homebrew/rubocops/negate_include.rb | 3 +- Library/Homebrew/rubocops/patches.rb | 22 ++++-- Library/Homebrew/rubocops/presence.rb | 1 + Library/Homebrew/rubocops/present.rb | 8 +- .../rubocops/safe_navigation_with_blank.rb | 3 +- Library/Homebrew/rubocops/service.rb | 21 +++--- .../Homebrew/rubocops/shared/desc_helper.rb | 5 +- .../rubocops/shared/helper_functions.rb | 6 +- .../rubocops/shared/homepage_helper.rb | 11 ++- .../shared/on_system_conditionals_helper.rb | 67 +++++++++++++++-- Library/Homebrew/rubocops/shell_commands.rb | 9 ++- Library/Homebrew/rubocops/text.rb | 6 +- Library/Homebrew/rubocops/urls.rb | 2 +- Library/Homebrew/rubocops/uses_from_macos.rb | 2 +- 27 files changed, 260 insertions(+), 115 deletions(-) diff --git a/Library/Homebrew/rubocops/blank.rb b/Library/Homebrew/rubocops/blank.rb index f71839eafb5fe..d0efa0bf8212b 100644 --- a/Library/Homebrew/rubocops/blank.rb +++ b/Library/Homebrew/rubocops/blank.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true module RuboCop @@ -44,6 +44,7 @@ class Blank < Base ) 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 @@ def on_or(node) 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 diff --git a/Library/Homebrew/rubocops/bottle.rb b/Library/Homebrew/rubocops/bottle.rb index 0255f1e4ae3c7..e6de4adc11626 100644 --- a/Library/Homebrew/rubocops/bottle.rb +++ b/Library/Homebrew/rubocops/bottle.rb @@ -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 @@ def audit_formula(formula_nodes) 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? diff --git a/Library/Homebrew/rubocops/cask/array_alphabetization.rb b/Library/Homebrew/rubocops/cask/array_alphabetization.rb index 2237052fce384..6f2f60d71b61b 100644 --- a/Library/Homebrew/rubocops/cask/array_alphabetization.rb +++ b/Library/Homebrew/rubocops/cask/array_alphabetization.rb @@ -7,6 +7,7 @@ module Cask class ArrayAlphabetization < Base extend AutoCorrector + sig { params(node: RuboCop::AST::SendNode).void } def on_send(node) return unless [:zap, :uninstall].include?(node.method_name) diff --git a/Library/Homebrew/rubocops/checksum.rb b/Library/Homebrew/rubocops/checksum.rb index c1776b2d74db6..44d749db0d688 100644 --- a/Library/Homebrew/rubocops/checksum.rb +++ b/Library/Homebrew/rubocops/checksum.rb @@ -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 @@ def audit_formula(formula_nodes) end end + sig { params(checksum: T.nilable(RuboCop::AST::Node)).void } def audit_sha256(checksum) return if checksum.nil? @@ -37,7 +38,7 @@ def audit_sha256(checksum) 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 @@ def audit_formula(formula_nodes) 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 diff --git a/Library/Homebrew/rubocops/compact_blank.rb b/Library/Homebrew/rubocops/compact_blank.rb index b020db3447bfd..ed3f17011a1c9 100644 --- a/Library/Homebrew/rubocops/compact_blank.rb +++ b/Library/Homebrew/rubocops/compact_blank.rb @@ -62,6 +62,7 @@ class CompactBlank < Base (sym :blank?))) PATTERN + sig { params(node: RuboCop::AST::SendNode).void } def on_send(node) return unless bad_method?(node) @@ -74,6 +75,7 @@ def on_send(node) 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 @@ def use_hash_value_block_argument?(arguments, receiver_in_block) 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 @@ def offense_range(node) 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 diff --git a/Library/Homebrew/rubocops/conflicts.rb b/Library/Homebrew/rubocops/conflicts.rb index 36eadf0465acf..f7ee2f9124e4c 100644 --- a/Library/Homebrew/rubocops/conflicts.rb +++ b/Library/Homebrew/rubocops/conflicts.rb @@ -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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 diff --git a/Library/Homebrew/rubocops/deprecate_disable.rb b/Library/Homebrew/rubocops/deprecate_disable.rb index 127ec5de57fac..4078f910a9a74 100644 --- a/Library/Homebrew/rubocops/deprecate_disable.rb +++ b/Library/Homebrew/rubocops/deprecate_disable.rb @@ -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 @@ def audit_formula(formula_nodes) 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 diff --git a/Library/Homebrew/rubocops/desc.rb b/Library/Homebrew/rubocops/desc.rb index c68ac5d8e8511..ca3da3ffd795b 100644 --- a/Library/Homebrew/rubocops/desc.rb +++ b/Library/Homebrew/rubocops/desc.rb @@ -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 @@ class Desc < FormulaCop 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) diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb index bc771d852340d..47cdbc3ed39d0 100644 --- a/Library/Homebrew/rubocops/extend/formula_cop.rb +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -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 @@ class FormulaCop < Base 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 @@ class FormulaNodes < T::Struct 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 @@ def audit_formula(formula_nodes); end # # @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 @@ def audit_urls(urls, regex) # 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 @@ def depends_on?(dependency_name, *types) 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 @@ def depends_on_name_type?(node, name = nil, type = :required) 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 @@ def depends_on_name_type?(node, name = nil, type = :required) 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 @@ def get_checksum_node(call) 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 @@ def audit_comments 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 @@ def style_exceptions_dir # 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 @@ def tap_style_exception?(list, formula = nil) 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 @@ def formula_class?(node) 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 diff --git a/Library/Homebrew/rubocops/io_read.rb b/Library/Homebrew/rubocops/io_read.rb index 7e20f3e7b5598..4eb74b39ec5a6 100644 --- a/Library/Homebrew/rubocops/io_read.rb +++ b/Library/Homebrew/rubocops/io_read.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true module RuboCop @@ -10,6 +10,7 @@ class IORead < Base 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 @@ def on_send(node) 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 diff --git a/Library/Homebrew/rubocops/keg_only.rb b/Library/Homebrew/rubocops/keg_only.rb index 765f05ba3b56d..309d8f1d66b65 100644 --- a/Library/Homebrew/rubocops/keg_only.rb +++ b/Library/Homebrew/rubocops/keg_only.rb @@ -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 @@ def audit_formula(formula_nodes) 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) diff --git a/Library/Homebrew/rubocops/lines.rb b/Library/Homebrew/rubocops/lines.rb index 599e31d6505c1..0e3e0edbb1793 100644 --- a/Library/Homebrew/rubocops/lines.rb +++ b/Library/Homebrew/rubocops/lines.rb @@ -40,7 +40,7 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) # 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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) [: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 diff --git a/Library/Homebrew/rubocops/move_to_extend_os.rb b/Library/Homebrew/rubocops/move_to_extend_os.rb index 00aa8742c661c..018f82bbc707c 100644 --- a/Library/Homebrew/rubocops/move_to_extend_os.rb +++ b/Library/Homebrew/rubocops/move_to_extend_os.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true module RuboCop @@ -12,6 +12,7 @@ class MoveToExtendOS < Base (send (const nil? :OS) {:mac? | :linux?}) PATTERN + sig { params(node: RuboCop::AST::Node).void } def on_send(node) return unless os_check?(node) diff --git a/Library/Homebrew/rubocops/negate_include.rb b/Library/Homebrew/rubocops/negate_include.rb index 37ffd6092c51d..05e1502c30767 100644 --- a/Library/Homebrew/rubocops/negate_include.rb +++ b/Library/Homebrew/rubocops/negate_include.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true module RuboCop @@ -32,6 +32,7 @@ class NegateInclude < Base (send (send $!nil? :include? $_) :!) PATTERN + sig { params(node: RuboCop::AST::SendNode).void } def on_send(node) return unless (receiver, obj = negate_include_call?(node)) diff --git a/Library/Homebrew/rubocops/patches.rb b/Library/Homebrew/rubocops/patches.rb index 32d2f87e9e82d..781117d9f1642 100644 --- a/Library/Homebrew/rubocops/patches.rb +++ b/Library/Homebrew/rubocops/patches.rb @@ -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 @@ class Patches < FormulaCop 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 @@ def audit_formula(formula_nodes) 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 @@ def patch_problems(patch_url_node) 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 @@ def patch_end? /^__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 diff --git a/Library/Homebrew/rubocops/presence.rb b/Library/Homebrew/rubocops/presence.rb index c924de724ee32..e710713d13773 100644 --- a/Library/Homebrew/rubocops/presence.rb +++ b/Library/Homebrew/rubocops/presence.rb @@ -78,6 +78,7 @@ class Presence < Base } PATTERN + sig { params(node: RuboCop::AST::IfNode).void } def on_if(node) return if ignore_if_node?(node) diff --git a/Library/Homebrew/rubocops/present.rb b/Library/Homebrew/rubocops/present.rb index c77a2eed5a7ea..ebca2f5aba196 100644 --- a/Library/Homebrew/rubocops/present.rb +++ b/Library/Homebrew/rubocops/present.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true module RuboCop @@ -37,6 +37,7 @@ class Present < Base ) 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 @@ def on_and(node) 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 @@ def on_or(node) 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 @@ def autocorrect(corrector, node) 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 diff --git a/Library/Homebrew/rubocops/safe_navigation_with_blank.rb b/Library/Homebrew/rubocops/safe_navigation_with_blank.rb index 74f83fe32ad0a..473ceeea924b6 100644 --- a/Library/Homebrew/rubocops/safe_navigation_with_blank.rb +++ b/Library/Homebrew/rubocops/safe_navigation_with_blank.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true module RuboCop @@ -36,6 +36,7 @@ class SafeNavigationWithBlank < Base (if $(csend ... :blank?) ...) PATTERN + sig { params(node: RuboCop::AST::IfNode).void } def on_if(node) return unless safe_navigation_blank_in_conditional?(node) diff --git a/Library/Homebrew/rubocops/service.rb b/Library/Homebrew/rubocops/service.rb index d7f76b17add58..32300d97c6c88 100644 --- a/Library/Homebrew/rubocops/service.rb +++ b/Library/Homebrew/rubocops/service.rb @@ -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 FormulaAudit 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 diff --git a/Library/Homebrew/rubocops/shared/desc_helper.rb b/Library/Homebrew/rubocops/shared/desc_helper.rb index ac2504a5f73ae..6e458f1378674 100644 --- a/Library/Homebrew/rubocops/shared/desc_helper.rb +++ b/Library/Homebrew/rubocops/shared/desc_helper.rb @@ -17,6 +17,7 @@ module DescHelper 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 @@ def audit_desc(type, name, 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. desc_length = string_content(desc).length @@ -56,7 +57,7 @@ def audit_desc(type, name, desc_call) 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 diff --git a/Library/Homebrew/rubocops/shared/helper_functions.rb b/Library/Homebrew/rubocops/shared/helper_functions.rb index 823d4c26c0dc2..42147e6f67852 100644 --- a/Library/Homebrew/rubocops/shared/helper_functions.rb +++ b/Library/Homebrew/rubocops/shared/helper_functions.rb @@ -32,7 +32,10 @@ def regex_match_group(node, pattern) @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 @@ def line_number(node) 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 diff --git a/Library/Homebrew/rubocops/shared/homepage_helper.rb b/Library/Homebrew/rubocops/shared/homepage_helper.rb index b0f743190c143..f5f53d3544186 100644 --- a/Library/Homebrew/rubocops/shared/homepage_helper.rb +++ b/Library/Homebrew/rubocops/shared/homepage_helper.rb @@ -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 Cop 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? diff --git a/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb b/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb index 8d074add7ab6e..f973dd72b604b 100644 --- a/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb +++ b/Library/Homebrew/rubocops/shared/on_system_conditionals_helper.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "macos_version" @@ -13,16 +13,23 @@ module OnSystemConditionalsHelper 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 @@ def audit_on_system_blocks(body_node, parent_name) 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 @@ def audit_arch_conditionals(body_node, allowed_methods: [], allowed_blocks: []) 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 @@ def audit_base_os_conditionals(body_node, allowed_methods: [], allowed_blocks: [ 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 @@ def audit_macos_version_conditionals(body_node, allowed_methods: [], allowed_blo 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 @@ def audit_macos_references(body_node, allowed_methods: [], allowed_blocks: []) 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 @@ def if_statement_problem(if_node, if_statement_string, on_system_method_string, 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) diff --git a/Library/Homebrew/rubocops/shell_commands.rb b/Library/Homebrew/rubocops/shell_commands.rb index a776e58e8b98c..6dafc4d145b67 100644 --- a/Library/Homebrew/rubocops/shell_commands.rb +++ b/Library/Homebrew/rubocops/shell_commands.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "extend/array" @@ -64,8 +64,12 @@ class ShellCommands < Base ].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 @@ class ExecShellMetacharacters < Base 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 diff --git a/Library/Homebrew/rubocops/text.rb b/Library/Homebrew/rubocops/text.rb index d7f0101fea002..6bbe47f371854 100644 --- a/Library/Homebrew/rubocops/text.rb +++ b/Library/Homebrew/rubocops/text.rb @@ -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 @@ def audit_formula(formula_nodes) 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 @@ def audit_formula(formula_nodes) # 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?(" ") diff --git a/Library/Homebrew/rubocops/urls.rb b/Library/Homebrew/rubocops/urls.rb index af13b6cfb5a08..5bdd2dc6a987e 100644 --- a/Library/Homebrew/rubocops/urls.rb +++ b/Library/Homebrew/rubocops/urls.rb @@ -30,7 +30,7 @@ def audit_formula(formula_nodes) # 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 diff --git a/Library/Homebrew/rubocops/uses_from_macos.rb b/Library/Homebrew/rubocops/uses_from_macos.rb index 2639f09d22025..621f3bc3edfc8 100644 --- a/Library/Homebrew/rubocops/uses_from_macos.rb +++ b/Library/Homebrew/rubocops/uses_from_macos.rb @@ -1,4 +1,4 @@ -# typed: true # rubocop:todo Sorbet/StrictSigil +# typed: strict # frozen_string_literal: true require "rubocops/extend/formula_cop"