Repository navigation
LookupTable, Breakpoint, VariantBank and Signal properties follow MATLAB - #124
Merged
Merged
Conversation
…AB's classes do not have
MATLAB R2027a has no Description property on Simulink.LookupTable or
Simulink.Breakpoint: isprop is 0, and setting one fails with "Unrecognized
property 'Description' for class 'Simulink.LookupTable'." Both nodes listed
one anyway, so the table and the Property Inspector offered an editor, the
edit was accepted, and both save paths wrote it as a top-level key that
MATLAB opens without a warning and ignores.
Both nodes now do what FunctionElement does. Description is not in
getProperties or in the General layout, descriptionEditable is false, and
setProperty('Description', ...) is refused in MATLAB's words and leaves the
entry unmodified. A Description key the file already has is shown read-only
(in the Description column and in the inspector's Other group) and is
written back as read on both save paths.
test/lutBreakpointNoDescription.test.ts covers both classes in both formats
and a new entry. Existing tests changed only where they pinned the removed
editor: typedef.fidelity's Description round-trip (now: refused, file
unchanged), the General groups in piGeneralAllNodes and lookupTableFlatProps,
the Breakpoint and LookupTable rows in absentPropertyWriteBack's table, and
schemaLayoutResolvable's layout-key floors (182 to 180 and 100 to 98, the two
removed description keys). The two class docs no longer claim a passing
MATLAB gate for a Description edit.
…s does not have
MATLAB R2027a has no Value property on Simulink.VariantBank: its properties
are Name, Description, VariantConditions, AllChoicesCoderInfo and
ActiveChoiceCoderInfo, isprop(..., 'Value') is 0, and setting one fails with
"Unrecognized property 'Value' for class 'Simulink.VariantBank'." The node
offered one anyway: the cell took an editor, setProperty('Value', ...) was
accepted, and both save paths wrote the text beside the saveobj envelope.
MATLAB opens such a file with no error or warning, builds a bank with no
Value, and drops the key on its next save, so the edit had no effect. Every
bank MATLAB wrote also showed '', a char value the class does not have.
The node now does what a bus element does (#113). valueEditable is false, a
Value edit is refused ("'<name>' is a Simulink.VariantBank, which has no
Value, so none can be set on it.") and leaves the entry unmodified, and
_serializedOverrides is empty, so no save writes a Value. A Value key a file
already carries (only ever this package's) is shown quoted, read-only, and
written back as read. A bank with no Value key shows an empty cell. The Value
column stays, read-only, for that key.
test/variantBankNoValue.test.ts covers the bank MATLAB wrote, in both
formats, and a new entry. Its fixtures are
test/fixtures/classes_r2027a_text.sldd and classes_r2027a_binary.sldd,
written by MATLAB R2027a, with their generator, make_classes_r2027a.m. A
re-run gives the same files apart from UUIDs and timestamps.
Existing tests changed only where they pinned the removed edit. In
variantLeafNodes, the VariantBank row of the shared contract now checks that
an edit is refused and the bag is written back as read, instead of checking
that the edit is written. Its two cases in the quoted-display regression,
which commit a Value, are removed. The class doc records the measurement,
and two comments that cited VariantBank's Value as written are corrected.
…AB's class does not have
MATLAB R2027a has no Value property on Simulink.VariantBankCoderInfo. Its
properties are HeaderFile, DefinitionFile, PreStatement, PostStatement and
Qualifier, isprop(..., 'Value') is 0, and setting one fails with
"Unrecognized property 'Value' for class 'Simulink.VariantBankCoderInfo'."
The node offered one anyway: the cell took an editor, setProperty('Value',
...) was accepted, and both save paths wrote the text beside the saveobj
envelope. MATLAB opens such a file with no error or warning and builds an
object with no Value, so the edit had no effect. Every entry MATLAB wrote
also showed '', a char value the class does not have.
The node now does what VariantBank does (the previous commit) and a bus
element does (#113). valueEditable is false, a Value edit is refused
("'<name>' is a Simulink.VariantBankCoderInfo, which has no Value, so none
can be set on it.") and leaves the entry unmodified, and
_serializedOverrides is empty, so no save writes a Value. A Value key a
file already carries (only ever this package's) is shown quoted, read-only,
and written back as read. An entry with no Value key shows an empty cell.
The Value column stays, read-only, for that key.
test/variantBankNoValue.test.ts now runs its cases over a table of both
classes, adding vbciD (MATLAB-written, in both formats of the existing
classes_r2027a fixtures) and a new entry. The VariantBank cases and their
titles are unchanged.
Existing tests changed only where they pinned the removed edit. In
variantLeafNodes, the VariantBankCoderInfo row of the shared contract
joins VariantBank in READ_ONLY: it now checks that an edit is refused and
the bag is written back as read, instead of checking that the edit is
written. The quoted-display case for the two classes is retitled, since
"like MATLAB" no longer holds for a key MATLAB's classes do not have; its
assertions are unchanged. The class doc records the measurement.
…AB's own sets
MATLAB R2027a's Simulink.Signal (and mpt.Signal) takes Complexity from
auto|real|complex and DimensionsMode from auto|Fixed|Variable, both defaulting
to auto, and refuses anything else with "There is no enumerated value named
'X'." Both showed as read-only labels, while BusElement and ValueType already
offered the same two properties as dropdowns. A setProperty('complexity', ...)
also answered true and changed nothing: the text went onto a stray lowercase
field that nothing shows or saves.
SignalNode now uses BusElement's and ValueType's mechanism with the Signal's
sets. Two new atoms (PropSignalComplexity, PropSignalDimensionsMode) replace the
two schema descriptors in place, both in the table columns and in the Property
Inspector layout, so both panes read the node field an edit writes. The column
order and the schema's layout order are unchanged. setProperty refuses any
other value through DataNode._rejectUnknownEnumeral, but only for these two
properties, so Storage Class keeps its own refusal. Both save paths write the
key when the file had it or the value is not auto. An untouched Signal, or one
set back to auto, therefore saves with no new key in a text dictionary, which
is how MATLAB writes it. A binary dictionary always has the key. A cleared cell
shows auto and is saved as auto, never as ''. Dimensions stays a label, and so
does Parameter's Complexity, which comes from its Value.
test/signalEnumProps.test.ts drives the session and the node over Signals
MATLAB wrote (sigC, sigR, sigA and sigNo in classes_r2027a_{text,binary}.sldd,
and sig1 in params.sldd), plus an mpt.Signal and a new Signal. A default
Signal set to complex/Variable saves as what MATLAB wrote for sigC: the text
bag is equal as a value (the new keys come last, where MATLAB sorts them), and
the binary element matches character for character. Set back
to auto, it saves as sigA. The test also covers refusals, a clear, undo
through the session, and the Property Inspector layout.
Existing tests changed only where they pinned the removed label:
- schemaColumns.test's "read-only Dimensions Mode" now expects the select cell.
- mptClasses.test's typed columns now read the cells' text.
- propAtoms.test: one comment.
Simulink.Signal.md and the two shared atoms' comments now describe the new
behaviour.
…TLAB's rule
Alignment (CoderInfo.Alignment) was a read-only label on Simulink.Parameter,
Simulink.Signal and their mpt subclasses. MATLAB R2027a lets it be set, by a
rule measured on 2026-10-16:
- The value is converted as int32 first, so 1.5 becomes 2 and 2^31 saturates.
- It must then be -1 or a power of two from 1 to 2^30.
- Only after that check, under StorageClass 'Auto', every value but -1 is
refused.
- Setting StorageClass back to 'Auto' resets Alignment to -1.
A text dictionary holds a non-default value as a typed int32, first in
CoderInfo, and leaves the key out at -1. A binary one always holds an int32.
MATLAB reads a string "16" back as -1, so writing the cell's text as it was
would have lost the edit.
The table's alignment column is now a text cell wherever MATLAB takes an
edit, and a plain string under 'Auto'. A new optional PropClass.editableFor
hook, which BaseNode.getPropInfo honours, gates the cell on the node's
StorageClass. trySetSchemaProperty applies the rule, refusing in MATLAB's
words. MATLAB's "no more than 128" is left out, because MATLAB does not apply
it.
An edit keeps the form the file already holds: a typed leaf keeps its _type
and a bare number stays bare. A new key is a typed int32, inserted where
MATLAB's sorted text puts it. A string leaf is replaced, and a string is never
written. -1 removes the key in a text dictionary, and a StorageClass edit to
'Auto' does the same. Setting the value already held marks nothing. The
Property Inspector still shows Alignment read-only, as it shows Storage Class.
test/alignmentEdit.test.ts drives the session and the node over the entries
MATLAB wrote in classes_r2027a_{text,binary}.sldd. pSC set to 8 saves pAl8's
CoderInfo exactly. pAl8 set to -1 saves pAlM1's, and pAl8 with StorageClass
'Auto' saves pNo's. The test also covers each power of two up to 2^30, the
int32 conversion, MATLAB's refusals with nothing changed, the Auto gate and
its order, undo and redo through the session, the stored forms, a new entry
in each format, and an mpt.Parameter.
Existing tests changed only where they pinned the removed label:
- schemaBridge.test and schemaColumns.test: alignment's editor is now 'text'.
- mptClasses.test: an ExportedGlobal mpt.Parameter's Alignment is now an
editable cell.
- schemaBridgeEdit.test: trySetSchemaProperty now owns alignment and refuses
it under Auto, instead of declining it as a label.
codegenEdit.test and schemaColumns.fidelity.test still pass unchanged, because
their entries are 'Auto'. Only their titles and comments changed, since those
called Alignment read-only.
CodeGeneration.schema-columns.md and Simulink.Parameter.md describe the rule
and the written form.
Two behaviours of this branch that no test locked (the correctness review put
`{ Value: this.Value }` back in both nodes, and swapped toInt32 for
Math.round, and the suite stayed green):
- C-168 and C-169: a Simulink.VariantBank or Simulink.VariantBankCoderInfo
held with no saveobj envelope, as the corpus's R2026b text dictionaries
hold one (plain sorted _properties, no Value key), saves with no Value.
The envelope cases could not see this, because under an envelope
_mergeProps drops an empty override. New cases in
test/variantBankNoValue.test.ts build that form from the committed
classes_r2027a_text.sldd, one entry at a time, and check that an unedited
save gives the file back byte for byte and that a save after a rename
writes no Value. Reverting either node's _serializedOverrides fails that
class's two cases.
- C-086: a negative half is rounded away from zero, as MATLAB's int32 does.
Measured in R2027a (27.1.0.3409468) on a Parameter's and a Signal's
CoderInfo under ExportedGlobal: -0.5 is set to -1; -1.5 and -1.6 are
refused as -2, -2.5 as -3, and -0.4 as 0; 0.5 is set to 1. Two new cases
per format in test/alignmentEdit.test.ts drive pAl8 and sAl16 through
setProperty and the save. Math.round fails all four.
Tests only; no src change.
main's #123 reached main after this branch's last green CI, and the merge ref failed 4 tests. Neither failure is a defect in either side: each test pinned something the other PR changed on purpose. - test/newEntryEnvelopeBothFormats.test.ts (from #123, C-199). Three cases set a Value on a new Simulink.VariantBank to exercise a field the saveobj envelope does not declare. C-168 removes exactly that Value (MATLAB's class has none), so the set is now refused. The cases move to the one vehicle a new entry still has for that shape: Simulink.VariantConfigurations' Value, written by createDefault as a sibling beside an envelope that does not declare it, in both formats. The assertions are unchanged; the undeclared case also states its premise (the envelope's _fields has no Value), so a vehicle that stops being one fails rather than passing vacuously. That Value is unmeasured against MATLAB and may be invented too; the comment says so. With #123's _mergeProps clear reverted (src only), all five C-199 cases here fail with the old sibling still written. - test/signalEnumProps.test.ts (this branch, C-030). The Property Inspector's Other group for sigC in a binary dictionary now lists LoggingInfo's seven properties, because #123's C-032 flattens a binary 1x1 object one level as the same object out of a .mat. The text dictionary's LoggingInfo has no properties, so it stays one row. The expectation follows #123 per format. With C-030's src reverted the case still fails (at its first assertion, the PI row's edit); with C-032's piOther change reverted it fails at the updated line. No src change; dist rebuilt clean after the merge with no difference.
This was referenced Oct 16, 2026
Merged
ww-mw
added a commit
to mathworks/data-explorer-vscode
that referenced
this pull request
Oct 17, 2026
v1.40.0 (f9acdf9) carries mathworks/data-explorer-core#124 (Signal Complexity and DimensionsMode options; Alignment editing), #125 (mpt entries admitted by paste and drop) and #127 (findNodeById and the duplicate-id warning), the core halves of C-030, C-086, C-180 and F1-50. It also carries #128 (MCOS numeric classes, per-element object classes). The lockfile changes only data-explorer-core: its root spec and its node_modules entry, which now resolves to f9acdf939aa726cb9ddd3162a6cac19fc4f4a5ca. With the pin: npm run verify passes 3422 of 3422 tests in 175 files, and check:leak is OK; npm run test:integration has 221 passing and 1 pending.
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.
Five items, one commit each. Each commit regenerates
dist/(rm -rf dist && npm run build) and passednpm run verifyon its own tree.The ruling (DECIDED 2026-10-16, group E, the backlog). The maintainer: "Agree your suggestions, use subagents, teammates, or workflow agents to handle all of them automatically. Add unit tests to lock down the fix. I pre-approve PR and merge as long as it passes all tests." All five items are under theme 2, follow MATLAB: "follow MATLAB, and measure it first (…) where it is unmeasured."
Measurements. MATLAB R2027a (27.1.0.3409468) was measured on 2026-10-16, before any code was written. Two dictionaries that MATLAB itself wrote then are now committed as
test/fixtures/classes_r2027a_text.slddandclasses_r2027a_binary.sldd, together with their generator,test/fixtures/make_classes_r2027a.m. A re-run of the generator gives the same files apart from UUIDs and timestamps. The four new test files use these entries, so each fix is checked against MATLAB's own bytes, not against a hand-written expectation.How the tests were checked. Every new test was run against the source as it was before its commit, with the test file present. Each one failed, and failed for the reason stated, apart from the controls marked below.
C-020: LookupTable and Breakpoint offered a Description that MATLAB's classes do not have (d0abc99)
The recommendation it adopts: "(a). It follows the FunctionElement ruling (ServiceBusNode.ts:26-30) and the MATLAB-measured default bags. Fix the doc's 'gate PASS' line in the same change." Option (a) is: "Mirror FunctionElement: drop PropDescription and the schema 'description' row for both classes, and keep any existing top-level key as a read-only pass-through."
What was wrong. In MATLAB,
isprop(Simulink.LookupTable,'Description')is 0, and the same holds forSimulink.Breakpoint. Setting one fails with "Unrecognized property 'Description' for class 'Simulink.LookupTable'." A LookupTable or Breakpoint that MATLAB writes carries no top-level Description, in either format. Core still offered an editor in the table and in the Property Inspector, accepted the edit, and wrote it as a top-level key on both save paths. MATLAB opens such a file with no warning and ignores the key, so the edit was saved and had no effect. The class docs also claimed "MATLAB gate: Description edit -> MATLAB reads back. PASS.", which was not true.Root cause.
LookupTableNode.getPropertiesandBreakpointNode.getPropertiesreturned[PropName, PropDataType, PropDescription]. Their_serializedOverrideswrote Description through_gatedProps. The General layouts inschema/classes/lookupTable.jsonandbreakpoint.jsonlisteddescription.Fix. Both nodes now do what FunctionElement does:
getPropertiesis[PropName, PropDataType], anddescriptionEditableis false.setProperty('Description', …)is refused in MATLAB's words, "Unrecognized property 'Description' for class ''.", and leaves the entry unmodified._serializedOverridesis gone (the inherited{}), so a top-level Description key that a file already has passes through as read, on both save paths.name, value, dataType, kind, class.A key that is already present shows read-only, both in the Description column and in the inspector's Other group.
Simulink.LookupTable.mdandSimulink.Breakpoint.mdnow record the measurement and the refusal, and the false gate line is removed.Tests.
test/lutBreakpointNoDescription.test.tshas 14 cases. They cover both classes in both formats of the parityparams.sldd(MyLUT and MyBkpt), plus a new entry, and run throughcreateSession/ingest,setProperty,toRow,toPIObjectandserializeSource:getProperties,_descriptionEditableis false, General has the 5 items, and the inspector has no editable Description.'kept'written into its bytes shows the value read-only in the row and in Other, refuses an edit, and writes'kept'back on both paths and in the re-parsed save.Before the fix, all 14 failed: "expected true not to be true" (the edit was accepted), "expected [Name, DataType, Description] to not include 'Description'", and "expected true to be false" (
_descriptionEditable).Existing tests changed. Each one pinned exactly the Description editor that the ruling removes.
test/parity/fidelity/typedef.fidelity.test.ts: the LUT and Breakpoint cases "Description edit round-trips in-process" become "Description edit is refused; the file's key is unchanged", in both formats.test/schema/piGeneralAllNodes.test.ts: the General check is split. CustomObject keeps Description, and LookupTable and Breakpoint have the five items.test/lookupTableFlatProps.test.ts: 'Description' is dropped from both General expectations.test/absentPropertyWriteBack.test.ts: the Breakpoint and LookupTable rows are removed from itsCASEStable, and the header's count goes from eleven classes to nine. Each row types a Description into the entry and checks how both save paths write it back. Neither class takes that edit now. The two states that still hold (a file without the key stays without it, and a file with the key keeps it) are covered by the new test.test/schemaLayoutResolvable.test.ts: its layout-key floors go from 182 to 180 pairs and from 100 to 98 probe cases. The two pairs lost are exactly the two removeddescriptionlayout keys.Left out.
setProperty('Value', …)still answers true on LookupTable, Breakpoint, Signal and ValueType, and the text is dropped on save. None of them has an editable Value. This is the kind of bug that #113 fixed for bus elements, but it is a separate item and not part of this ruling.C-168: VariantBank offered and wrote a Value that MATLAB's class does not have (bbbb4f1)
The recommendation it adopts: "(a) now, together with C-169, as one deliberate test edit. Do (b) once a MATLAB-written fixture exists. Run one MATLAB load of a dictionary carrying the sibling Value first: if MATLAB refuses it, raise the priority." Option (a) is: "Override valueEditable to false and stop writing a non-empty Value, so _serializedOverrides writes nothing."
What was wrong.
properties(Simulink.VariantBank)is Name, Description, VariantConditions, AllChoicesCoderInfo and ActiveChoiceCoderInfo.isprop(…, 'Value')is 0, andvb.Value = 'x'fails with "Unrecognized property 'Value' for class 'Simulink.VariantBank'." Core offered a Value editor anyway.setProperty('Value', …)was accepted, and both save paths wrote the text beside the saveobj envelope:_properties: {Value: 'x'}in text, and<P Name="Value" Class="char">x</P>after the saveobj in binary. Every bank that MATLAB wrote also showed'', a char value the class does not have.The pre-check the recommendation asks for. A dictionary carrying our writer's sibling Value was loaded in MATLAB, in both formats. MATLAB opens it with no error and no warning, reads all 14 entries, and builds a bank with no Value. A MATLAB re-save drops the key. MATLAB does not refuse the file, so the priority was not raised. The edit was accepted, saved, and had no effect, which is what (a) removes.
Root cause.
VariantBankNode.getPropertieslistedPropValue, with novalueEditableoverride, so BaseNode's default made the cell editable._serializedOverrideswrote Value with no gate. The display quoted the empty field.Fix. The node now does what a bus element does after #113:
valueEditableis false._serializedOverridesreturns{}, so no save writes a Value.Simulink.VariantBank.mdrecords the measurement. Two comments that described VariantBank's Value as written were corrected, inPropValue.tsandVariantConfigurationDataNode.ts.Fixtures.
test/fixtures/classes_r2027a_text.slddandclasses_r2027a_binary.slddare the MATLAB-written dictionaries described above, with 14 entries each. They are used here (vbD) and by C-169, C-030 and C-086. The fixture sweeps (fixtureHygiene and check:leak) pass with them.Tests.
test/variantBankNoValue.test.tshas 9 cases over vbD, in text and binary, plus a new entry:''in displayValue, in the row and in the inspector, and none of them is editable.x,'x'and the empty string. The entry is not Modified. Neither save path writes a Value, and neither does the saved file after a rename, both re-parsed and in the text entry and binary XML.'b1'written into the bytes where the old writer put it: shown as'b1', read-only in the row and the inspector, edits refused, and written back as'b1'on both paths and in the re-parsed save.'', is not editable, refuses an edit, and writes no Value (the text bag, the binary bag and the XML).Before the fix there were 8 failures: the 7 non-control cases, and the new contract row in
variantLeafNodes. Each failed for the right reason: "expected '''' to be ''" (the display), "expected true not to be true" (the edit was accepted), "expected true to be false" (the cell was editable), and "expected true to match object { error: true }".Existing tests changed.
test/variantLeafNodes.test.tspinned exactly the removed edit:READ_ONLYset is added. For the VariantBank row of the shared contract, "writes an edit back through the array wrapper" becomes "refuses an edit, and writes the property back as it was read".The contract's other cases for this row are unchanged and green.
Left out. Option (b) is left for a follow-up: modelling the bank's real fields through
classes/variantBank.json. The recommendation makes it the next step once a MATLAB-written fixture exists, and this PR commits that fixture.VariantConfigurationDataNodehas the same Value contract. WhetherSimulink.VariantConfigurationshas a Value was not measured, so it is not changed.C-169: VariantBankCoderInfo offered and wrote a Value that MATLAB's class does not have (1d2be05)
The recommendation it adopts: "(a) in the same change as C-168. (b) is a reasonable follow-up here sooner than for VariantBank, because every field is a plain char with a measured default." Option (a) is: "valueEditable false and no non-empty Value write."
What was wrong.
properties(Simulink.VariantBankCoderInfo)is HeaderFile, DefinitionFile, PreStatement, PostStatement and Qualifier. All of them are char and default to'', except Qualifier, which defaults to'None'.isprop(…, 'Value')is 0, and setting a Value fails with "Unrecognized property 'Value' for class 'Simulink.VariantBankCoderInfo'." The node behaved exactly as VariantBank did: the cell had an editor,setProperty('Value', …)was accepted, and both save paths wrote the text beside the envelope. MATLAB opens such a file in either format with no error and no warning. It builds an object with no Value, with Qualifier'None', so the edit had no effect. The class doc's header said "Editable in our UI: no", which contradicted the code.Root cause. This is the same as C-168, in
VariantBankCoderInfoNode.ts. There was novalueEditableoverride, and_serializedOverrideswrote Value with no gate.Fix. The node now mirrors C-168's VariantBankNode:
valueEditableis false._serializedOverridesreturns{}.The two nodes are kept as copies of each other, as they were before, rather than sharing a new helper.
Simulink.VariantBankCoderInfo.mdis rewritten to match: its header is now true, it records the measurement, and it leaves (b) as the follow-up.Tests.
test/variantBankNoValue.test.tsnow runs its cases over a table of both classes, which adds the same 9 cases for vbciD. That entry is MATLAB-written and comes from the same fixtures, in both formats. The VariantBank cases, their assertions and their titles are unchanged. A Value is injected into the binary bytes at the place where the old writer put it for this class: after the closing</P>of the saveobj.Before the fix there were 8 failures: the 7 non-control vbciD cases, and the vbciD contract row in
variantLeafNodes. They failed for the same reasons as in C-168. The VariantBank cases stayed green.Existing tests changed. In
test/variantLeafNodes.test.ts, each change pinned the removed edit:'Simulink.VariantBankCoderInfo'joinsREAD_ONLY. Its row's "writes an edit back through the array wrapper" becomes "refuses an edit, and writes the property back as it was read".Left out. Option (b) is left out: the five real char fields modelled through
classes/variantBankCoderInfo.json. The recommendation calls (b) a follow-up. Its fixture, vbciD, is now committed.C-030: Signal's Complexity and DimensionsMode become dropdowns over MATLAB's own sets (cca1e6e)
The recommendation it adopts: "(a). Confirm Signal's enum sets with set(Simulink.Signal,'Complexity') and set(Simulink.Signal,'DimensionsMode') in MATLAB first, then reuse the BusElement and ValueType mechanism with Signal's own options. Dimensions stays a label."
MATLAB, measured first.
set(Simulink.Signal,'Complexity')isauto|real|complex, andset(…,'DimensionsMode')isauto|Fixed|Variable. Both default toauto, andmpt.Signalis the same.''..slddwrites a value other than auto as a top-level key and leaves the key out atauto. A binary one always writes<P Name="Complexity" Class="char">auto</P>.What was wrong. Both properties were read-only labels on a Signal, while BusElement and ValueType already offered the same two as dropdowns. A
setProperty('complexity', …)also answered true and changed nothing. The text went onto a stray lowercase field that nothing shows or saves.Root cause.
schema/props/dataObject.jsongivescomplexityanddimensionsModethe editorlabel, andSignalNode.setPropertyrouted only Min and Max specially, so there was no enum path. The shared atoms could not simply be reused, becausePropComplexityoffersreal|complexandPropDimensionsModeoffersFixed|Variable. Neither has Signal'sauto.Fix.
PropSignalComplexity(auto, real, complex) andPropSignalDimensionsMode(auto, Fixed, Variable), bothselect. A cleared cell reads asauto, which is what the save writes.PropComplexityandPropDimensionsModekeep their sets for BusElement and ValueType.SignalNodegetsComplexityandDimensionsModefields, defaulting toauto. The two atoms replace the two schema descriptors in place: in the table columns, and in every group of the inspector layout. Both panes read the field that an edit writes. The column order and the schema's layout order are unchanged.setPropertyrefuses any other value throughDataNode._rejectUnknownEnumeral, in MATLAB's words.auto. So an untouched Signal, or one set back toauto, saves with no new key in a text dictionary, which is how MATLAB writes it. A binary dictionary always has the key. A clear is saved asauto, never as''.dataObject.jsonis not touched.Simulink.Signal.mdis updated, including its "safe as read-only" note, which now covers Dimensions only. The two shared atoms' comments are updated too: "only BusElement uses this" was already stale, because ValueType uses them as well.Deviation from the scoped change, with its reason. The enum check runs only for
complexityanddimensionsMode. Run for every select, it also caught Signal'sstorageClass, whose refusal would have changed from "Invalid value for Storage Class" to MATLAB's enumeral wording. That broke two cases intest/parity/fidelity/schemaColumns.fidelity.test.ts, which pin nothing the ruling removes, so the check was narrowed and that test was left alone.Tests.
test/signalEnumProps.test.tshas 18 cases. They run through the session (ingest,editProperty, undo,serializeSource) and through the node, over the MATLAB-written sigC, sigR, sigA and sigNo in both formats. They also cover sig1 inparams.sldd, anmpt.Signalon both save paths (re-parsed), and a new entry:<Element>is identical character for character.auto, the text entry equals the untouched save, with no key, as MATLAB's sigA has none. The binary entry writesauto, as sigA does.auto.Before the fix, all 18 failed: the cell was a label string (
expected 'auto' to deeply equal { text: 'auto', editable: true, … }), the edit reached neither the display nor the save, a foreign value was accepted, and the inspector row was read-only.Existing tests changed. Each pinned exactly the removed label.
test/schema/schemaColumns.test.ts: "read-only Dimensions Mode" now expects editorselectand the select cell, and is retitled.test/mptClasses.test.ts:row.complexityandrow.dimensionsModeare now read through.text, because they are select cells.test/propAtoms.test.ts: one comment only. Its assertion is unchanged.Left out. MATLAB matches case-insensitively and stores the canonical spelling (
'Complex'becomes complex). That is not adopted: the match stays exact, as it is for BusElement and ValueType, and a dropdown sends only canonical spellings.setProperty('Complexity', …), with the capitalised field name that no host sends, skips the enum check, and ValueType and BusElement have the same gap. Both points apply to all three classes, so they are left for one later change.C-086: a Parameter's or Signal's Alignment can be edited in the table, by MATLAB's rule (71b3446)
The recommendation it adopts: "(b): the validation rule is already recorded, but the written form and defaults-stripping are exactly what the plan deferred. One MATLAB check turns this into a bounded core and vscode change." Option (b) is: "Measure first in MATLAB: how Alignment=8 is written in text and binary .sldd, whether a bare number reads back as Alignment, the upper bound, and whether -1 should be stripped. Then ship with defaults-stripping."
MATLAB, measured first.
StorageClass'Auto', the default, any value but -1 is refused: "Cannot set Alignment when StorageClass is 'Auto'." The value check comes first. Setting StorageClass back to 'Auto' resets Alignment to -1..slddholds a value other than -1 as"Alignment": {"_type": "int32", "_value": "8"}, first in CoderInfo, and leaves the key out at -1. A binary one always holds<P Name="Alignment" Class="int32">8</P>."16", which is what the generic writer would have written, is silently read as -1, so the edit would be lost.What was wrong. The user chose inline editing for Alignment, and it was never delivered. Alignment stayed a read-only label on
Simulink.Parameter,Simulink.Signaland theirmptsubclasses.Root cause. In
schema/props/codeGen.json, alignment has the editorlabel.trySetSchemaPropertydeclines every label prop and validates only selects. Making the cell editable alone would have written the cell's text as a string, which MATLAB reads as -1.Fix.
parameter.jsonandsignal.jsongive thealignmentref the editortext.codeGen.jsonstill sayslabel, so Bus's inspector-only row is unchanged.PropClass.editableFor(node), whichBaseNode.getPropInfohonours. It can only take editability away. Alignment is editable unless the node's StorageClass is 'Auto'. Under 'Auto', the row holds a plain string.schemaBridgeapplies MATLAB's rule, in MATLAB's order and words:_type, and a bare number stays bare. A new key is a typed int32, inserted where MATLAB's sorted text puts it. A string leaf is replaced by a typed one, and a string is never written. In a text dictionary -1 removes the key. Elsewhere it is written as int32 -1, and a key that is absent stays absent. Setting the value already held marks nothing as Modified.CodeGeneration.schema-columns.mdandSimulink.Parameter.mddescribe the rule and the written form. Two helpers,sourceLeafandisTypedScalar, are added toschema/index.ts, andwriteSourcePathnow uses them, with no change in its behaviour.Deviations from the scoped change, with their reasons.
Tests.
test/alignmentEdit.test.tshas 25 cases. They run through the session (ingest,editProperty, undo, redo,serializeSource,addEntry) and through the node, in both formats, over the MATLAB-written pSC, pAl8, pAlM1, pNo and sAl16:addEntry: refused under Auto, then accepted after ExportedGlobal, saved and read back.mpt.Parameter.Before the fix, all 25 failed: the cell was the label string, the edit was not written, or a refusal was answered
true.Existing tests changed. Each pinned the removed label.
test/schema/schemaBridge.test.tsandtest/schema/schemaColumns.test.ts: alignment's editor is nowtext. Both are retitled.test/mptClasses.test.ts: an ExportedGlobalmpt.Parameter's alignment is now an editable cell.test/schemaBridgeEdit.test.ts: it checked thattrySet('alignment')returns null, because alignment was a label.trySetSchemaPropertynow handles alignment, and with no StorageClass refuses it as Auto. The checks that nothing changes are unchanged.Only titles and comments changed in
test/codegenEdit.test.tsandtest/parity/fidelity/schemaColumns.fidelity.test.ts, which called Alignment read-only. Their assertions are unchanged, and they pass because their entries are Auto.Left out.
For the vscode pin bump (not in this PR)
None of the five needs a vscode source change. The table already honours
_descriptionEditableand_valueEditable, it already renders a select cell and a text cell for a schema column, and both providers send the edit tonode.setProperty. This core was packed and installed into vscode v1.39.0 (3cd6a16), and the two suites were run:npm run test:integration: 191 passing and 1 pending, the same as with vscode's own pinned core.npm run verify: 3263 passed and 1 failed (3264 pass with vscode's own core). The failure istest/dimensionsMode.test.ts:39-47, "the Signal surfaces a read-only dimensionsMode column from real data", withexpected 'select' to be 'label'. It pins exactly the label that C-030 removes. It is to be updated at the pin bump, where a lock test for the Alignment cell (C-086) also belongs.Gate, at the head (71b3446)
rm -rf dist && npm run build: rc 0, and the tree stays clean (git status --porcelainis empty, after the build and after verify).npm run verify: rc 0. It ran typecheck, build, smoke, test, check:pack, check:leak and check:browser:node:builtin.8e33408.mainhas since gained A zip member that inflates past its declared size is reported unreadable instead of silently truncated #121 and The MCOS decoder warns about the blocks it stopped reading and the variables its confidence gate skipped #122. Those two PRs and this one change no file in common, andgit merge-treereports no conflict.Implements the maintainer's 2026-10-16 group E ruling.
Follow-up commit 8353f69: tests that lock the two parts the review found unlocked
This commit adds tests only. There is no src change. The correctness review found that two parts of this PR could be reverted with the suite staying green. Each now has tests that fail when it is reverted.
test/variantBankNoValue.test.ts. They hold a VariantBank and a VariantBankCoderInfo in the form the corpus's R2026b text dictionaries use: plain, sorted_properties, with no_custom_saveand no Value key. That form is copied field for field frommix/dd_json.slddandtextsldd/dd.sldd, and is built from the committedclasses_r2027a_text.sldd, rewriting one entry per case."Value"in the entry, and a save after a rename writes no Value either._mergePropsdrops an empty override, so the old{ Value: '' }never reached the file.{ Value: this.Value }back in both nodes fails 4 of 8047 tests, and those 4 are exactly these cases. Reverting one node alone fails only that class's 2 cases.test/alignmentEdit.test.tsdrive pAl8 and sAl16 throughsetPropertyand the save:toInt32forMath.roundfails all 4 of them, and nothing else.npm run verifypasses: 8023 passed and 26 skipped, which is 8 more than at 71b3446.Merge of main (#123) and two reconciled tests: 49d51fa, f0d2b90
#123 (C-032, C-199, F2-4, F6-1, C-003) reached main as c3dee1a after this PR's last green CI. On the merge ref, CI then failed 4 tests. Neither side has a defect. Each failing test pinned something the other PR changes on purpose.
rm -rf dist && npm run buildgives a dist that matches the committed one exactly (zero files changed), so no dist commit was needed.1.
test/newEntryEnvelopeBothFormats.test.ts(from #123, C-199): the test needed a new vehicle; what it checks is the sameWhat broke. Three cases called
setProperty('Value', 'x')on a newSimulink.VariantBank:They used that Value to exercise one shape: a field the saveobj envelope does not declare, so the sibling
<P>is its only copy. C-168 removes exactly that Value, because MATLAB'sSimulink.VariantBankhas none (measured in R2027a). The set is now refused with "'vNew' is a Simulink.VariantBank, which has no Value, so none can be set on it."Why the change is authorized. The maintainer ruled for C-168 (group E, 2026-10-16, theme 2: follow MATLAB). That ruling removes the vehicle these cases used. C-199's ruled behaviour does not change: a cleared envelope property is written as MATLAB writes one, and an undeclared field's sibling goes.
The new vehicle.
Simulink.VariantConfigurations' Value. Among new entries, it is the only fieldcreateDefaultstill writes as a sibling beside a_custom_saveenvelope that does not declare it. That is true in both formats: VariantBankCoderInfo's Value went with C-169, and VariantVariable's Specification is declared.{ className: 'Simulink.VariantConfigurations', prop: 'Value', declared: false }, and the undeclared_mergePropscase uses the same class._fieldshas noValue. If this vehicle ever becomes declared, or goes away, the case fails instead of passing vacuously.A caveat, stated in the test's comment. Whether MATLAB's
Simulink.VariantConfigurationshas a Value has not been measured (scope-C-169 already noted this). It may be invented too. If a later ruling removes it, there is no vehicle left among new entries for the undeclared shape.Proof that the intent is kept. I reverted Binary nested objects in Other, a cleared envelope property, VariantControl Description, model-reference ids, and a dist-freshness CI gate #123's C-199 change in
DataNode._mergeProps(src only, then restored) and ran the file. All 5 C-199 cases failed, including the 3 moved ones. Each failure shows the old value still written:expected [ '<unnamed>', 'Value' ] to deeply equal [ '<unnamed>' ]expected [ '_properties', '_custom_save' ] to deeply equal [ '_custom_save' ]expected true to be false, :419)2.
test/signalEnumProps.test.ts(this PR, C-030): the expectation now follows #123's layout['Other.LoggingInfo']. Binary nested objects in Other, a cleared envelope property, VariantControl Description, model-reference ids, and a dist-freshness CI gate #123's C-032 flattens a binary 1x1 object one level, the same as that object out of a.mat. So Other now lists LoggingInfo's seven properties:Other.LoggingInfo.{DataLogging, NameMode, LoggingName, DecimateData, Decimation, LimitDataPoints, MaxPoints}.['Other.LoggingInfo'], because MATLAB's text writer gives LoggingInfo no properties, so it is one row named by its class.expected { shown: 'complex', editable: false } to deeply equal { shown: 'real', editable: true }(:266).piOther.tschange reverted, the binary case fails at the updated line:expected [ 'Other.LoggingInfo' ] to deeply equal [ …(7) ](:277). So the line pins Binary nested objects in Other, a cleared envelope property, VariantControl Description, model-reference ids, and a dist-freshness CI gate #123's layout.Gate
npm run verifyon the merged tree passes: 8172 passed and 26 skipped (246 files passed, 1 skipped). That is the 8168 tests that passed on the old merge ref plus the 4 reconciled ones. check:pack, check:leak and check:browser are OK, and the tree is clean afterwards.