Skip to content

feat: the TOML reader accepts TOML 1.1 inline tables written over several lines - #929

Open
NopeCharon wants to merge 1 commit into
mcpp-community:mainfrom
NopeCharon:feat/toml-multiline-inline-tables
Open

NopeCharon wants to merge 1 commit into
mcpp-community:mainfrom
NopeCharon:feat/toml-multiline-inline-tables

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

Summary

mcpp.libs.toml read an inline table only when it was written on one line. A newline, a comment or a comma after the last pair inside the braces was refused with expected key. TOML 1.1.0 allows all three, and the provider example in docs/35-platforms.md already writes runner = { ... } over three lines, which mcpp could not read. The released 2026.11.12.1 refuses cmdline = { version = "0.0.1",⏎ features = [] } with mcpp.toml:6:31: error: expected key.

read_inline_table now skips newlines and comments between the braces and the pairs, and accepts a comma after the last pair. A pair stays on one line (key = value, as TOML 1.1 requires). An empty element ({ , }, { a = 1,, }) is still refused. A table that never closes is reported at its { as unterminated inline table.

Two text editors meet the new form, and both now handle the whole value:

  • upsert_dependency_text (mcpp add, template self-dependency injection) replaced an existing entry by its first line only. Its own re-parse then refused the result (dependency edit produced invalid manifest).
  • mcpp remove erased the first line only and wrote the file without a re-parse. That left the rest of the value behind as a corrupt manifest.

Both use one helper, mcpp::manifest::assignment_end. It finds the newline after a value by counting brackets outside strings and comments. mcpp index pin and unpin still edit only an [indices] entry written on one line. They already refused a multi-line one without writing anything, but called it "malformed"; the refusal now states the real cause. docs/04 states the TOML dialect and docs/09 states the pin/unpin boundary, in English and Chinese.

Closes #928.

Criteria

  • Toml.AnInlineTableSpansLines covers newlines, comments, a trailing comma, a nested table with trailing commas, a multi-line array inside the table, {⏎}, and a key after the table. Toml.AnInlineTableKeepsEachPairOnOneLine covers what stays refused: a pair split before or after =, two pairs without a comma, ,,, { , }, and the position and text of unterminated inline table. On macOS arm64 I built modules/libs with tests/unit/test_toml.cpp using the released 2026.11.12.1. Both cases fail without the change (expected key, and "expected key" == "unterminated inline table") and pass with it; all 20 cases pass.
  • ManifestEditor.ReplacesAnEntryWrittenOverSeveralLines replaces a multi-line entry that holds a } in a comment and a ] in a string. ManifestEditor.AnAssignmentEndsWhereItsValueCloses pins the helper. On the same host I built the modules/manifest package alone with these two tests, the two existing ManifestEditor tests and tests/unit/test_toml_serialize.cpp (including RepositoryManifestsRoundTrip). All pass. Without the change, the editor case fails with dependency edit produced invalid manifest: mcpp.toml:7:23: error: expected key.
  • tests/e2e/23_remove_update.sh now seeds a multi-line baz = { ... } and removes it. With the released 2026.11.12.1 it fails: the manifest keeps the table's last three lines under [dependencies]. I did not build a full mcpp binary on this host, so the passing run of this script, and the compile of src/pm/commands.cppm and src/pm/index_management.cppm, are left to CI. I checked the mcpp remove erase logic separately in a scratch test that copies its lambda over assignment_end: on the script's manifest it leaves foo and bar intact.
  • check_docs_style.sh, check_docs_structure.sh, check_version_pins.sh, check_manifest_key_classes.py, check_narrow_conversions.sh, check_include_regions.sh and check_workflow_assertions.py pass.

Intersections

New rule or feature Invariant it crosses Test at the crossing
Inline tables span lines serialize writes a document that reads back into the same tree (it writes inline tables on one line) TomlSerialize.*, including RepositoryManifestsRoundTrip
Inline tables span lines Source-preserving mcpp add edits one entry and re-parses its result ManifestEditor.ReplacesAnEntryWrittenOverSeveralLines
Inline tables span lines mcpp remove erases one entry and leaves the others e2e 23_remove_update.sh (baz removed whole, bar kept)
Inline tables span lines mcpp index pin/unpin edit an [indices] entry in place none: they refuse an entry that does not close on its line and write nothing, as before; only the message changed
Comments inside an inline table A # inside a string is not a comment AnInlineTableSpansLines ("{}" and "--" values), AnAssignmentEndsWhereItsValueCloses

Compatibility

Every file that parsed before parses into the same tree. Files with an inline table over several lines, a comment inside one, or a trailing comma were refused before and now load. Only one error message changes for a file that was refused before: an inline table that never closes is reported at its { as unterminated inline table instead of expected key. No output, default or cache key changes.

Checks before merging

  • bash .github/tools/check_docs_style.sh, check_docs_structure.sh and check_version_pins.sh pass.
  • python3 .github/tools/check_workflow_assertions.py passes (a step asserts what its name says).
  • No commit on the branch carries an attribution trailer:
    git log origin/main..HEAD -i --grep='Co-Authored-By' prints nothing.
  • The squash merge is given an explicit subject and body, so GitHub does not
    compose one from the branch's commits. Suggested subject: feat: the TOML reader accepts TOML 1.1 inline tables written over several lines.

…eral lines

mcpp.libs.toml read an inline table only when it was written on one line:
a newline, a comment or a comma after the last pair inside the braces was
refused with `expected key`. TOML 1.1.0 allows all three, and the provider
example in docs/35 already writes `runner = { ... }` over three lines, which
mcpp could not read.

read_inline_table now skips newlines and comments between the braces and the
pairs and accepts a comma after the last pair. A pair stays on one line, an
empty element (`{ , }`, `{ a = 1,, }`) is still refused, and a table that
never closes is reported at its `{` as `unterminated inline table`. Every
document that parsed before parses into the same tree.

Two text editors meet the new form:

- upsert_dependency_text (`mcpp add`, template self-dependency injection)
  replaced an existing entry by its first line only, so its own re-parse
  refused the result. It now replaces the whole value.
- `mcpp remove` erased the first line only and wrote the file without a
  re-parse, leaving the rest of the value as a corrupt manifest. It now erases
  the whole value.

Both use one helper, mcpp::manifest::assignment_end, which finds the newline
after a value by counting brackets outside strings and comments.
`mcpp index pin` and `unpin` still edit only an entry on one line; their
refusal of a multi-line one now says so instead of calling it malformed.

Docs: docs/04 states the TOML dialect, docs/09 the pin/unpin boundary, in
English and Chinese.

Tests: Toml.AnInlineTableSpansLines, Toml.AnInlineTableKeepsEachPairOnOneLine,
ManifestEditor.ReplacesAnEntryWrittenOverSeveralLines,
ManifestEditor.AnAssignmentEndsWhereItsValueCloses, and a multi-line entry in
e2e 23_remove_update.sh.

Closes mcpp-community#928.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: the TOML reader accepts TOML 1.1 inline tables written over several lines

1 participant