From 061028782bcc4d5d496c4b5568a7d81a97148b6f Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Wed, 1 Jan 2020 21:48:58 -0700 Subject: [PATCH] Workaround for what seems to be a Crystal macro bug The syntax: stub instance.==(other) { true } effectively becomes: stub instance.==(other { true }) --- src/spectator/mocks/double.cr | 17 ++++++++++++++++- src/spectator/mocks/stubs.cr | 8 +++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/spectator/mocks/double.cr b/src/spectator/mocks/double.cr index 45071ac..ef17e84 100644 --- a/src/spectator/mocks/double.cr +++ b/src/spectator/mocks/double.cr @@ -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 diff --git a/src/spectator/mocks/stubs.cr b/src/spectator/mocks/stubs.cr index 374cc78..00677f8 100644 --- a/src/spectator/mocks/stubs.cr +++ b/src/spectator/mocks/stubs.cr @@ -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