From e126cb744b6a38bc39f1dbee839bfc129e113bc3 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Wed, 4 Mar 2020 23:16:29 -0700 Subject: [PATCH] Ensure that a TypeNode is resolved When describing a constant, the `resolve?` method can return a non-TypeNode, which is the constant's value. The Crystal docs seem to indicate this should only return `TypeNode` or `NilLiteral`. But, I can see when this would be useful to resolve a constant in a macro. To work around this, `described_class` and `subject` should only be defined when it resolves to a `TypeNode`. Fixes arctic-fox/spectator#40 Fixes arctic-fox/spectator#41 --- src/spectator/dsl/groups.cr | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/spectator/dsl/groups.cr b/src/spectator/dsl/groups.cr index 5d112ac..429cf85 100644 --- a/src/spectator/dsl/groups.cr +++ b/src/spectator/dsl/groups.cr @@ -19,7 +19,9 @@ module Spectator %source = ::Spectator::Source.new({{_source_file}}, {{_source_line}}) ::Spectator::SpecBuilder.start_group({{description}}, %source) - {% if (what.is_a?(Path) || what.is_a?(Generic)) && (described_type = what.resolve?) %} + # Oddly, `#resolve?` can return a constant's value, which isn't a TypeNode. + # Ensure `described_class` and `subject` are only set for real types (is a `TypeNode`). + {% if (what.is_a?(Path) || what.is_a?(Generic)) && (described_type = what.resolve?).is_a?(TypeNode) %} macro described_class {{described_type.name}} end