Workaround for what seems to be a Crystal macro bug

The syntax:
stub instance.==(other) { true }
effectively becomes:
stub instance.==(other { true })
This commit is contained in:
Michael Miller 2020-01-01 21:48:58 -07:00
parent a9ac48e12c
commit 061028782b
2 changed files with 23 additions and 2 deletions

View file

@ -17,13 +17,28 @@ module Spectator::Mocks
named = false
name = definition.name.id
params = definition.args
# Possibly a weird compiler bug, but syntax like this:
# stub instance.==(other) { true }
# Results in `other` being the call `other { true }`.
# This works around the issue by pulling out the block
# and setting the parameter to just the name.
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 = definition.block.is_a?(Nop) ? block : definition.block
# The unless is here because `||=` can't be used in macros @_@
unless body
body = definition.block.is_a?(Nop) ? block : definition.block
end
elsif definition.is_a?(TypeDeclaration) # stub foo : Symbol
name = definition.var
params = [] of MacroId

View file

@ -12,13 +12,19 @@ module Spectator::Mocks
named = false
name = definition.name.id
params = definition.args
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 = definition.block.is_a?(Nop) ? block : definition.block
unless body
body = definition.block.is_a?(Nop) ? block : definition.block
end
elsif definition.is_a?(TypeDeclaration) # stub foo : Symbol
name = definition.var
params = [] of MacroId