Skip to content

Commit

Permalink
Recognize more pass-through constructor signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
flash-gordon committed Nov 12, 2023
1 parent 4c703d5 commit 9ecab4c
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 5 deletions.
2 changes: 1 addition & 1 deletion lib/dry/auto_inject/dependency_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module AutoInject
DuplicateDependencyError = Class.new(StandardError)
DependencyNameInvalid = Class.new(StandardError)

VALID_NAME = /([a-z_][a-zA-Z_0-9]*)$/.freeze
VALID_NAME = /([a-z_][a-zA-Z_0-9]*)$/

class DependencyMap
def initialize(*dependencies)
Expand Down
17 changes: 15 additions & 2 deletions lib/dry/auto_inject/method_parameters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,22 @@ class MethodParameters
PASS_THROUGH = [
[%i[rest]],
[%i[rest], %i[keyrest]],
[%i[keyrest]],
[%i[keyrest], %i[block &]],
[%i[block]],
[%i[rest *]],
[%i[rest *], %i[keyrest **]]
].freeze
[%i[rest *], %i[keyrest **]],
[%i[rest *], %i[block &]],
[%i[keyrest **]],
[%i[keyrest **], %i[block &]],
[%i[block &]]
].to_set

unless RUBY_VERSION < "3.1"
PASS_THROUGH << [%i[rest *], %i[block &]]
end

PASS_THROUGH.freeze

def self.of(obj, name)
Enumerator.new do |y|
Expand Down
1 change: 1 addition & 0 deletions lib/dry/auto_inject/strategies/kwargs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def define_initialize(klass)
super_parameters = MethodParameters.of(klass, :initialize).each do |ps|
# Look upwards past `def foo(*)` and `def foo(...)` methods
# until we get an explicit list of parameters

break ps unless ps.pass_through?
end

Expand Down
3 changes: 1 addition & 2 deletions spec/integration/kwargs/super_initialize_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ def initialize(*args)
Class.new do
# rubocop:disable Lint/RedundantCopDisableDirective
# rubocop:disable Style/RedundantInitialize
def initialize
end
def initialize; end
# rubocop:enable Style/RedundantInitialize
# rubocop:enable Lint/RedundantCopDisableDirective
end
Expand Down
44 changes: 44 additions & 0 deletions spec/unit/method_parameters_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def initialize(*)
all_parameters = parameters.of(klass, :initialize).to_a

expect(all_parameters.size).to eq 2

if RUBY_VERSION >= "3.2"
expect(all_parameters[0].parameters).to eql([[:rest, :*]])
else
Expand All @@ -53,4 +54,47 @@ def initialize(*)
expect(all_parameters[1]).to be_empty
end
end

describe "#pass_through?" do
klass = Class.new {
def arg_kwarg(*, **) = super

def arg(*) = super

def kwarg(**) = super

def ellipsis(...) = super

if RUBY_VERSION >= "3.1"
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
def arg_kwarg_block(*, **, &) = super
def arg_block(*, &) = super
def kwarg_block(**, &) = super
RUBY
else
alias_method :arg_kwarg_block, :arg
alias_method :arg_block, :arg
alias_method :kwarg_block, :kwarg
end
}

it "returns true for pass-through methods" do
expect(parameters.of(klass, :arg_kwarg).first).to be_pass_through
expect(parameters.of(klass, :arg).first).to be_pass_through
expect(parameters.of(klass, :kwarg).first).to be_pass_through
expect(parameters.of(klass, :arg_block).first).to be_pass_through
expect(parameters.of(klass, :kwarg_block).first).to be_pass_through
end

it "returns false for non-pass-through methods" do
# ellipsis are treated differently because
# it can be used for delegation to methods other than super
expect(parameters.of(klass, :ellipsis).first).not_to be_pass_through
# same signature
expect(parameters.of(klass, :arg_kwarg_block).first).not_to be_pass_through
end
end
end

0 comments on commit 9ecab4c

Please sign in to comment.