mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Explode method expansion
Somewhere along the way the block argument gets dropped. Even though `method` is a `Def` that accepts a block, the `&block` portion is dropped. Possible Crystal compiler bug.
This commit is contained in:
parent
15dd2ea6f1
commit
17e97cb39a
2 changed files with 29 additions and 4 deletions
|
@ -5,7 +5,7 @@ Spectator.describe Spectator::Double do
|
|||
Spectator::Double.define(FooBarDouble, "dbl-name", foo: 42, bar: "baz")
|
||||
|
||||
# The subject `dbl` must be carefully used in sub-contexts, otherwise it pollutes parent scopes.
|
||||
# This changes the type of `dbl` to `Double`, which produces a union of methods and their return types.
|
||||
# This changes the type of `dbl` to `Double+`, which produces a union of methods and their return types.
|
||||
context "plain double" do
|
||||
subject(dbl) { FooBarDouble.new }
|
||||
|
||||
|
@ -38,6 +38,10 @@ Spectator.describe Spectator::Double do
|
|||
it "uses nil for undefined messages" do
|
||||
expect { dbl.baz }.to compile_as(Nil)
|
||||
end
|
||||
|
||||
it "supports blocks" do
|
||||
dbl.bar
|
||||
end
|
||||
end
|
||||
|
||||
context "without a double name" do
|
||||
|
|
|
@ -269,12 +269,33 @@ module Spectator
|
|||
end
|
||||
|
||||
# Utility for defining a stubbed method and a fallback.
|
||||
#
|
||||
# NOTE: The method definition is exploded and redefined by its parts because using `{{method}}` omits the block argument.
|
||||
private macro inject_stub(method)
|
||||
{% if method.abstract? %}
|
||||
abstract_stub {{method}}
|
||||
abstract_stub {% if method.visibility != :public %}{{method.visibility.id}}{% end %} abstract def {{method.receiver}}{{method.name}}(
|
||||
{% for arg, i in method.args %}{% if i == method.splat_index %}*{% end %}{{arg}}, {% end %}
|
||||
{% if method.double_splat %}**{{method.double_splat}}, {% 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 %}
|
||||
{% else %}
|
||||
{{method}}
|
||||
stub {{method}}
|
||||
{% if method.visibility != :public %}{{method.visibility.id}}{% end %} def {{method.receiver}}{{method.name}}(
|
||||
{% for arg, i in method.args %}{% if i == method.splat_index %}*{% end %}{{arg}}, {% end %}
|
||||
{% if method.double_splat %}**{{method.double_splat}}, {% 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 %}
|
||||
{{method.body}}
|
||||
end
|
||||
|
||||
stub {% if method.visibility != :public %}{{method.visibility.id}}{% end %} def {{method.receiver}}{{method.name}}(
|
||||
{% for arg, i in method.args %}{% if i == method.splat_index %}*{% end %}{{arg}}, {% end %}
|
||||
{% if method.double_splat %}**{{method.double_splat}}, {% 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 %}
|
||||
# Content of this method is discarded,
|
||||
# but this will compile successfully even if it's used.
|
||||
previous_def{% if method.accepts_block? %} { |*%yargs| yield *%yargs }{% end %}
|
||||
end
|
||||
{% end %}
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue