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