From ed00dc0b956cb717c7c3c83f45580be4673374c9 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 6 Feb 2024 16:04:08 +0100 Subject: [PATCH] Add type annotations for cask loaders. --- Library/Homebrew/cask/cask_loader.rb | 58 ++++++++++++++++++++++------ Library/Homebrew/tap_constants.rb | 2 +- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/Library/Homebrew/cask/cask_loader.rb b/Library/Homebrew/cask/cask_loader.rb index 5d7901a854..86a4885e2d 100644 --- a/Library/Homebrew/cask/cask_loader.rb +++ b/Library/Homebrew/cask/cask_loader.rb @@ -18,6 +18,11 @@ module Cask extend T::Helpers interface! + sig { overridable.params(_ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } + def self.can_load?(_ref) + false + end + sig { abstract.params(config: Config).returns(Cask) } def load(config:); end end @@ -50,10 +55,11 @@ module Cask # Loads a cask from a string. class FromContentLoader < AbstractContentLoader + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) return false unless ref.respond_to?(:to_str) - content = ref.to_str + content = T.unsafe(ref).to_str # Cache compiled regex @regex ||= begin @@ -66,7 +72,8 @@ module Cask content.match?(@regex) end - def initialize(content, tap: nil) + sig { params(content: String, tap: Tap).void } + def initialize(content, tap: T.unsafe(nil)) super() @content = content.force_encoding("UTF-8") @@ -82,14 +89,19 @@ module Cask # Loads a cask from a path. class FromPathLoader < AbstractContentLoader + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) - path = Pathname(ref) + ref = Pathname(ref) if ref.is_a?(String) + return false unless ref.is_a?(Pathname) + + path = ref %w[.rb .json].include?(path.extname) && path.expand_path.exist? end attr_reader :token, :path - def initialize(path, token: nil) + sig { params(path: T.any(Pathname, String), token: String).void } + def initialize(path, token: T.unsafe(nil)) super() path = Pathname(path).expand_path @@ -134,6 +146,7 @@ module Cask # Loads a cask from a URI. class FromURILoader < FromPathLoader + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) # Cache compiled regex @uri_regex ||= begin @@ -141,9 +154,10 @@ module Cask Regexp.new("\\A#{uri_regex.source}\\Z", uri_regex.options) end - return false unless ref.to_s.match?(@uri_regex) + uri = ref.to_s + return false unless uri.match?(@uri_regex) - uri = URI(ref) + uri = URI(uri) return false unless uri.path true @@ -173,10 +187,12 @@ module Cask # Loads a cask from a tap path. class FromTapPathLoader < FromPathLoader + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) super && !Tap.from_path(ref).nil? end + sig { params(path: T.any(Pathname, String)).void } def initialize(path) super(path) @tap = Tap.from_path(path) @@ -185,10 +201,12 @@ module Cask # Loads a cask from a specific tap. class FromTapLoader < FromTapPathLoader + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) ref.to_s.match?(HOMEBREW_TAP_CASK_REGEX) end + sig { params(tapped_name: String).void } def initialize(tapped_name) user, repo, token = tapped_name.split("/", 3) tap = Tap.fetch(user, repo) @@ -205,10 +223,12 @@ module Cask # Loads a cask from the default tap path. class FromDefaultTapPathLoader < FromTapPathLoader + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) super CaskLoader.default_path(ref) end + sig { params(ref: String).void } def initialize(ref) super CaskLoader.default_path(ref) end @@ -217,10 +237,13 @@ module Cask # Loads a cask from an existing {Cask} instance. class FromInstanceLoader include ILoader + + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) ref.is_a?(Cask) end + sig { params(cask: Cask).void } def initialize(cask) @cask = cask end @@ -233,25 +256,32 @@ module Cask # Loads a cask from the JSON API. class FromAPILoader include ILoader + attr_reader :token, :path + sig { returns(T.nilable(Hash)) } + attr_reader :from_json + + sig { params(ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } def self.can_load?(ref) return false if Homebrew::EnvConfig.no_install_from_api? return false unless ref.is_a?(String) - return false unless ref.match?(HOMEBREW_MAIN_TAP_CASK_REGEX) - token = ref.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "") + return false unless (match = ref.match(HOMEBREW_MAIN_TAP_CASK_REGEX)) + + token = match[:token] Homebrew::API::Cask.all_casks.key?(token) end - def initialize(token, from_json: nil) + sig { params(token: String, from_json: Hash).void } + def initialize(token, from_json: T.unsafe(nil)) @token = token.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "") @path = CaskLoader.default_path(@token) @from_json = from_json end def load(config:) - json_cask = @from_json || Homebrew::API::Cask.all_casks[token] + json_cask = from_json || Homebrew::API::Cask.all_casks[token] cask_options = { loaded_from_api: true, @@ -401,7 +431,8 @@ module Cask # Pseudo-loader which raises an error when trying to load the corresponding cask. class NullLoader < FromPathLoader - def self.can_load?(*) + sig { params(_ref: T.any(String, Pathname, Cask, URI::Generic)).returns(T::Boolean) } + def self.can_load?(_ref) true end @@ -468,6 +499,7 @@ module Cask if [FromAPILoader, FromTapLoader].include?(loader_class) token, tap, = tap_cask_token_type(ref, warn: warn) + loader_class = T.cast(loader_class, T.any(T.class_of(FromAPILoader), T.class_of(FromTapLoader))) return loader_class.new("#{tap}/#{token}") end @@ -484,7 +516,9 @@ module Cask end possible_installed_cask = Cask.new(ref) - return FromPathLoader.new(possible_installed_cask.installed_caskfile) if possible_installed_cask.installed? + if (installed_caskfile = possible_installed_cask.installed_caskfile) + return FromPathLoader.new(installed_caskfile) + end NullLoader.new(ref) end diff --git a/Library/Homebrew/tap_constants.rb b/Library/Homebrew/tap_constants.rb index 2df0d9a759..a9fc1bdd9b 100644 --- a/Library/Homebrew/tap_constants.rb +++ b/Library/Homebrew/tap_constants.rb @@ -6,7 +6,7 @@ HOMEBREW_TAP_FORMULA_REGEX = T.let(%r{^([\w-]+)/([\w-]+)/([\w+-.@]+)$}, Regexp) # Match taps' casks, e.g. `someuser/sometap/somecask` HOMEBREW_TAP_CASK_REGEX = T.let(%r{^([\w-]+)/([\w-]+)/([a-z0-9\-_]+)$}, Regexp) # Match main cask taps' casks, e.g. `homebrew/cask/somecask` or `somecask` -HOMEBREW_MAIN_TAP_CASK_REGEX = T.let(%r{^([Hh]omebrew/(?:homebrew-)?cask/)?[a-z0-9\-_]+$}, Regexp) +HOMEBREW_MAIN_TAP_CASK_REGEX = T.let(%r{^(?[Hh]omebrew/(?:homebrew-)?cask/)?(?[a-z0-9\-_]+)$}, Regexp) # Match taps' directory paths, e.g. `HOMEBREW_LIBRARY/Taps/someuser/sometap` HOMEBREW_TAP_DIR_REGEX = T.let( %r{#{Regexp.escape(HOMEBREW_LIBRARY.to_s)}/Taps/(?[\w-]+)/(?[\w-]+)}, Regexp