Merge branch 'master' into example-api

This commit is contained in:
Michael Miller 2020-11-07 11:18:47 -07:00
commit b8901d485d
No known key found for this signature in database
GPG key ID: FB9F12F7C646A4AD
2 changed files with 49 additions and 11 deletions

View file

@ -7,7 +7,7 @@ module Spectator::Mocks
def initialize(@spectator_double_name : String, @null = false) def initialize(@spectator_double_name : String, @null = false)
end end
private macro stub(definition, &block) private macro stub(definition, *types, return_type = :undefined, &block)
{% {%
name = nil name = nil
params = nil params = nil
@ -44,12 +44,27 @@ module Spectator::Mocks
params = [] of MacroId params = [] of MacroId
args = [] of MacroId args = [] of MacroId
body = block body = block
elsif definition.is_a?(SymbolLiteral) # stub :foo, arg : Int32
name = definition.id
named = false
params = types
if params.last.is_a?(Call)
body = params.last.block
params[-1] = params.last.name
end
args = params.map do |p|
n = p.is_a?(TypeDeclaration) ? p.var : p.id
r = named ? "#{n}: #{n}".id : n
named = true if n.starts_with?('*')
r
end
body = block unless body
else else
raise "Unrecognized stub format" raise "Unrecognized stub format"
end end
%} %}
def {{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} def {{name}}({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args)
::Spectator::Harness.current.mocks.record_call(self, %call) ::Spectator::Harness.current.mocks.record_call(self, %call)
@ -60,7 +75,7 @@ module Spectator::Mocks
end end
end end
def {{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} def {{name}}({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args)
::Spectator::Harness.current.mocks.record_call(self, %call) ::Spectator::Harness.current.mocks.record_call(self, %call)
@ -73,9 +88,11 @@ module Spectator::Mocks
end end
end end
def %method({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} def %method({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
{% if body && !body.is_a?(Nop) %} {% if body && !body.is_a?(Nop) %}
{{body.body}} {{body.body}}
{% elsif return_type.is_a?(ArrayLiteral) %}
{{return_type.splat}}
{% else %} {% else %}
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args)
@ -84,7 +101,9 @@ module Spectator::Mocks
end end
# This code shouldn't be reached, but makes the compiler happy to have a matching return type. # This code shouldn't be reached, but makes the compiler happy to have a matching return type.
{% if definition.is_a?(TypeDeclaration) %} {% if return_type != :undefined %}
%x = uninitialized {{return_type}}
{% elsif definition.is_a?(TypeDeclaration) %}
%x = uninitialized {{definition.type}} %x = uninitialized {{definition.type}}
{% else %} {% else %}
nil nil

View file

@ -1,6 +1,6 @@
module Spectator::Mocks module Spectator::Mocks
module Stubs module Stubs
private macro stub(definition, _file = __FILE__, _line = __LINE__, &block) private macro stub(definition, *types, _file = __FILE__, _line = __LINE__, return_type = :undefined, &block)
{% {%
receiver = nil receiver = nil
name = nil name = nil
@ -30,6 +30,21 @@ module Spectator::Mocks
params = [] of MacroId params = [] of MacroId
args = [] of MacroId args = [] of MacroId
body = block body = block
elsif definition.is_a?(SymbolLiteral) # stub :foo, arg : Int32
name = definition.id
named = false
params = types
if params.last.is_a?(Call)
body = params.last.block
params[-1] = params.last.name
end
args = params.map do |p|
n = p.is_a?(TypeDeclaration) ? p.var : p.id
r = named ? "#{n}: #{n}".id : n
named = true if n.starts_with?('*')
r
end
body = block unless body
else else
raise "Unrecognized stub format" raise "Unrecognized stub format"
end end
@ -50,12 +65,16 @@ module Spectator::Mocks
%} %}
{% if body && !body.is_a?(Nop) %} {% if body && !body.is_a?(Nop) %}
def {{receiver}}%method({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} def {{receiver}}%method({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
{{body.body}} {{body.body}}
end end
{% elsif return_type.is_a?(ArrayLiteral) %}
def {{receiver}}%method({{params.splat}}) : {{return_type.type}}
{{return_type.splat}}
end
{% end %} {% end %}
def {{receiver}}{{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} def {{receiver}}{{name}}({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
if (%harness = ::Spectator::Harness.current?) if (%harness = ::Spectator::Harness.current?)
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args)
@ -64,7 +83,7 @@ module Spectator::Mocks
return %stub.call!(%args) { {{original}} } return %stub.call!(%args) { {{original}} }
end end
{% if body && !body.is_a?(Nop) %} {% if body && !body.is_a?(Nop) || return_type.is_a?(ArrayLiteral) %}
%method({{args.splat}}) %method({{args.splat}})
{% else %} {% else %}
{{original}} {{original}}
@ -74,7 +93,7 @@ module Spectator::Mocks
end end
end end
def {{receiver}}{{name}}({{params.splat}}){% if definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %} def {{receiver}}{{name}}({{params.splat}}){% if return_type.is_a?(ArrayLiteral) %} : {{return_type.type}}{% elsif return_type != :undefined %} : {{return_type.id}}{% elsif definition.is_a?(TypeDeclaration) %} : {{definition.type}}{% end %}
if (%harness = ::Spectator::Harness.current?) if (%harness = ::Spectator::Harness.current?)
%args = ::Spectator::Mocks::GenericArguments.create({{args.splat}}) %args = ::Spectator::Mocks::GenericArguments.create({{args.splat}})
%call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args) %call = ::Spectator::Mocks::MethodCall.new({{name.symbolize}}, %args)
@ -83,7 +102,7 @@ module Spectator::Mocks
return %stub.call!(%args) { {{original}} { |*%ya| yield *%ya } } return %stub.call!(%args) { {{original}} { |*%ya| yield *%ya } }
end end
{% if body && !body.is_a?(Nop) %} {% if body && !body.is_a?(Nop) || return_type.is_a?(ArrayLiteral) %}
%method({{args.splat}}) { |*%ya| yield *%ya } %method({{args.splat}}) { |*%ya| yield *%ya }
{% else %} {% else %}
{{original}} do |*%yield_args| {{original}} do |*%yield_args|