Merge pull request #18520 from Homebrew/delegator-compiler
Add a Delegator DSL compiler
This commit is contained in:
commit
69941c0c73
@ -8,11 +8,23 @@ module Cask
|
|||||||
# Class corresponding to the `url` stanza.
|
# Class corresponding to the `url` stanza.
|
||||||
class URL < Delegator
|
class URL < Delegator
|
||||||
class DSL
|
class DSL
|
||||||
attr_reader :uri, :specs,
|
attr_reader :uri, :tag, :branch, :revisions, :revision,
|
||||||
:verified, :using,
|
:trust_cert, :cookies, :header, :data, :only_path
|
||||||
:tag, :branch, :revisions, :revision,
|
|
||||||
:trust_cert, :cookies, :referer, :header, :user_agent,
|
sig { returns(T.nilable(T.any(URI::Generic, String))) }
|
||||||
:data, :only_path
|
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
|
extend Forwardable
|
||||||
def_delegators :uri, :path, :scheme, :to_s
|
def_delegators :uri, :path, :scheme, :to_s
|
||||||
@ -137,6 +149,8 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
# Allows calling a nested `url` stanza in a `url do` block.
|
# Allows calling a nested `url` stanza in a `url do` block.
|
||||||
#
|
#
|
||||||
# @api public
|
# @api public
|
||||||
@ -150,7 +164,6 @@ module Cask
|
|||||||
def url(uri, &block)
|
def url(uri, &block)
|
||||||
self.class.new(uri, dsl: @dsl, &block).call
|
self.class.new(uri, dsl: @dsl, &block).call
|
||||||
end
|
end
|
||||||
private :url
|
|
||||||
|
|
||||||
# This allows calling DSL methods from inside a `url` block.
|
# This allows calling DSL methods from inside a `url` block.
|
||||||
#
|
#
|
||||||
@ -162,12 +175,10 @@ module Cask
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
private :method_missing
|
|
||||||
|
|
||||||
def respond_to_missing?(method, include_all)
|
def respond_to_missing?(method, include_all)
|
||||||
@dsl.respond_to?(method, include_all) || super
|
@dsl.respond_to?(method, include_all) || super
|
||||||
end
|
end
|
||||||
private :respond_to_missing?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
@ -244,30 +255,11 @@ module Cask
|
|||||||
@caller_location = caller_location
|
@caller_location = caller_location
|
||||||
end
|
end
|
||||||
|
|
||||||
def __getobj__
|
|
||||||
@dsl
|
|
||||||
end
|
|
||||||
|
|
||||||
def __setobj__(dsl)
|
|
||||||
@dsl = dsl
|
|
||||||
end
|
|
||||||
|
|
||||||
sig { returns(Homebrew::SourceLocation) }
|
sig { returns(Homebrew::SourceLocation) }
|
||||||
def location
|
def location
|
||||||
Homebrew::SourceLocation.new(@caller_location.lineno, raw_url_line&.index("url"))
|
Homebrew::SourceLocation.new(@caller_location.lineno, raw_url_line&.index("url"))
|
||||||
end
|
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) }
|
sig { params(ignore_major_version: T::Boolean).returns(T::Boolean) }
|
||||||
def unversioned?(ignore_major_version: false)
|
def unversioned?(ignore_major_version: false)
|
||||||
interpolated_url = raw_url_line&.then { |line| line[/url\s+"([^"]+)"/, 1] }
|
interpolated_url = raw_url_line&.then { |line| line[/url\s+"([^"]+)"/, 1] }
|
||||||
@ -283,5 +275,23 @@ module Cask
|
|||||||
def from_block?
|
def from_block?
|
||||||
@from_block
|
@from_block
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|||||||
@ -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
|
|
||||||
64
Library/Homebrew/sorbet/rbi/dsl/cask/url.rbi
generated
Normal file
64
Library/Homebrew/sorbet/rbi/dsl/cask/url.rbi
generated
Normal file
@ -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
|
||||||
40
Library/Homebrew/sorbet/tapioca/compilers/delegators.rb
Normal file
40
Library/Homebrew/sorbet/tapioca/compilers/delegators.rb
Normal file
@ -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
|
||||||
Loading…
x
Reference in New Issue
Block a user