Add CompositeMapperCompilerProvider for typed provider graph traversal - #126
Draft
janedbal wants to merge 1 commit into
Draft
Add CompositeMapperCompilerProvider for typed provider graph traversal#126janedbal wants to merge 1 commit into
janedbal wants to merge 1 commit into
Conversation
Consumers sometimes need to walk a provider graph to discover all transitively referenced classes, e.g. to pre-generate mappers for every MapDelegate reachable from an Input class. Until now that required reflecting over provider internals (get_mangled_object_vars over plain `object`), which static analysis cannot attribute to any class — shipmonk/dead-code-detector reports it as an unknown read over unknown type and degrades dead code analysis of the consumer project. Every provider composed of other providers now exposes them via CompositeMapperCompilerProvider::getInnerMapperCompilerProviders(), and MapperCompilerProviderUtils::iterate() walks the graph using only that interface. The completeness of the implementations is enforced mechanically: a test compares the typed traversal against a reflective walk over a graph exercising every attribute provider, and a companion test forces every (current and future) attribute provider class into that graph. Co-Authored-By: Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Consumers that pre-generate mappers (e.g. a Symfony command compiling input + output mappers for every
*Inputclass and everything reachable from it) need to walk a provider graph to discover all transitively referenced classes — every reachableMapDelegate. Until now that required reflecting over provider internals (get_mangled_object_vars()over a plainobject), which static analysis cannot attribute to any class:shipmonk/dead-code-detectorreports it as an unknown read over unknown type and it degrades dead-code analysis of the whole consumer project.What this adds
CompositeMapperCompilerProvider— implemented by providers composed of other providers, exposing them viagetInnerMapperCompilerProviders(): list<InputMapperCompilerProvider|OutputMapperCompilerProvider>. Implemented on all 12 composite attributes; notablyMapArrayShapeexposes the mappers wrapped inArrayShapeItemMappingandMapObjectexposes both constructor-arg and property providers.MapperCompilerProviderUtils::iterate()— yields a provider and all transitively nested providers, using only the interface. Consumers can then e.g. filter forMapDelegatewithout any reflection.Completeness is enforced mechanically
Two tests keep implementations honest:
testTypedTraversalMatchesReflectiveTraversalcompares the typed traversal against a reflective property walk over a graph exercising every attribute provider — forgetting a nested provider in any implementation fails the test naming the missed provider.testProviderGraphContainsAllAttributeProvidersglobssrc/Compiler/Attributeand forces every current and future provider attribute into that test graph — a new composite attribute cannot ship without exposing its inner providers.Direction / follow-up
This is intended as a building block: input-mapper should ideally support mapper pre-generation natively. A follow-up could add e.g. a
MapperPregeneratorthat takes root classes, expandsMapDelegatedependencies via this traversal, and compiles input + output mappers for all of them — so consumer applications just call it from their console command instead of owning the discovery logic.Backward compatible: purely additive, custom providers opt in by implementing the interface.
Co-Authored-By: Claude Code
Drafted by Claude