Say what a vector is a vector of - #156
Merged
Merged
Conversation
A velocity is three metres per second and a position is three metres, and a schema that said only "three floats" left the one fact worth knowing about either of them to a comment. That is the argument Semantic already makes for a single value; this applies it to three of them. Vector gains an ElementType, inherited by Vector2, Vector3, Vector4 and - since they derive from the vectors - ColorRGB and ColorRGBA. It defaults to Float, so a vector that says nothing about its components is what a vector has always been, and it is omitted from the file when it is: a file whose vectors are vectors of floats is written exactly as it was before the property existed. A non-nullable property has no ignore condition meaning "the same as saying nothing", so the omission is a contract modifier on the serializer's options. Validation refuses a component that is not a number, or a semantic type represented as one: a vector of objects is a collection of things rather than one value with components, which is what Array is for. A colour is held to Float, because its components are the channels every consumer of one reads as floats. Two things fall out of the change: - ValidateType had no arm for Semantic, so a member naming a semantic type the schema does not declare was silently accepted. It is reported now, the same way a dangling class or interface reference is; the vector rule needs it to mean anything. - The C# generator maps a vector to System.Numerics only when its components are floats, because those types hold nothing else. A vector of anything else falls through to the same object? every type that generator cannot yet say does, rather than being emitted as a type it is not. formatVersion moves to 4 for the reason version 2 did: a version 3 reader would load a Vec3 of a semantic type, drop what it is three of, and write it back as three bare floats. The editor's type picker does not offer a component yet, for the same reason it does not offer a Semantic, a Span or a Handle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AhoPJ5AbxP8QEBNxPQYEPk
The contract modifier walks every property to find the one it cares about, which reads as a loop over all of them. Saying Where once says what is being looked for where a reader looks for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AhoPJ5AbxP8QEBNxPQYEPk
|
matt-edmondson
pushed a commit
that referenced
this pull request
Sep 10, 2026
MSTEST0037: comparing a count to zero says less than asserting emptiness, and Assert.AreEqual(0, ...) reports "expected 0, was 2" where Assert.IsEmpty names what it found. The message follows the convention the rest of the suite already uses for a validation assertion - joining the issues, so a failure says which rule fired rather than only that one did. Reported by SonarCloud on #156, which had already merged. The same shape appears throughout the suite and predates that change; only the new line is touched here, since a sweep would be a large diff for no behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AhoPJ5AbxP8QEBNxPQYEPk
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.



A velocity is three metres per second and a position is three metres, and a schema that said only "three floats" left the one fact worth knowing about either of them to a comment. That is the argument
Semanticalready makes for a single value; this applies it to three of them.{ "TypeName": "Vector3", "elementType": { "TypeName": "Semantic", "semanticTypeName": "MetresPerSecond" } }What changed
Vectorgains anElementType, inherited byVector2,Vector3,Vector4and — since they derive from the vectors —ColorRGBandColorRGBA.It defaults to
Float, so a vector that says nothing about its components is what a vector has always been, and it is omitted from the file when it is: a file whose vectors are vectors of floats is written exactly as it was before the property existed. A non-nullable property has no ignore condition meaning "the same as saying nothing", so the omission is a contract modifier on the serializer's options rather than an attribute.Validation refuses a component that is not a number, or a semantic type represented as one — a vector of objects is a collection of things rather than one value with components, which is what
Arrayis for. A colour is held toFloat, because its components are the channels every consumer of one reads as floats.Two things that fall out of it
ValidateTypehad no arm forSemantic. A member naming a semantic type the schema does not declare was silently accepted. It is reported now, the same way a dangling class or interface reference is — the vector rule needs it to mean anything, and without it a typo'd component name would pass.System.Numericsonly when its components are floats, because those types hold nothing else. A vector of anything else falls through to the sameobject?every type that generator cannot yet say does, rather than being emitted as a type it is not.Format version
formatVersionmoves to 4 for the reason version 2 did: the change is additive and a file that uses none of it is byte-identical to the version 3 file it would have been, but a version 3 reader would load aVec3of a semantic type, drop what it is three of, and write it back as three bare floats.Also here: the generator table is no longer fixed
SchemaGenerator's table of generators was a private dictionary built once, which assumes every generator can live in this project. Not every one can: this library publishesnet8.0, and the C++ generator being written next is built on an AST that ships nonet8.0assembly, so it has to live somewhere with a higher framework floor.Registerlets one do that and still be found by the language a schema names;IsRegisteredis the other half, so a host can ask whether a schema's language will resolve before running anything. Registration replaces rather than duplicates, so a host may override a built-in generator, and a generator naming no language is refused outright — it could never be found again, so an entry under an empty key would only fail later and further away. The table is process-wide and unsynchronised, meant to be filled once at startup; the remarks say so.Not in this change
The editor's type picker does not offer a component yet, for the same reason it does not offer a
Semantic, aSpanor aHandle—Schema.GetSelectableElementTypesstill lists only the built-ins, the enums and the classes.Testing
Schema.Test376 passed,SchemaEditor.Test201 passed, whole solution builds with no warnings. Twelve new tests inVectorElementTypeTestscover the default, inequality by component and by shape, resolution against the schema, each validation rule, the round trip, and that a vector of floats writes no component. Seven more inGeneratorRegistryTestscover registration, case-insensitive lookup, replacement, and both refusals.🤖 Generated with Claude Code
https://claude.ai/code/session_01AhoPJ5AbxP8QEBNxPQYEPk