How the Features Work Together
This chapter explains the feature interactions of different features working together.
The File Mode Is the Master Switch
Every multi-file feature is gated by the configurationFileMode of the definition.
The definition author picks the mode, and that decides which keys your files may use:
configurationFileMode |
Several files | Entities merge | Priority $fileType |
Fragments $path / $type |
Mixins $mixins / $applyMixins |
|---|---|---|---|---|---|
|
no |
no |
no |
no |
no |
|
yes |
no |
no |
no |
no |
|
yes |
yes |
no |
yes |
yes |
|
yes |
yes |
yes |
yes |
yes |
Consequences:
-
A key that is right in one project is an error in the next one, because the definition behind it uses a different mode.
cfu def listprints the mode of every definition in the workspace. -
Mixins and fragments have no switch of their own. Once a definition merges entities, both are available.
Fragments and Mixins
Both write configuration content outside the place it ends up, and both merge it in as if a file had written it there. They differ in how they pick the target:
| Fragment | Mixin | |
|---|---|---|
Selects |
one entity, by its path ( |
every element of a type ( |
Creates the target |
never, some file has to declare the anchor |
never, some file has to declare the element |
Creates content below the target |
yes |
yes, except a mixin of a |
Identity on its own root |
forbidden, the last |
forbidden, one body cannot give many elements one identity |
Everything below the selector follows the ordinary merge rules of Working with Multiple Files. A fragment may apply mixins, a mixin body may contain the nested entities a fragment would have written, and the merged model does not record which route a value took.
Priority Decides Before Specificity
A mixin has its own precedence ladder (content on the element, then a named mixin, then an unnamed one), and $fileType has another one.
The two are not weighed against each other, they apply in order: $fileType first, the mixin ladder only within one priority.
The effect people trip over: an unnamed mixin in a UserConfigPriorityHigh file overrides a value written directly on the element in a UserConfig file, although content on the
element is the most specific source there is.
When an override does not take effect, compare the $fileType of the two files before looking at the mixins.
Defaults and Preconfiguration Require a Config
.default.def.json5 and .preconfig.def.json5 files belong to the definition.
They stay inert until one of your .cfg.json(5) files declares that definition, per CfgSpace, and a file holding nothing but $definition is enough to activate them.
Three combinations follow from that:
-
A CfgSpace that configures definition
Agets `A’s defaults and not `B’s, although both definitions are discovered in the same workspace. -
A
refin your file must not point at an entity that exists only in the default or preconfiguration content of a definition your CfgSpace never activates. The target would be missing from the merged model, so add a configuration file for that definition. -
Deleting your last configuration file for a definition also removes its preconfigured values from the merged model. A merged result that loses more than you deleted is usually this.
An Identity That Is Also a Value
An entity may be named by one of its own parameters, see Entities Named by One of Their Values. Everything that binds to identity then binds to that value:
-
A reference path and a fragment
$pathspell the mangled name (/Bus/comvectorEngine), not the value it was mangled from. -
A contribution in another file has to repeat the source value, because each file builds the name it merges under on its own.
-
A mixin body cannot supply that value: the name is built while the file is parsed, before mixins are applied and before defaults are merged.
Editing such a value is therefore a rename, with all the consequences described in Pitfalls.
Reading the Merged Result
Where several files, mixins and defaults meet, the merged model is the only thing that answers "what is actually configured". The tools that show it, from coarse to precise:
| Tool | Answers |
|---|---|
|
What the consuming software sees, as one file. |
|
Which file and which line each value came from. |
|
The same as a tree in the terminal, with required properties that no file configures marked |
Inlay hints |
That this value is shadowed by a higher priority file, and which value wins instead. |
Go to implementation in the IDE |
The files contributing to a merged element, and the source of an effective value. |
The Mixin applies to n elements code lens |
How far a mixin declaration currently reaches. |
Discovery Beats All of It
Merging, mixins and references only consider files that discovery found, and only within one CfgSpace. A file in the wrong place therefore produces no conflict and no error, it produces nothing:
-
Outside the workspace, or below a folder whose
.confusetsignoreTraversal: true: the file is invisible and validation stays green. -
Inside the workspace but in another CfgSpace: the file is validated, but it never merges with your CfgSpace. A mixin declared there applies in that space only, and a fragment there needs its anchor there.
cfu workspace list shows the discovered files and the CfgSpace each one landed in, which is the first command to run when a change has no effect at all.
Text That Travels, and Text That Does Not
$description and $comment are part of the model and survive merging and export, a plain JSON5 // comment does not.
A typed annotation travels as far as its definition allows: the definition author sets its retention, and a Source annotation is dropped from every merged JSON output while an
Output one reaches the downstream consumer.
Worth knowing before putting a note into an annotation that a generator reads, or expecting a // comment to survive an export.
-
Feature Interactions in the developer manual describes the same interactions from the definition author’s side.