Read a project whose whole definition is one matlab.toml - #61
Merged
Merged
Conversation
A `matlab.toml` project file is designed to be hand-edited, so it will carry comments, quoting variants, dotted keys and multi-line arrays. A subset parser that mis-reads one of those renders a confidently wrong project page, which is the expensive failure; smol-toml is a spec-compliant parse with no dependencies of its own, is browser-safe, and ships under the same BSD-3-Clause license this package does. The lockfile's `resolved` URL is rewritten to the public registry, as every entry here must be. Its recorded version also catches up to package.json, which a bump had left behind at 1.13.1.
R2026b's `matlab.project.DefinitionFiles.Toml` puts a project's entire definition into one hand-editable `matlab.toml` at the project root, and deletes `resources/` and the `<name>.prj` marker with it. There is no store to walk, so this is a separate reader rather than a fourth layout in `ProjectParser`; what the two share is the result, `ParsedProject`, so a page, a node tree and a host see one project shape whichever of the four formats it arrived as. `parseProject` dispatches on finding the file among a store's entries, which keeps every existing caller at one call. Two fields carry what the format cannot say. `membersEnumerated` answers whether the FORMAT records a member list, not whether members were found: an XML store that enumerates none means "0 members", and a `matlab.toml` means "ask the filesystem", which is a different sentence and the one a host needs to tell apart. `ProjectLabel.declaredFiles` holds the paths a label was declared against, which only this format has — a store assigns labels the other way round, per member file. A project is now identified by an extension OR by a name, so `isProjectFile` is name-aware and `projectFallbackName` reduces a marker PATH: every project in the new format spells its file identically, so stripping an extension would title all of them "matlab", and the rule that works is the parent folder's name. That widening has one reachable consequence, which is why `ingest` gains a branch ahead of its `.prj` one: a `.prj` is a zip and this is text, so unzipping first would fail with "invalid zip data" on a healthy project. The parser folder may now reach `datamodel/fileKinds.ts` as well as `blockIdentity.ts`. Both are tables of rules about names shared with code outside the folder, neither imports anything itself, and re-spelling 'matlab.toml' inside the folder to avoid the edge would be the exact defect `fileKinds` was written to end.
A project page built from a format that records no member list must not report one. `memberCount`, `labelledCount` and each label's `count` become `number | null`, `null` exactly when `ParsedProject.membersEnumerated` is false, because 0 is a sentence — "this project contains nothing" — and it is false about a project whose members are every file under its root. The maintainer's decision is to declare only what the file declares, with no folder walk to synthesize a membership the document does not have. `null` rather than a sentinel, deliberately: the consuming webview's `esc()` takes `string | number`, so a `null` reaching it is a compile error at the call site and a renderer is forced to branch. A -1 would have type-checked and shipped. What a page shows instead is on the new `ProjectPageLabel.declaredFiles`, carried through from the parse: an XML store assigns labels per member file and the count is the whole story there, while this format inverts it — the label declares its files — so the list stands in place of the count rather than beside it. With no assignments to count, the label ordering falls back to the name; "used labels first" would order every label as if it were known to be unused. Tests: a reader suite over the committed parity fixture for what MATLAB writes, and over inline documents for what a person writes, since hand editing is the whole point of the format — comments, a `#` inside a string, literal strings, dotted keys, trailing commas, a single string where MATLAB writes an array, and every field given the wrong TOML type. The parity suite's three assertions that the format was unread are replaced by the agreement they were standing in for: a TOML parse equals an XML parse of the same project field for field on everything the format records, entry-point run order included, which is a linked list in a store and an array here. The lossiness measurements stay as they are.
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.
R2026b added a fourth project definition format,
matlab.project.DefinitionFiles.Toml:the project's entire definition is one hand-editable
matlab.tomlat the project root,and both
resources/and the<name>.prjmarker are deleted with it. This reads it.There is no store to walk, so
src/datamodel/parser/TomlProject.tsis a reader of itsown rather than a fourth layout in
ProjectParser. What the two share is the result,ParsedProject, so a page, a node tree and a host see one project shape whichever ofthe four formats it arrived as.
parseProjectdispatches on finding the file among astore's entries, which keeps every existing caller at one call.
What the format does not record
Two new fields carry that, because an empty list would otherwise be read as a claim
about the project rather than about the format:
ParsedProject.membersEnumerated— whether the FORMAT records a member list, notwhether members were found.
trueon every XML path (a damaged store enumeratednothing, which is a different sentence from a format that enumerates nothing, and the
memberCount: 0a host already shows for one is correct and unchanged);falseonlyfor TOML, where MATLAB's rule is that the files under the project root ARE the
members — about the filesystem, not about the document.
ProjectLabel.declaredFiles— the paths or patterns a label was declared against, aswritten. Empty on every XML layout, which assigns labels the other way round, per
member file.
The page follows:
memberCount,labelledCountand each label'scountbecomenumber | null, and a label's declared entries stand in place of a count it does nothave.
nullrather than a sentinel is deliberate — the consuming webview'sesc()takes
string | number, so anullreaching it is a compile error at the call site anda renderer is forced to branch. A
-1would have type-checked and shipped.Identity
A project is now identified by an extension OR by a name, so
isProjectFileisname-aware and
projectFallbackNamereduces a marker PATH: every project in the newformat spells its definition file identically, so stripping an extension would title all
of them "matlab", and the parent folder's name is the rule that works. That widening has
one reachable consequence inside this package, which is why
ingestgains a branchahead of its
.prjone: a.prjis a zip and this is text, so unzipping first wouldfail with "invalid zip data" on a perfectly healthy project.
It is the file NAME and emphatically not the
.tomlextension, which would make everyCargo.tomlandpyproject.tomlin a workspace a MATLAB project.Conservative readings, each recorded where it is made
[dependencies]yields a reference only for an inline table carrying a stringpath.A bare string there is a package version constraint — a valid entry of a kind this
package does not model, not damage — so it is skipped in silence. A warning there
would fire on healthy files, and a count that cries wolf is a count a host learns to
hide.
[project.shortcuts]takes both spellings, because under that key there isnothing else a bare string could mean.
a user edits by hand, so a number where a path belongs is an ordinary state of a real
file; what could not be read is said in
warningsinstead of thrown.been verifiable against the corpus — MATLAB reports 9 members for the converted
fixture — but it would make a page's numbers depend on disk state rather than on the
document.
Tests
test/tomlProject.test.tsreads the committed parity fixture for every assertion of theform "this is what MATLAB writes", and inline documents for what a person writes, since
hand editing is the whole point of the format: comments including a
#inside a string,basic vs literal strings, dotted keys, trailing commas, a single string where MATLAB
writes an array, and every field given the wrong TOML type.
The parity suite's three assertions that this format was unread are replaced by the
agreement they were standing in for: a TOML parse equals an XML parse of the same
project field for field on everything the format records, entry-point run order included
— a linked list in a store, an array here. Ids are excluded and the reason is in the
test: conversion preserves MATLAB's UUIDs between XML layouts, while this format records
none, so every id here is synthetic. The lossiness measurements (
LabelDataLoss, thedropped read-only category) stay as they are.
npm run verifygreen: 5241 tests / 175 files,check:pack(dist-only, 539 files,588.1 kB),
check:leak,check:browser(148 modules, nonode:import reachable fromthe barrel).
The parser folder may now reach
datamodel/fileKinds.tsas well asblockIdentity.ts,and
test/moduleBoundaries.test.tsrecords why: both are tables of rules about namesshared with code outside the folder, neither imports anything itself, and re-spelling
'matlab.toml'inside the folder to avoid the edge would be the exact defectfileKindswas written to end. No folder-level edge is added —
datamodel/parser -> datamodelalready existed.