Skip to content

Fix #935 + implement #770: context-function-scoped path selectors - #948

Merged
MateuszKubuszok merged 3 commits into
masterfrom
fix-935-and-770-context-function-selectors
Sep 1, 2026
Merged

MateuszKubuszok merged 3 commits into
masterfrom
fix-935-and-770-context-function-selectors

Conversation

@MateuszKubuszok

Copy link
Copy Markdown
Member

Summary

Fix #935: withEnumCaseHandled with Option target

Root cause: TransformToOptionRule wraps From into Option[From] and delegates to OptionToOption, which recurses into From → InnerTo. During recursion, source-side subtype overrides are dropped because:

  1. Their paths don't start with matching[Some[From]].value (the recursion prefix)
  2. Their return type (Option[To]) doesn't match the inner target (InnerTo)

Fix: When source-side subtype overrides exist and From is a sealed hierarchy, TransformToOptionRule now generates the pattern match directly at the From → Option[To] level — consuming overrides there (where the return type matches) and deriving non-overridden subtypes by name-matching against InnerTo's subtypes.

Implement #770: context-function-scoped path extensions

Path extension methods were available on every value once dsl.* or syntax.* was imported. Now they require using ChimneySelector, which is only provided inside DSL selector lambdas via context functions (ChimneySelector ?=> From => T).

Changes:

  • New ChimneySelector sealed trait phantom type in internal.runtime
  • using ChimneySelector constraint on path extension blocks in syntax.scala
  • Selector params in all Scala 3 DSL classes changed to context functions
  • DslDefinitions parser updated to unwrap Block/nested-lambda wrapping from context function resolution
  • Macro adapter selector params widened to Expr[Any]

Not a breaking change: selector functions are inline macro parameters, so the context function wrapper is invisible to existing user code.

Test plan

  • New test cases for Converting enum with null value to Option #935 (total and partial transformer with withEnumCaseHandled to Option target)
  • All 1153 core tests pass
  • All 312 cats integration tests pass
  • All modules compile (chimney, chimney-cats, chimney-java-collections, chimney-protobufs)

When deriving Foo → Option[Bar], TransformToOptionRule wraps Foo into
Option[Foo] and delegates to OptionToOption, which recurses into
Foo → Bar. Source-side subtype overrides (from withEnumCaseHandled)
are dropped during that recursion because their paths don't match
the Option wrapper path, and their return type (Option[Bar]) doesn't
match the inner target (Bar).

Fix: when source-side subtype overrides exist and From is a sealed
hierarchy, generate the pattern match directly at the From → Option[To]
level — consuming overrides there and deriving non-overridden subtypes
by name-matching against the inner target's subtypes.
Path extension methods (matching, everyItem, everyMapKey, everyMapValue,
matchingSome, matchingLeft, matchingRight) were available on every value
once dsl.* or syntax.* was imported. Now they require a ChimneySelector
given, which is only provided inside DSL selector lambdas via context
functions (ChimneySelector ?=> From => T).

- Add sealed trait ChimneySelector phantom type in internal.runtime
- Add `using ChimneySelector` to path extension blocks in syntax.scala
- Change selector params in all Scala 3 DSL classes to context functions
- Update DslDefinitions parser to unwrap Block/nested-lambda wrapping
- Widen macro adapter selector params to Expr[Any]

Not a breaking change: selector functions are inline macro parameters,
so the context function wrapper is invisible to existing user code.
Remove dead `OptionFromType` implicit val from `wrapInOptionAndTransform`
(moved to `wrapAndDelegateToOptionToOption` during #935 refactor) — Scala
2.13 -Werror rejects unused locals. Fix Scaladoc line wrap in
ChimneySelector.scala for scalafmt.
@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 56.88073% with 47 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.91%. Comparing base (b128e63) to head (68574fa).

Files with missing lines Patch % Lines
...ransformer/rules/TransformToOptionRuleModule.scala 61.90% 32 Missing ⚠️
...mney/internal/compiletime/dsl/DslDefinitions.scala 76.92% 3 Missing ⚠️
...a-3/io/scalaland/chimney/dsl/CodecDefinition.scala 0.00% 1 Missing ⚠️
...ala-3/io/scalaland/chimney/dsl/IsoDefinition.scala 0.00% 1 Missing ⚠️
...and/chimney/dsl/PartialTransformerDefinition.scala 0.00% 1 Missing ⚠️
...imney/dsl/PartialTransformerDefinitionForAll.scala 0.00% 1 Missing ⚠️
...scalaland/chimney/dsl/PartialTransformerInto.scala 0.00% 1 Missing ⚠️
...and/chimney/dsl/PartialTransformerIntoForAll.scala 0.00% 1 Missing ⚠️
...3/io/scalaland/chimney/dsl/PatcherDefinition.scala 0.00% 1 Missing ⚠️
...cala-3/io/scalaland/chimney/dsl/PatcherUsing.scala 0.00% 1 Missing ⚠️
... and 4 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #948      +/-   ##
==========================================
- Coverage   83.46%   82.91%   -0.56%     
==========================================
  Files         176      180       +4     
  Lines        7011     7127     +116     
  Branches      509      525      +16     
==========================================
+ Hits         5852     5909      +57     
- Misses       1159     1218      +59     

☔ 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.

@MateuszKubuszok
MateuszKubuszok merged commit cc34634 into master Sep 1, 2026
15 of 17 checks passed
@MateuszKubuszok
MateuszKubuszok deleted the fix-935-and-770-context-function-selectors branch September 1, 2026 21:32
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.

Converting enum with null value to Option

1 participant