Support response constraints

Reduce union expansion by casting at key points.
This commit is contained in:
Michael Miller 2022-03-05 12:21:31 -07:00
parent 8668e495ef
commit ec57105afd
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2

View file

@ -17,9 +17,17 @@ module Spectator
end end
def initialize(@name : String? = nil, **methods : **NT) def initialize(@name : String? = nil, **methods : **NT)
@responses = methods.map do |method, value| @responses = {% if NT.keys.empty? %}
Response.new(method, value).as(AbstractResponse) [] of AbstractResponse
end {% else %}
{% begin %}
[
{% for key in NT.keys %}
Response.new({{key.symbolize}}, methods[{{key.symbolize}}]).as(AbstractResponse),
{% end %}
]
{% end %}
{% end %}
end end
# Utility returning the double's name as a string. # Utility returning the double's name as a string.
@ -53,7 +61,18 @@ module Spectator
\{% if type <= {{meth.return_type}} %} \{% if type <= {{meth.return_type}} %}
# Return type appears to match configured type. # Return type appears to match configured type.
# Respond with configured value. # Respond with configured value.
@messages[{{meth.name.symbolize}}].as({{meth.return_type}})
# Find a suitable response.
call = MethodCall.capture({{meth.name.symbolize}}, {{meth.args.map(&.name).splat}})
response = @responses.find &.===(call)
if response
# Return configured response.
response.as(Response(\{{NT[{{meth.name.symbolize}}]}})).value
else
# Response not configured for this method/message.
raise UnexpectedMessage.new("#{_spectator_double_name} received unexpected message :{{meth.name}} with (<TODO: ARGS>).")
end
\{% else %} \{% else %}
# Return type doesn't match configured type. # Return type doesn't match configured type.
# Can't return the configured response as the type mismatches (won't compile). # Can't return the configured response as the type mismatches (won't compile).
@ -62,7 +81,18 @@ module Spectator
\{% end %} \{% end %}
{% else %} {% else %}
# No return type restriction, return configured response. # No return type restriction, return configured response.
@messages[{{meth.name.symbolize}}]
# Find a suitable response.
call = MethodCall.capture({{meth.name.symbolize}}, {{meth.args.map(&.name).splat}})
response = @responses.find &.===(call)
if response
# Return configured response.
response.as(Response(\{{NT[{{meth.name.symbolize}}]}})).value
else
# Response not configured for this method/message.
raise UnexpectedMessage.new("#{_spectator_double_name} received unexpected message :{{meth.name}} with (<TODO: ARGS>).")
end
{% end %} {% end %}
\{% else %} \{% else %}
# Response not configured for this method/message. # Response not configured for this method/message.
@ -85,8 +115,14 @@ module Spectator
# Find a suitable response. # Find a suitable response.
call = MethodCall.capture({{call.name.symbolize}}, {{call.args.splat}}) call = MethodCall.capture({{call.name.symbolize}}, {{call.args.splat}})
response = @responses.find &.===(call) response = @responses.find &.===(call)
# Return configured response.
@messages[{{call.name.symbolize}}] if response
# Return configured response.
response.as(Response(\{{NT[{{call.name.symbolize}}]}})).value
else
# Response not configured for this method/message.
raise UnexpectedMessage.new("#{_spectator_double_name} received unexpected message :{{call.name}} with (<TODO: ARGS>).")
end
\{% else %} \{% else %}
# Response not configured for this method/message. # Response not configured for this method/message.
raise UnexpectedMessage.new("#{_spectator_double_name} received unexpected message :{{call.name}} with (<TODO: ARGS>).") raise UnexpectedMessage.new("#{_spectator_double_name} received unexpected message :{{call.name}} with (<TODO: ARGS>).")