Skip to content

kdiff 2.1.0

Latest

Choose a tag to compare

@github-actions github-actions released this 29 Sep 08:59

Added

  • PatchResult.prefixedWith(property), PatchResult.prefixedWith(segment) and
    PatchFailure.prefixedWith(segment)
    , which lift failures onto a prefix the way
    Change.prefixedWith lifts changes. A hand-written Patcher calls the first on each helper's result
    to report full paths, as the library's own patchers now do. It uses the second for an element of a
    collection it rebuilds itself. Both return the same instance when nothing failed, so a clean
    application allocates nothing for them.

Changed

  • The tutorial derives its comparison, and applies a diff. It used to describe its model with seven
    differ { } values, which is the route the rest of the documentation tells you not to start from.
    It now derives one with autoDiffer { } and three exceptions. Money, which deriving refuses, is
    where the refusal and its two exits are taught. A new section sends the handler's diff to a read
    model, including one that missed an update. No published API changes.
  • patching.md says what applying does to a source that has moved on. A change's before is
    never read, so values are overwritten and a removal of something already gone is a no-op. Only a
    change reaching beneath something absent is reported. This was always the behaviour, and now it is
    documented, with a runtime test per case.

Fixed

  • A patch failure names the full path of the change it declines, however deep. Applying
    addresses[id=A3].city to an instance holding no address A3 used to report
    city: no element with this key to patch. That names neither the list nor the element, and it is
    ambiguous in any model where city occurs twice. It now reports
    addresses[id=A3].city: no element with this key to patch, on the generated, derived and toPatcher
    routes alike. PatchFailure.change carries that full path too.

    Recompile to get it everywhere. The runtime restores element keys and indexes at once, but the
    property segment is restored by generated code, so a differ generated by an earlier processor reports
    [id=A3].city until it is regenerated. Nothing stops compiling either way.

    A hand-written Patcher changes in one of two ways. If it composes patch* helpers, call
    prefixedWith("<property>") on each helper's result, or its property segments stay missing. If it
    worked around the old paths by prefixing the failures of patchKeyedList, patchPositionalList or
    patchMap with the element's key or index itself, remove that prefixing, or the segment appears
    twice ([id=A3][id=A3].city). The helpers now return those failures already lifted onto the element.

    Restoring the property segment costs a clean apply one check per property. Nothing is allocated,
    but applying one change to an 18-property type measured 4–7% slower in kdiff-benchmarks.

Coordinates

implementation("io.github.rcapraro:kdiff-annotations:2.1.0")
implementation("io.github.rcapraro:kdiff-runtime:2.1.0")
ksp("io.github.rcapraro:kdiff-processor:2.1.0")

Deriving a differ from a type's shape is a separate artefact, declared only by a consumer
who uses it — it is the one part of kdiff that brings kotlin-reflect:

implementation("io.github.rcapraro:kdiff-reflect:2.1.0")