Resolve same-named schemas from different files as distinct components (fixes #2333)#2349
Open
seonwooj0810 wants to merge 1 commit into
Conversation
When resolving with resolveFully/resolve, an external $ref whose target shares a name with another, not-yet-resolved external $ref placeholder caused the placeholder to be silently overwritten. ExternalRefProcessor's finalNameRec treated any existing schema that still carried a $ref as a free slot, so two distinct files defining e.g. 'Pet' collapsed into one. Only reuse the existing name when the placeholder $ref targets the same reference being resolved; otherwise fall through to a suffixed name. Fixes swagger-api#2333
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.
Fixes #2333
Problem
When parsing a spec with
resolve: truewhere two schemas in different files share the same name, both references collapse into the first model. In the issue's reproducer,SomeItem(→inventory.yaml#/components/schemas/Pet, hasname) andPet(→pets.yaml#/components/schemas/Pet, hasid) both end up pointing at inventory'sPet.Root cause
ExternalRefProcessor.finalNameRecdecides which name a freshly resolved external schema gets. When the candidate name is already taken by an entry that still carries a$ref(an unresolved external placeholder, e.g. the siblingPetcomponent pointing atpets.yaml), the code unconditionally treated that slot as free and reused the name — thenaddSchemas(newRef, schema)overwrote the placeholder. The distinct second schema was lost.Fix
A
$refplaceholder slot is only safe to reuse when it targets the same reference currently being resolved. The incoming$refis now threaded intofinalNameRec; if the existing placeholder points to a different target, resolution falls through to the next suffixed name (Pet_1) instead of clobbering it. This is the conservative direction — a mismatch only ever produces an extra suffixed name, never data loss.Result on the reproducer
SomeItemcorrectly carriesnameandPetcorrectly carriesid.Test evidence
Issue2333Testwith the issue's three-file reproducer asserting the twoPetschemas resolve distinctly. Passes.swagger-parser-v3module suite: 609 tests, 0 failures, 0 errors (run with-Dmaven.javadoc.skip=true; the offline javadoc fetch and the unrelatedswagger-parser-safe-url-resolverPermittedUrlsCheckerTestfailures are pre-existing JDK 25 environment issues, not related to this change).Verification done
gh pr listsearch for the issue/keywords — none open); 2. no self-claim in the thread; 3. code-focused (.java); 4. reproduced the bug onmaster, confirmed the fix flips the behavior; 5. confirmed root symbolfinalNameRec/processRefToExternalSchemastill present onmaster; 6. n/a (no parent epic).