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")
|
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.
|
# 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
|
context "plain double" do
|
||||||
subject(dbl) { FooBarDouble.new }
|
subject(dbl) { FooBarDouble.new }
|
||||||
|
|
||||||
|
@ -38,6 +38,10 @@ Spectator.describe Spectator::Double do
|
||||||
it "uses nil for undefined messages" do
|
it "uses nil for undefined messages" do
|
||||||
expect { dbl.baz }.to compile_as(Nil)
|
expect { dbl.baz }.to compile_as(Nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "supports blocks" do
|
||||||
|
dbl.bar
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "without a double name" do
|
context "without a double name" do
|
||||||
|
|
|
@ -269,12 +269,33 @@ module Spectator
|
||||||
end
|
end
|
||||||
|
|
||||||
# Utility for defining a stubbed method and a fallback.
|
# 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)
|
private macro inject_stub(method)
|
||||||
{% if method.abstract? %}
|
{% 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 %}
|
{% else %}
|
||||||
{{method}}
|
{% if method.visibility != :public %}{{method.visibility.id}}{% end %} def {{method.receiver}}{{method.name}}(
|
||||||
stub {{method}}
|
{% 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 %}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue