You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: narrow enum advisory to fire only when zero cases carry #[EnumValue]
Partial annotation is the mechanism that will hide internal cases from
the public schema once the default flips to opt-in; leaving some cases
unannotated is deliberate and must not produce a warning. Under the
previous logic the advisory fired for every partial annotation, which
would punish exactly the pattern the migration encourages.
New rule: fire the E_USER_DEPRECATED advisory only when a #[Type]-mapped
enum declares zero #[EnumValue] attributes across all its cases — the
signal that the developer has not yet engaged with the opt-in model.
Annotating even a single case acknowledges the migration and silences
the notice; from that point any combination of annotated and unannotated
cases is correct and intentional.
Implementation: EnumTypeMapper::mapByClassName() now tracks a single
`sawAnyEnumValueAttribute` flag while iterating cases and emits the
notice only when the flag stays false. Message rewritten to explain the
"at least one case" requirement and point the reader at the intended
migration path — including the fact that a bare #[EnumValue] on a
single case is a valid acknowledgement.
Tests:
- Replaces the previous "any case missing" assertion with
testEnumWithZeroEnumValueAttributesTriggersDeprecation using a new
DescriptionLegacyEnum/Era fixture that declares no #[EnumValue] at
all.
- Adds testEnumWithPartialEnumValueAttributesIsSilent to lock in the
partial-annotation contract against regressions.
- Pre-existing Color/Size/Position fixtures gain a bare #[EnumValue] on
their first case so their integration tests stop triggering the
advisory — demonstrates the minimal upgrade path recommended in the
docs.
Full suite 539/539 green across cs-check, phpstan, and phpunit, with
exactly 1 intentional deprecation coming from the dedicated advisory
test. The docs in descriptions.md are updated to reflect the corrected
semantics — "partial annotation is intentional and silent".
'Enum "%s" is mapped to a GraphQL enum type but exposes one or more cases without a #[EnumValue] attribute. '
216
-
. 'Today every case is automatically exposed; a future major release will require #[EnumValue] on each case that should participate in the schema, mirroring #[Field]\'s opt-in model. '
217
-
. 'Add #[EnumValue] to each case you want to keep exposed. Cases currently exposed without an attribute: %s.',
213
+
'Enum "%s" is mapped to a GraphQL enum type but declares no #[EnumValue] attributes on any case. '
214
+
. 'Today every case is automatically exposed; a future major release will require at least one #[EnumValue]-annotated case per #[Type]-mapped enum, and only annotated cases will participate in the schema (mirroring #[Field]\'s opt-in model on classes). '
215
+
. 'Add #[EnumValue] to the case(s) you want to expose — annotating at least one case acknowledges the opt-in model and silences this notice. Cases left unannotated will be hidden from the schema after the future default flip, which is the intended way to keep internal values out of the public API.',
0 commit comments