Skip to content

fix: constrain the xml and xlink attributes in mx::core - #461

Merged
webern merged 1 commit into
mainfrom
m/mxdev-xmlattr
Sep 19, 2026
Merged

webern merged 1 commit into
mainfrom
m/mxdev-xmlattr

Conversation

@webern

@webern webern commented Sep 19, 2026 •

Copy link
Copy Markdown
Owner

Human Summary

This was a relatively unimportant missing validation on the MusicXML. Now we coerce pattern-invalid link attributes and send up a diagnostic when we do.

Summary

MusicXML imports xml.xsd and xlink.xsd, and the generator passed every attribute declared there through as a plain string. Values those schemas forbid were therefore representable in mx::core, which is the exception #398 reports: the model is supposed to make an invalid MusicXML value impossible.

The IR now follows the imports the MusicXML schema declares. The XSD parser reads the imported schemas that sit beside the main one, and the lowering resolves each external attribute ref against the declaration it finds there:

  • xml:space becomes a closed vocabulary (default, preserve).
  • xlink:type, xlink:show and xlink:actuate become closed vocabularies whose members are read from xlink.xsd, so a schema bump cannot leave them drifting.
  • xml:lang becomes the xs:language primitive. Its declared type is the builtin xs:language, which no schema declares, so it rides the builtin primitive table the way the identity tokens do; the C++ target maps it to a new hand-written Language wrapper beside Token that validates the builtin pattern and admits the empty tag the attribute's schema unions in. An out-of-grammar tag repairs to the empty tag, the un-declared value.
  • xlink:href, xlink:role and xlink:title stay std::string: they are xs:anyURI and xs:string, which accept nearly any string.

An out-of-vocabulary value is repaired and reported through a Diagnostic, the leniency every other value type applies, so no document that parsed before now fails to parse and no in-vocabulary value changes. 49 corpus files carry xml:lang, 54 carry xml:space and 7 carry the xlink attributes; all of their values are in-vocabulary.

All four targets are regenerated in the same commit: 4 new value types in C++, Go and C, plus the 18 attribute sites the issue lists. mx::api is untouched, because none of these attributes is exposed there.

Testing

  • make test-all: core round trip (841 files), core unit (646 assertions), api-test (5879 assertions), api round trip (414 files)
  • make test-go and make test-c, the other two targets' suites
  • make gen-test (146 tests, including the new imported-vocabulary IR cases)
  • make gen-quality (84.7, floor 84.5) and make gen-lint (9.29, floor 9.29)
  • make gen then git diff --exit-code: no generated drift
  • make fmt-check
  • New tests: LanguageKeepsTheBuiltinPatternOrEmpty and ImportedXmlAndXlinkVocabulary in ValueTest.cpp, RepairsOutOfVocabularyXmlAndXlinkAttributes in DocumentTest.cpp, and four cases in gen/tests/test_ir.py

References

The generator now follows the imports the MusicXML schema declares, so the
attribute declarations in xml.xsd and xlink.xsd are lowered instead of being
passed through as strings: xml:space and xlink:type/show/actuate become closed
vocabularies with the schemas' own members, and xml:lang becomes the builtin
xs:language primitive, mapped in C++ to a hand-written Language wrapper beside
Token. Regenerates all four targets; no mx::api change.
@webern webern added bug software defect non-breaking fixes or implementation that do not require breaking changes core Affects the mx::core layer gen The gen/ directory which is generating code from the spec ai Issues opened by, or through, a coding agent. labels Sep 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

gen-quality gen/

gen-quality: 84.7 / 100   (floor 84.5, +0.2)

  structure     86.3  x0.50   [fn 90.7 / file 82.0]
  cyclomatic    88.7  x0.25
  cognitive     77.3  x0.25

  423 functions across 31 files, 7924 lines (largest file 1051)
  max cc 56  max cognitive 44  max fn loc 152

Worst offenders (top 5 per axis; full lists in score.json):
  cyclomatic gen/xsd/analyze.py:311     report                             56
  cyclomatic gen/plates/build.py:963    _validate_config_against_ir        35
  cyclomatic gen/press/context.py:145   plate_context                      35
  cyclomatic gen/__main__.py:46         _ir                                23
  cyclomatic gen/tests/test_ir.py:102   _check_references                  20
  cognitive  gen/xsd/analyze.py:311     report                             44
  cognitive  gen/ir/resolve.py:119      flat_elements                      40
  cognitive  gen/tests/test_ir.py:102   _check_references                  38
  cognitive  gen/press/context.py:145   plate_context                      37
  cognitive  gen/xsd/analyze.py:207     _sccs                              37
  size       gen/xsd/analyze.py:311     report                             152
  size       gen/press/context.py:145   plate_context                      97
  size       gen/plates/build.py:540    _value_plate                       89
  size       gen/plates/build.py:963    _validate_config_against_ir        89
  size       gen/ir/resolve.py:119      flat_elements                      78

Commit 1e858fcecc5e5b11a9b7bc8af6a08d95215f4692.

@webern

webern commented Sep 19, 2026

Copy link
Copy Markdown
Owner Author

/coverage

@github-actions

Copy link
Copy Markdown
Contributor

Coverage report

Core-dev coverage src/private/mx/core/

Metric Coverage Covered / Total
Lines 76.9% 28961 / 37668
Functions 73.5% 6568 / 8935
Branches 50.8% 23805 / 46903

API coverage src/private/mx/{api,impl,utility}/

Metric Coverage Covered / Total
Lines 88.1% 9836 / 11163
Functions 81.7% 3980 / 4870
Branches 54.9% 8440 / 15365

Core HTML report | API HTML report

Commit be7fca1e4dccb458107fd0954814738b354b65cb.

@webern
webern merged commit ad0ca08 into main Sep 19, 2026
8 checks passed
@webern
webern deleted the m/mxdev-xmlattr branch September 19, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai Issues opened by, or through, a coding agent. bug software defect core Affects the mx::core layer gen The gen/ directory which is generating code from the spec non-breaking fixes or implementation that do not require breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

xml:* and xlink:* attributes are unconstrained strings in mx::core

1 participant