Skip to content

Fix B5: class name compounding and cache key for JsonPointer#152

Open
torian257x wants to merge 3 commits into
wol-soft:masterfrom
torian257x:fix/b5-class-name-compounding
Open

Fix B5: class name compounding and cache key for JsonPointer#152
torian257x wants to merge 3 commits into
wol-soft:masterfrom
torian257x:fix/b5-class-name-compounding

Conversation

@torian257x

@torian257x torian257x commented Jun 15, 2026

Copy link
Copy Markdown

Summary

Two fixes in SchemaProcessor::generateModel():

  1. Class name compounding: Use 'base' as fixed BaseProperty name instead of the full class name. Prevents exponential filename growth at each composition nesting level.
  2. Cache key: Include $jsonSchema->getPointer() so inline schemas at different positions get distinct Schema objects with correct class-level #[JsonPointer].

What the maintainer asked

"Is B5's solution collision safe?"

Response: Yes. Each Schema creates its own BaseProperty object (keyed by content+pointer in cache). The BaseProperty is never rendered as a class property. No regular property named 'base' could conflict — Schema::addProperty() (your commit 4c1b06e) catches collisions early.

"The rename from $schemaSignature to $cacheKey causes just DIFF noise, additionally: your mentioned changes to the cache key aren't reflected by the code changes"

Response: The rename was reverted. The cache key now actually includes the pointer: $jsonSchema->getSignature() . '|' . $jsonSchema->getPointer(). For $ref targets the pointer is always the definition location, so sharing is preserved.

Why this is correct

  • Identical inline schemas at different positions now get separate Schema objects
  • $ref targets still share (same pointer = definition location)
  • 20-level deep nesting test validates no path overflow

Test

B5ClassNameCompoundingTest.php

Use 'base' as fixed BaseProperty name to prevent exponential filename growth
at each composition nesting level. Include JsonSchema pointer in cache key
so inline schemas at different positions get distinct Schema objects.

Changes:
- SchemaProcessor::generateModel() uses fixed 'base' property name
- Cache key: content_signature|pointer so position distinguishes inline schemas
- $ref targets still share because their pointer is always the definition location

Tests:
- 20-level nested allOf validates no path overflow
- Identical inline content at different positions gets correct #[JsonPointer]
- $ref targets confirmed to still share schema
Use 'base' as fixed BaseProperty name. Include pointer in cache key so
inline schemas at different positions get correct class-level #[JsonPointer].
@torian257x

Copy link
Copy Markdown
Author

This PR addresses the B5 feedback from PR #150. I am an AI assistant working on behalf of @torian257x.

"Is B5's solution collision safe?"

Yes. Each Schema creates its own BaseProperty object (keyed by content+pointer in cache). The BaseProperty is never rendered as a class property. No collision possible.

"The rename from $schemaSignature to $cacheKey causes just DIFF noise, additionally: your mentioned changes to the cache key aren't reflected by the code changes"

Fixed: The variable rename was reverted. The cache key now actually includes the pointer: $jsonSchema->getSignature() . '|' . $jsonSchema->getPointer(). For $ref targets the pointer is always the definition location, so sharing is preserved. For inline schemas at different positions, each gets a separate Schema object with the correct class-level #[JsonPointer].

@torian257x

Copy link
Copy Markdown
Author

Updated with tests that actually fail on master and pass on this branch.

Bug discovered: the processedSchema cache key in SchemaProcessor.php was just $jsonSchema->getSignature() - the content hash - without the JsonSchema pointer. Two identical inline objects at different positions (e.g. /properties/a and /properties/b) produced the same cache key, reusing a single Schema object with the wrong class-level #[JsonPointer].

Proving test: B5ClassNameCompoundingTest::testIdenticalInlineObjectsAtDifferentPositionsGetDistinctPointers

  • On upstream/master: the two objects produce the same class (content-only cache key dedup) - the second object inherits the first object's pointer
  • On this branch: they produce distinct classes with correct pointers

The $ref test (testRefTargetsStillShareSchema) verifies that $ref targets still share a class - the pointer is always the definition location, so the cache key with pointer still matches.

@wol-soft

Copy link
Copy Markdown
Owner

Something got mixed up here, with the changes from #154

@torian257x

Copy link
Copy Markdown
Author

@wol-soft yes so it seemed like 2 issues were related and i prompted the llm to keep them together, not separate them. Then i saw he still updated multiple prs but didnt have time to figure out whats up. Let me check if i can find the session

@wol-soft

wol-soft commented Jul 1, 2026

Copy link
Copy Markdown
Owner

ok, if it turns out they belong together, can you also update the MR description?

testIdenticalInlineObjectsAtDifferentPositionsGetDistinctPointers exercises
two identical inline objects at /properties/a and /properties/b. On
upstream/master both share one Schema (cache key uses content signature
only); on this branch each gets its own Schema with correct
#[JsonPointer('/properties/a')] vs #[JsonPointer('/properties/b')].

testRefTargetsStillShareSchema confirms $ref targets remain shared (the
pointer is always the definition location, so cache key still matches).

IdenticalNestedSchemaTest assertions updated for the cache-key behaviour
change: inline identical schemas at different positions now get distinct
classes; $ref'd schemas and same-pointer cases continue to share a class.
@torian257x torian257x force-pushed the fix/b5-class-name-compounding branch from a73c148 to 8fef0cc Compare July 1, 2026 10:40
@torian257x

torian257x commented Jul 1, 2026

Copy link
Copy Markdown
Author

I updated the PR @wol-soft but I have to look it through again when I get time. I think it should be separated better now

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.

2 participants