schema: hoist inline definitions into named $defs for codegen#726
Merged
Conversation
aba4829 to
3ac9de4
Compare
d4f2b7e to
b070c77
Compare
b070c77 to
3e652fc
Compare
…iness Promote every anonymous object/array-item schema and inline string enum into top-level $defs entries with unique names. Replace inline schemas with $ref pointers. Validator behavior is unchanged. LumpedPort and SurfaceCurrent items are split into named oneOf variants (LumpedPortAttributes / LumpedPortElements, SurfaceCurrentAttributes / SurfaceCurrentElements) so a downstream codegen sees two distinct shapes plus a tagged union, instead of one shape with everything optional.
Resolve internal $defs references during recursive schema key lookup so that nested-via-$ref schemas (e.g. BoundaryPostprocessing.FarField) are discoverable. Add a depth guard to prevent infinite recursion from pathological self-referential $defs cycles. Change error message enhancement from exact equality checks to substring matching so type mismatch and enum hints also fire for messages wrapped in oneOf/anyOf combination contexts. Update unit tests to use substring assertions instead of exact string comparisons to accommodate the richer validator output.
Rename DielectricType to InterfaceDielectric in boundaries.json for clarity, and merge duplicate AdaptiveGSOrthogonalization and GSOrthogonalization enums into a single Orthogonalization definition in solver.json.
…ath $def VoltagePath and CurrentPath share the same array-of-2D/3D-points shape; hoist into a single $defs/CoordinatePath and reference it from all WavePort, PostprocessingImpedance, and PostprocessingVoltage uses.
Separate the max-depth guard from the is_object check in FindAllSchemasByKey and emit an Mpi::Warning when the depth cap is hit. This surfaces potential self-referential $defs cycles in the schema as a developer-visible diagnostic instead of silently truncating the search.
Update SchemaCoverageGaps to resolve $ref pointers against $defs and handle oneOf/anyOf discriminated unions introduced by schema hoisting. Properties are collected as the union across arms while required fields are computed as the intersection, matching pre-hoist single-object semantics.
4c28172 to
f526f19
Compare
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
The current schema is correct for validation, but its pervasive use of inline definitions makes it hostile to code generation (Python, Julia, or any target that turns a JSON Schema into a set of named types in a single module):
Attributes,Direction,CoordinateSystem) collide as soon as the generated types share a namespace.…Itemstypes.SurfaceCurrent.itemswas an inline object, which generators render asSurfaceCurrentItems. The same was true forElements, producingSurfaceCurrentElementsItems— a name with no relationship to anything in the source of truth.oneOf-by-requireddiscriminators are anonymous.LumpedPortandSurfaceCurrentitems usedoneOf: [{required:[Attributes]}, {required:[Elements]}]over a single inline object. Generators can't see two distinct shapes, so they emit one type with every field optional and lose the discriminator.["Cartesian", "Cylindrical"]or["MGS", "CGS", "CGS2"]show up at multiple call sites; without a named definition, each call site produces a separate, name-clashing enum.What this PR does
Commit 1: schema refactor (
scripts/schema/config/*.json)Pure refactor — no semantic changes. The same documents that validated before still validate, and the same documents that failed still fail.
For each of
boundaries.json,domains.json,model.json,problem.json,solver.json:Hoist inline object schemas into
\$defswith unique, source-traceable names. Examples:boundaries:PEC,PMC,Absorbing,Conductivity,WavePort,WavePortPEC,Ground,ZeroCharge,Terminal,Periodic,BoundaryPostprocessingdomains:Material,DomainPostprocessing,DomainEnergy,Probe,CurrentDipolemodel:Box,SphereSplit anonymous
oneOfdiscriminators into named variants:LumpedPort.items→oneOf: [LumpedPortAttributes, LumpedPortElements]SurfaceCurrent.items→oneOf: [SurfaceCurrentAttributes, SurfaceCurrentElements]This gives codegen two distinct, well-named types plus a tagged union, instead of one type with everything optional.
Promote inline string enums to named
\$defs:CoordinateSystem,ProblemType,GSOrthogonalization,AdaptiveGSOrthogonalization,AdaptiveCircuitSynthesisDomainOrthogonalization,MaterialAxes,Direction,DipoleDirection.Name polymorphic value shapes that previously appeared as anonymous
oneOffragments:Samples→SamplesPoint|SamplesLinear|SamplesLogDirection→PortDirection|Vector3Excitationinteger →ExcitationIndexCommit 2: validator follow-ups (
palace/utils/jsonschema.cpp,test/unit/test-schema.cpp)Caught by running the schema unit tests locally; required to keep behavior consistent under the named-
\$refschema.FindAllSchemasByKeynow resolves internal#/\$defs/refs instead of skipping them. Previously the functioncontinued past any\$refinto\$defs, which meant schemas only reachable through a named ref (e.g.BoundaryPostprocessing.FarField) were no longer findable viaValidateConfig(data, "FarField"). Adds a depth guard against pathological cycles.SchemaErrorHandlerenhances type-mismatch and enum errors using substring matching. WithLumpedPort.itemsnow aoneOf, the validator wraps simple errors as[combination: oneOf / case#0] unexpected instance type. The exact-string check stopped matching, so the(got string)/ valid-enum hints disappeared. Switching tofind()makes the enhancement fire regardless ofoneOf/anyOfwrapping.test-schema.cpprelaxed to substring checks. The validator's behavior is unchanged, but the wording forIndexfailures shifted from a flat single-message form to aoneOf-enumerated form. Asserting on the underlying message keeps the test resilient to validator-output formatting.Why this is safe
\$refto a\$defsentry whose body is byte-equivalent (modulo whitespace) to the inlined version.additionalProperties: false,required, andoneOf/allOfconstraints are preserved at the same nesting level.LumpedPort/SurfaceCurrent, the two split variants carry the full property set; only therequireddiffers, so no document that was valid before is rejected now.FindAllSchemasByKeycontinues to return the same results for top-level property lookups; it now also finds keys reachable only through internal\$defsrefs (strictly more permissive).Test plan
cmake --build build/palace-build --target unit-tests && build/palace-build/test/unit/palace-unit-tests "[schema]"— 10 passed, 1 skipped (theEmbedded Schema Matches SourceSECTION skips by design when its source path isn't present), 0 failed, 155/155 assertions.LumpedPort/WavePort/SurfaceCurrent/CurrentDipole/Materials/FarField.LumpedPort/SurfaceCurrentoneOf: [Attributes, Elements]discrimination.PEC/GroundandPMC/ZeroChargemutual exclusion.Problem.Type → Solverrequirements (Driven/Eigenmode/Transientreject if matching solver section absent;Electrostatic/Magnetostaticaccept defaults).style.yml"Check JSON Schema" —scripts/validate-configruns over everyexamples/**/*.jsonagainst the refactored schema.test-schema.cpp).