Repository navigation
test(compilers/openapi): hold the loop gates on branch reports - #1514
Open
fuad-daoud wants to merge 15 commits into
Open
fuad-daoud wants to merge 15 commits into
fuad-daoud wants to merge 15 commits into
Conversation
Removing the onLoop gate in fillRefBranch, or the one in diagUnresolvedBranches, added an unresolved-ref error beside the cyclic-ref that load already reports for the same loop, and no test noticed. One case per gate compiles the allOf and the union spec and holds the whole diagnostic list.
The struct the test compares now has exported fields, the form assert.Equal is allowed on, and the failure message no longer calls the loop the whole report, since the union case also expects a degraded-construct info.
…napi-loop-gate-reports
fuad-daoud
marked this pull request as ready for review
November 5, 2026 08:39
fuad-daoud
marked this pull request as draft
November 5, 2026 22:55
fuad-daoud
marked this pull request as ready for review
November 5, 2026 23:37
fuad-daoud
marked this pull request as draft
November 6, 2026 09:55
The union row of the reference-ends test had one branch, so a report at the wrong branch index stayed green. Give it two and hold both reports, and say in the doc comment that a $ref is unread only in the first copy of a key written twice.
The unplaced-branch rows reached diagUnresolvedBranches through oneOf only, so a report filed under the wrong keyword stayed green: it keyed its pointer on the union's keyword and no row used anyOf. Add an anyOf row. The union row's two branches named one $ref, so a report quoting the wrong branch's target read the same. Give the second branch its own target, and compare each branch's message against its own.
The rows compared the pointer and message of each unresolved-ref report but not its severity, so a report downgraded to a warning stayed green at both the allOf and the union report. Assert that each is an error.
The loop table held the union's gate on oneOf alone, so a gate applied to oneOf only drew no failure while an anyOf loop was reported twice. A walk that stopped at the first skipped branch was unheld too, as its only fixture put the unresolved branch first.
The loop table reached a union only beside structural keywords, so a gate in refTypeRef scoped to union positions added an unresolved-ref on a plain oneOf or anyOf loop and no test noticed. Two rows with no keyword beside the union reach it. The union rows also did not hold that a loop-only union reaches diagUnresolvedBranches as case 3 of union-beside-structure: the degraded-construct info has the same code, severity and pointer in all five cases. A classifier returning another case left them green with a false reason and the second gate unheld. The rows now assert the reason the info gives.
fuad-daoud
marked this pull request as ready for review
November 6, 2026 19:26
This was referenced Nov 7, 2026
Open
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.
Summary
In short: A
$refloop under anallOfor union branch is reported once, ascyclic-ref, and two checks stop the same branch being reported again asunresolved-ref; removing either left the suite green. This adds a test with a case for each check.An
allOfbranch or a union branch on a loop of$refs is reported once, as theopenapi/cyclic-refthe load step raises. For anallOfbranch and a union branch beside structural keywords, two gates keep the lowering from reporting the same branch again asopenapi/unresolved-ref:onLoopinfillRefBranchand indiagUnresolvedBranches. Removing either left the compiler's suite green.This adds one table-driven test through the compiler's public face, with one case per gate, one more for
anyOfat the union's gate, and two for a union with no keyword beside it, whichrefTypeReflowers, holding the whole diagnostic list rather than the absence of one code. It sits beside the other loop tests ine2erather than ininternal/schema, as #1086 proposed, because the list joins what load reports with what the lowering does. A second test, ininternal/schema, holds the report the first gate lets through on a$refload also reports, which a full compile then drops for load's own. A third test, ine2e, holds both reports where load makes none, on a$refthe binder cannot place, which a full compile keeps.union-beside-structurenow says a case-3 branch on a loop of$refs is reported by the loop's oneopenapi/cyclic-refrather thanopenapi/unresolved-ref. The third site,refTypeRef, is held byTestCompile_ReportsAReferenceCycleAnOverlayIntroduceson a component, and by those two cases at a union's branches.Closes #1086
Before and after
flowchart TB subgraph before ["Before"] b0["The onLoop gate in fillRefBranch or diagUnresolvedBranches is removed"] b1["An unresolved-ref error appears beside the cyclic-ref for one loop"] b2["No test notices"] b0 --> b1 b1 --> b2 end subgraph after ["After"] a0["The onLoop gate in fillRefBranch or diagUnresolvedBranches is removed"] a1["An unresolved-ref error appears beside the cyclic-ref for one loop"] a2["The exact-list case for that gate goes red"] a0 --> a1 a1 --> a2 end before ~~~ afterWhat it brings: A spec author with an
allOfor union branch on a$refloop gets nounresolved-reffor that branch beside the loop'scyclic-ref, and removing a gate that keeps it away now fails a test.Test plan
mainat2a0996a6merged in, runsmake gate. Onf6c1cf19,go build ./...,go testoncompilers/openapi,internal/schema,compilers/openapi/e2eandinternal/archtest,make vet,make lintandmake lint-plantedeach pass.internal/schemacase and theallOfcase ofTestReferenceEnds_ABranchTheBinderCannotPlaceIsReportedAtItfail with the first gate's report block deleted, with the rest of the suites green, and both pass with the gate forcedif true.if _, read := c.Bindings().Entry(b); read && !onLoop(c, b) {and the second asif _, read := c.Bindings().Entry(b); !read || c.RefScope().NamesReferent(b) || onLoop(c, b) {, reddens only that gate's rows of that test:allOffor the first,union beside structural keywordsandanyOf beside structural keywordsfor the second."oneOf"forkeyatunion.go:537, with_forkeyatunion.go:530, reddens theanyOf beside structural keywordsrow alone, and plantingbranches[0].GetRef()forb.GetRef()atunion.go:538reddens theunion beside structural keywordsrow and both rows ofTestOneOf_CoDeclaredBranchAfterASkippedOneIsReported.ir.SeverityWarningforir.SeverityErroratunion.go:536reddens theunion beside structural keywordsandanyOf beside structural keywordsrows,TestOneOf_CoDeclaredUnresolvableBranchIsNotDistributedandTestOneOf_CoDeclaredBranchAfterASkippedOneIsReported, and atallof.go:317theallOfrow and the newinternal/schemacase.strconv.Itoa(0*i)forstrconv.Itoa(i)atunion.go:537reddens theunion beside structural keywordsrow of that test, which holds the reports atoneOf/0andoneOf/1, and both rows ofTestOneOf_CoDeclaredBranchAfterASkippedOneIsReported.if !onLoop(c, b)withif trueinfillRefBranchreddens theallOf branchescase alone, dropping|| onLoop(c, b)indiagUnresolvedBranchesreddens theunion branches beside structural keywordsandanyOf branches beside structural keywordscases alone, and planting(key == "oneOf" && onLoop(c, b))foronLoop(c, b)atunion.go:533reddens theanyOfcase alone.breakforcontinueatunion.go:534reddens both rows ofTestOneOf_CoDeclaredBranchAfterASkippedOneIsReported.onLoop(c, js) && !strings.Contains(string(pointer), "/oneOf/")foronLoop(c, js)inrefTypeRef, withstringsimported, reddens theunion branches with no keyword beside themcase alone,"/anyOf/"there theanyOf branches with no keyword beside themcase alone, and removing that gate reddens both andTestCompile_ReportsAReferenceCycleAnOverlayIntroduces.unionInlineBranchfromclassifyUnionSiblingswhere every branch lies on a loop reddens the twobeside structural keywordscases alone, asdiagUnresolvedBranchesis called for case 3 only.allOf branchescase, the newinternal/schemacase and thatallOfcase, and no other test ininternal/schemaore2e, and dropping thedegraded-constructrow from the expected union list reddens the union case, so the list is held exactly.