diff --git a/Library/Homebrew/cask/url.rb b/Library/Homebrew/cask/url.rb index 627163ee65..6cbfdd13fa 100644 --- a/Library/Homebrew/cask/url.rb +++ b/Library/Homebrew/cask/url.rb @@ -8,11 +8,23 @@ module Cask # Class corresponding to the `url` stanza. class URL < Delegator class DSL - attr_reader :uri, :specs, - :verified, :using, - :tag, :branch, :revisions, :revision, - :trust_cert, :cookies, :referer, :header, :user_agent, - :data, :only_path + attr_reader :uri, :tag, :branch, :revisions, :revision, + :trust_cert, :cookies, :header, :data, :only_path + + sig { returns(T.nilable(T.any(URI::Generic, String))) } + attr_reader :referer + + sig { returns(T::Hash[Symbol, T.untyped]) } + attr_reader :specs + + sig { returns(T.nilable(T.any(Symbol, String))) } + attr_reader :user_agent + + sig { returns(T.any(T::Class[T.anything], Symbol, NilClass)) } + attr_reader :using + + sig { returns(T.nilable(String)) } + attr_reader :verified extend Forwardable def_delegators :uri, :path, :scheme, :to_s @@ -137,6 +149,8 @@ module Cask end end + private + # Allows calling a nested `url` stanza in a `url do` block. # # @api public @@ -150,7 +164,6 @@ module Cask def url(uri, &block) self.class.new(uri, dsl: @dsl, &block).call end - private :url # This allows calling DSL methods from inside a `url` block. # @@ -162,12 +175,10 @@ module Cask super end end - private :method_missing def respond_to_missing?(method, include_all) @dsl.respond_to?(method, include_all) || super end - private :respond_to_missing? end sig { @@ -244,30 +255,11 @@ module Cask @caller_location = caller_location end - def __getobj__ - @dsl - end - - def __setobj__(dsl) - @dsl = dsl - end - sig { returns(Homebrew::SourceLocation) } def location Homebrew::SourceLocation.new(@caller_location.lineno, raw_url_line&.index("url")) end - sig { returns(T.nilable(String)) } - def raw_url_line - return @raw_url_line if defined?(@raw_url_line) - - @raw_url_line = Pathname(T.must(@caller_location.path)) - .each_line - .drop(@caller_location.lineno - 1) - .first - end - private :raw_url_line - sig { params(ignore_major_version: T::Boolean).returns(T::Boolean) } def unversioned?(ignore_major_version: false) interpolated_url = raw_url_line&.then { |line| line[/url\s+"([^"]+)"/, 1] } @@ -283,5 +275,23 @@ module Cask def from_block? @from_block end + + private + + def __getobj__ = @dsl + + def __setobj__(dsl) + @dsl = dsl + end + + sig { returns(T.nilable(String)) } + def raw_url_line + return @raw_url_line if defined?(@raw_url_line) + + @raw_url_line = Pathname(T.must(@caller_location.path)) + .each_line + .drop(@caller_location.lineno - 1) + .first + end end end diff --git a/Library/Homebrew/cask/url.rbi b/Library/Homebrew/cask/url.rbi deleted file mode 100644 index 3c56476e6d..0000000000 --- a/Library/Homebrew/cask/url.rbi +++ /dev/null @@ -1,24 +0,0 @@ -# typed: strict - -module Cask - class URL - include Kernel - - # TODO: Generate this - - sig { returns(T.any(T::Class[T.anything], Symbol, NilClass)) } - def using; end - - sig { returns(T.nilable(T.any(URI::Generic, String))) } - def referer; end - - sig { returns(T::Hash[Symbol, T.untyped]) } - def specs; end - - sig { returns(T.nilable(T.any(Symbol, String))) } - def user_agent; end - - sig { returns(T.nilable(String)) } - def verified; end - end -end diff --git a/Library/Homebrew/sorbet/rbi/dsl/cask/url.rbi b/Library/Homebrew/sorbet/rbi/dsl/cask/url.rbi new file mode 100644 index 0000000000..2cd61a1d6f --- /dev/null +++ b/Library/Homebrew/sorbet/rbi/dsl/cask/url.rbi @@ -0,0 +1,64 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for dynamic methods in `Cask::URL`. +# Please instead update this file by running `bin/tapioca dsl Cask::URL`. + + +class Cask::URL + include Kernel + + sig { returns(T.untyped) } + def branch; end + + sig { returns(T.untyped) } + def cookies; end + + sig { returns(T.untyped) } + def data; end + + sig { returns(T.untyped) } + def header; end + + sig { returns(T.untyped) } + def only_path; end + + sig { returns(T.untyped) } + def path; end + + sig { returns(T.nilable(T.any(::String, ::URI::Generic))) } + def referer; end + + sig { returns(T.untyped) } + def revision; end + + sig { returns(T.untyped) } + def revisions; end + + sig { returns(T.untyped) } + def scheme; end + + sig { returns(T::Hash[::Symbol, T.untyped]) } + def specs; end + + sig { returns(T.untyped) } + def tag; end + + sig { returns(T.untyped) } + def to_s; end + + sig { returns(T.untyped) } + def trust_cert; end + + sig { returns(T.untyped) } + def uri; end + + sig { returns(T.nilable(T.any(::String, ::Symbol))) } + def user_agent; end + + sig { returns(T.nilable(T.any(::Symbol, T::Class[T.anything]))) } + def using; end + + sig { returns(T.nilable(::String)) } + def verified; end +end diff --git a/Library/Homebrew/sorbet/tapioca/compilers/delegators.rb b/Library/Homebrew/sorbet/tapioca/compilers/delegators.rb new file mode 100644 index 0000000000..681d7fcc3d --- /dev/null +++ b/Library/Homebrew/sorbet/tapioca/compilers/delegators.rb @@ -0,0 +1,40 @@ +# typed: strict +# frozen_string_literal: true + +require_relative "../../../global" +require "cask/url" + +module Tapioca + module Compilers + # A compiler for subclasses of Delegator. + # To add a new delegator: require it above add add it to the DELEGATIONS hash below. + class Delegators < Tapioca::Dsl::Compiler + # Mapping of delegator classes to the classes they delegate to (as defined in `__getobj__`). + DELEGATIONS = T.let({ + Cask::URL => Cask::URL::DSL, + }.freeze, T::Hash[Module, Module]) + ConstantType = type_member { { fixed: Module } } + + sig { override.returns(T::Enumerable[Module]) } + def self.gather_constants = DELEGATIONS.keys + + sig { override.void } + def decorate + root.create_path(constant) do |klass| + # Note that `Delegtor` does not subclass `Object`: + # https://github.com/ruby/ruby/blob/a6383fb/lib/delegate.rb#L41 + # but we assume that we are delegating to a class that does. + klass.create_include("Kernel") + delegated = DELEGATIONS.fetch(constant) + + delegated.instance_methods(false).each do |method| + signature = T::Utils.signature_for_method(delegated.instance_method(method)) + # TODO: handle methods with parameters + return_type = signature&.return_type&.to_s || "T.untyped" + klass.create_method(method.to_s, return_type:) + end + end + end + end + end +end