Cleanup and docs

This commit is contained in:
Michael Miller 2022-04-28 22:22:07 -06:00
parent ad24515d58
commit 978e6c3625
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2

View file

@ -247,6 +247,33 @@ module Spectator
end
end
# Redefines a method to require stubs.
#
# The *method* can be a `Def`.
# That is, a normal looking method definition should follow the `stub` keyword.
#
# ```
# stub def stubbed_method
# "foobar"
# end
# ```
#
# If the *method* is abstract, then a stub must be provided otherwise attempts to call the method will raise `UnexpectedMessage`.
#
# ```
# stub abstract def stubbed_method
# ```
#
# A `Call` can also be specified.
# In this case all methods in the stubbed type and its ancestors that match the call's signature are stubbed.
#
# ```
# stub stubbed_method(arg)
# ```
#
# The method being stubbed doesn't need to exist yet.
# Stubbed methods will call `#_spectator_find_stub` with the method call information.
# If no stub is found, then `#_spectator_stub_fallback` or `#_spectator_abstract_stub_fallback` is called.
macro stub(method)
{% raise "Cannot define a stub inside a method" if @def %}
@ -261,6 +288,36 @@ module Spectator
{% end %}
end
# Redefines all methods and ones inherited from its parents and mixins to support stubs.
private macro stub_hierarchy(type_name = @type)
{% type = type_name.resolve
# Reverse order of ancestors (there's currently no reverse method for ArrayLiteral).
count = type.ancestors.size
ancestors = type.ancestors.map_with_index { |_, i| type.ancestors[count - i - 1] } %}
{% for ancestor in ancestors %}
stub_type {{ancestor}}
{% end %}
stub_type {{type_name}}
end
# Redefines all methods in the specified type to support stubs.
private macro stub_type(type_name = @type)
{% type = type_name.resolve %}
{% for method in type.methods.reject do |meth|
meth.name.starts_with?("_spectator") ||
::Spectator::DSL::RESERVED_KEYWORDS.includes?(meth.name.symbolize)
end %}
{{(method.abstract? ? :abstract_stub : :default_stub).id}} {{method.visibility.id if method.visibility != :public}} 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 %}
{{ type == @type ? :previous_def.id : :super.id }}{{ " { |*_spectator_yargs| yield *_spectator_yargs }".id if method.accepts_block? }}
end
{% end %}
end
# Utility macro for casting a stub (and it's return value) to the correct type.
#
# *stub* is the variable holding the stub.
@ -300,34 +357,5 @@ module Spectator
end
end
end
# Redefines all methods and ones inherited from its parents and mixins to support stubs.
private macro stub_hierarchy(type_name = @type)
{% type = type_name.resolve
# Reverse order of ancestors (there's currently no reverse method for ArrayLiteral).
count = type.ancestors.size
ancestors = type.ancestors.map_with_index { |_, i| type.ancestors[count - i - 1] } %}
{% for ancestor in ancestors %}
stub_type {{ancestor}}
{% end %}
stub_type {{type_name}}
end
private macro stub_type(type_name = @type)
{% type = type_name.resolve %}
{% for method in type.methods.reject do |meth|
meth.name.starts_with?("_spectator") ||
::Spectator::DSL::RESERVED_KEYWORDS.includes?(meth.name.symbolize)
end %}
{{(method.abstract? ? :abstract_stub : :default_stub).id}} {{method.visibility.id if method.visibility != :public}} 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 %}
{{ type == @type ? :previous_def.id : :super.id }}{{ " { |*_spectator_yargs| yield *_spectator_yargs }".id if method.accepts_block? }}
end
{% end %}
end
end
end