Additional handling for passing blocks

This commit is contained in:
Michael Miller 2022-12-17 19:16:38 -07:00
parent 65a4b8e756
commit 9f54a9e542
No known key found for this signature in database
GPG key ID: 32B47AE8F388A1FF
2 changed files with 44 additions and 19 deletions

View file

@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Fixed ### Fixed
- Fix macro logic to support free variables, 'self', and variants on stubbed methods. [#48](https://github.com/icy-arctic-fox/spectator/issues/48) - Fix macro logic to support free variables, 'self', and variants on stubbed methods. [#48](https://github.com/icy-arctic-fox/spectator/issues/48)
- Fix method stubs used on methods that capture blocks.
### Changed ### Changed
- Simplify string representation of mock-related types. - Simplify string representation of mock-related types.

View file

@ -130,14 +130,25 @@ module Spectator
# Workaround for Crystal not propagating block with previous_def/super. # Workaround for Crystal not propagating block with previous_def/super.
if method.accepts_block? if method.accepts_block?
original += "(" original += "("
method.args.each_with_index do |arg, i| if method.splat_index
original += '*' if method.splat_index == i method.args.each_with_index do |arg, i|
original += arg.name.stringify if i == method.splat_index
original += ", " original += '*'
end if arg.internal_name && arg.internal_name.size > 0
if method.double_splat original += "#{arg.internal_name}, "
original += method.double_splat.stringify end
original += ", " original += "**#{method.double_splat}, " if method.double_splat
elsif i > method.splat_index
original += "#{arg.name}: #{arg.internal_name}"
else
original += "#{arg.internal_name}, "
end
end
else
method.args.each do |arg|
original += "#{arg.internal_name}, "
end
original += "**#{method.double_splat}, " if method.double_splat
end end
# If the block is captured (i.e. `&block` syntax), it must be passed along as an argument. # If the block is captured (i.e. `&block` syntax), it must be passed along as an argument.
# Otherwise, use `yield` to forward the block. # Otherwise, use `yield` to forward the block.
@ -269,14 +280,25 @@ module Spectator
# Workaround for Crystal not propagating block with previous_def/super. # Workaround for Crystal not propagating block with previous_def/super.
if method.accepts_block? if method.accepts_block?
original += "(" original += "("
method.args.each_with_index do |arg, i| if method.splat_index
original += '*' if method.splat_index == i method.args.each_with_index do |arg, i|
original += arg.name.stringify if i == method.splat_index
original += ", " original += '*'
end if arg.internal_name && arg.internal_name.size > 0
if method.double_splat original += "#{arg.internal_name}, "
original += method.double_splat.stringify end
original += ", " original += "**#{method.double_splat}, " if method.double_splat
elsif i > method.splat_index
original += "#{arg.name}: #{arg.internal_name}"
else
original += "#{arg.internal_name}, "
end
end
else
method.args.each do |arg|
original += "#{arg.internal_name}, "
end
original += "**#{method.double_splat}, " if method.double_splat
end end
# If the block is captured (i.e. `&block` syntax), it must be passed along as an argument. # If the block is captured (i.e. `&block` syntax), it must be passed along as an argument.
# Otherwise, use `yield` to forward the block. # Otherwise, use `yield` to forward the block.
@ -467,9 +489,11 @@ module Spectator
{% if method.block_arg %}&{{method.block_arg}}{% elsif method.accepts_block? %}&{% end %} {% if method.block_arg %}&{{method.block_arg}}{% elsif method.accepts_block? %}&{% end %}
){% if method.return_type %} : {{method.return_type}}{% end %}{% if !method.free_vars.empty? %} forall {{method.free_vars.splat}}{% end %} ){% if method.return_type %} : {{method.return_type}}{% end %}{% if !method.free_vars.empty? %} forall {{method.free_vars.splat}}{% end %}
{% unless method.abstract? %} {% unless method.abstract? %}
{{scope}}{% if method.accepts_block? %}( {{scope}}{% if method.accepts_block? %}({% for arg, i in method.args %}
{% for arg, i in method.args %}{% if i == method.splat_index %}*{% end %}{{arg.name}}, {% end %} {% if i == method.splat_index && arg.internal_name && arg.internal_name.size > 0 %}*{{arg.internal_name}}, {% if method.double_splat %}**{{method.double_splat}}, {% end %}{% end %}
{% if method.double_splat %}**{{method.double_splat}}, {% end %} {% if method.splat_index && i > method.splat_index %}{{arg.name}}: {{arg.internal_name}}, {% end %}
{% if !method.splat_index || i < method.splat_index %}{{arg.internal_name}}, {% end %}{% end %}
{% if !method.splat_index && method.double_splat %}**{{method.double_splat}}, {% end %}
{% captured_block = if method.block_arg && method.block_arg.name && method.block_arg.name.size > 0 {% captured_block = if method.block_arg && method.block_arg.name && method.block_arg.name.size > 0
method.block_arg.name method.block_arg.name
else else