Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recognize more pass-through constructor signatures #92

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading