Skip to content

feat!: make #[EnumValue] control per-case enum schema exposure - #826

Merged
oojacoboo merged 1 commit into
thecodingmachine:masterfrom
oojacoboo:feat/enumvalue-schema-exposure-upstream
Aug 19, 2026
Merged

oojacoboo merged 1 commit into
thecodingmachine:masterfrom
oojacoboo:feat/enumvalue-schema-exposure-upstream

Conversation

@oojacoboo

Copy link
Copy Markdown
Collaborator

Builds on #793 (which added #[EnumValue] for per-case metadata). This makes #[EnumValue] the schema-exposure toggle for #[Type]-mapped enums, mirroring #[Field]'s opt-in model on classes.

Behavior

Once any case of a mapped enum carries #[EnumValue], the enum enters opt-in mode: only annotated cases are exposed, and unannotated cases are hidden from the schema. A fully-unannotated mapped enum stays in legacy mode (every case exposed) and keeps emitting the existing deprecation advisory.

Implementation

  • Adds Types\ExposedEnumCase and reshapes EnumType's internal constructor to take the resolved exposed cases the mapper decided, replacing the parallel per-name metadata arrays.
  • EnumTypeMapper buckets cases in a single pass, preserving deprecation precedence (explicit #[EnumValue(deprecationReason:)] wins, an empty string clears, otherwise the @deprecated docblock is honored).

Breaking change

Partially-annotated #[Type] enums now hide their unannotated cases from the schema. Annotate every case you want exposed.

Docs updated (attributes-reference, descriptions); tests added (EnumExposureTest + fixtures, covering opt-in, legacy, and mixed enums).

@codecov-commenter

codecov-commenter commented Aug 19, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.15385% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.72%. Comparing base (53f9d49) to head (42b0fd0).
⚠️ Report is 167 commits behind head on master.

Files with missing lines Patch % Lines
src/Mappers/Root/EnumTypeMapper.php 95.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #826      +/-   ##
============================================
- Coverage     95.72%   91.72%   -4.00%     
- Complexity     1773     2027     +254     
============================================
  Files           154      199      +45     
  Lines          4586     5439     +853     
============================================
+ Hits           4390     4989     +599     
- Misses          196      450     +254     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Once any case of a #[Type]-mapped enum carries #[EnumValue], the enum enters
opt-in mode: only annotated cases are exposed and unannotated cases are hidden
from the schema. A fully-unannotated mapped enum stays in legacy mode (every
case exposed) and emits the existing deprecation advisory.

Adds Types\ExposedEnumCase and reshapes EnumType's internal constructor to take
the resolved exposed cases the mapper decided, replacing the parallel per-name
metadata arrays.

BREAKING CHANGE: partially-annotated #[Type] enums now hide their unannotated
cases from the schema. Annotate every case you want exposed.
@oojacoboo
oojacoboo force-pushed the feat/enumvalue-schema-exposure-upstream branch from 0cd846f to 42b0fd0 Compare August 19, 2026 16:47
@oojacoboo
oojacoboo merged commit 0e2daf7 into thecodingmachine:master Aug 19, 2026
12 checks passed
@oojacoboo
oojacoboo deleted the feat/enumvalue-schema-exposure-upstream branch August 19, 2026 18:39
@enricobono

Copy link
Copy Markdown

Hello @oojacoboo,
Thank you for your work on keeping the library moving forward and improving it together with the community!

Regarding the new #[EnumValue] attribute, I've been trying it out in our codebase and noticed that it can become quite verbose in practice. We have quite a few enums with 10+ cases, and some with several dozen cases, so adding #[EnumValue] to every case can add quite a bit of boilerplate.

I was wondering if you had considered having a class-level attribute that could expose all the enum cases, rather than requiring the attribute on each individual case?

If not, perhaps this could be something worth considering. I think it could help keep the code a bit cleaner and more readable, especially for enums with many cases.

Just sharing some feedback from trying it out in a real-world codebase.
Thanks again for all the work on this!

@oojacoboo

Copy link
Copy Markdown
Collaborator Author

@enricobono thanks for the feedback. If you don't annotate any of the cases, all of them should be included. Maybe this is a bit confusing an an argument on the type annotation would be more ideal. Is that what you're thinking here? Or have you tried not annotating any of them for full inclusion?

@enricobono

Copy link
Copy Markdown

Thanks! I tried it, and it works exactly as described.

If you don't annotate any of the cases, all of them should be included.

My concern was more about the future behavior. As I understand it, starting with a future release, once the schema is generated, only enum cases explicitly annotated with #[EnumValue] will be included.

So in that context, I was wondering whether a type-level annotation could be a more explicit and less verbose way to opt in all cases.

@oojacoboo

oojacoboo commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator Author

@enricobono great.

So in that context, I was wondering whether a type-level annotation could be a more explicit and less verbose way to opt in all cases.

Yea, I think this would be a reasonable addition. I am questioning just leaving it like it is now though, instead of forcing the #[EnumValue] attribute (or a type arg, as you suggest). My only concern is that it's not as explicit, as you state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants