Editor Features

The Confµgami LSP server provides the editor features listed here for configuration and definition files. Any LSP capable editor can use them. Setting Up the IDE describes the VS Code setup.

Diagnostics

Files are validated in real time as you type:

  • JSON5 parse errors.

  • A missing $definition key in configuration.

  • Values that violate the definition, such as wrong types, out of range values, or unknown properties.

  • Definition model errors, such as invalid type paths, duplicate declarations, or bad multiplicities.

Opening or saving a file re-validates all related files, so a change in one file updates the diagnostics of every file that depends on it.

Code Completion

  • In configuration files, ref values complete to all reachable entities by path or numeric id.

  • In definition files, type references (refTargetTypes, typeRefs, ref, inherits) complete to all visible entity types.

  • Inside a constraint’s assert or a message.

  • $applyMixins completes to the mixins whose $type applies to the element, minus the ones it already applies. Inside a mixin body it also leaves out what would close a composition cycle.

  • The $applyMixins key itself is offered on every entity and struct of a mergeable configuration.

  • Inside a $mixins entry, $type completes to every type of the definition a mixin may select, and the properties of that type complete once it names one.

Scaffolding a Whole Structure

Accepting a key completion in a configuration file does not insert the key alone. The inserted value is the whole required structure below it, as deep as the definition requires:

  • Every required child, filled with its default, and a typed empty tab stop where the definition declares none.

  • The number of list elements the multiplicity demands, with generated entity names that continue the names already in the list and skip the ones another merged file already uses.

  • The $type discriminator of a union member.

  • Tab stops through the values that still need a decision, so Tab walks the skeleton instead of the cursor hunting for the next hole.

In a mergeable configuration the scaffold leaves out what another file already contributes to the same element, so accepting a completion adds what is missing rather than a duplicate that conflicts on the next validation.

Go to Definition

  • In configuration files, jump from a ref value to the entity it points to.

  • In definition files, jump from a type reference to the type’s declaration.

  • On a $type value in a configuration file, jump to the type it names, on a fragment root and on a union member alike. Its leading segment is the definition name and jumps to the definition document.

  • Navigation is segment aware. Invoking it on an intermediate path segment jumps to that segment’s entity.

  • On the value of an _origin entry, jump to the position of the upstream file that entry names, as far as its anchor still finds that line. The whole entry is the clickable range, so a Ctrl click does not stop at the first :.

  • On a relPath or absPath of the $originSpec table, open the upstream file it names.

  • In .confu files, on a definitions entry, list the definition files discovery actually found under it. That is the direct answer to "did this entry contribute anything", which otherwise only shows up as an unresolvable $definition in some configuration file much later.

Each definitions entry of a .confu file is a link to the folder or file it names, so a Ctrl click opens it. An entry that does not resolve carries no link and is reported as a diagnostic instead.

Go to Type Definition

Go to type definition on any position inside a configuration element jumps to the definition element that types it: the entity, struct, or parameter declaration in the .def.json5 file. Unlike go to definition, which fires on a relation key or a ref value, this works from anywhere inside the element’s body. In definition files it resolves the type reference under the cursor, like go to definition there.

Find References

  • In configuration files, find all ref parameters in the workspace that point to a given entity.

  • In definition files, find all type references across all documents that reference a given type.

  • On a mixin, every place its name is written (the $mixin declaring it, the elements applying it, the mixin bodies composing it) plus the elements it applies to. Those elements are what an unnamed mixin answers with at all, and for a named one they cover what a composing mixin carries onto an element that never names it. A mixin is addressed by its name wherever that is written, and by the $mixin or $type key of its declaration.

  • On an element with an _origin, the upstream positions that annotation names are results as well, so the record leads back to the files the element was generated from. An element carries one entry per upstream file, and every entry that resolves is a result. An entry whose anchor no longer finds its line is left out instead of pointing at a position that has moved away.

Document Highlight

Placing the cursor on an entity name in a configuration file marks that name as the write occurrence and every ref value in the same file pointing at it as a read occurrence. In definition files the same works on a type’s name: its declaration is the write occurrence, every typeRef and refTargetTypes entry naming it in the same file a read occurrence. The cross-file picture stays with find references.

Hover Documentation

Hovering over a parameter, entity, or relation shows its name, title, and Markdown description from the definition.

On a constraint’s name or message, the hover shows the constraint.

In a configuration file, on the place a constraint violation is reported at, the hover traces the violated constraint first. An accepted violation is traced too, further violations of the element are listed by name.

Constraint MaxBaud is violated: The bus runs at 1000000.

baud <= 500000
|    |
|    false
1000000

Signature Help

Inside the argument list of a built-in function of a constraint, the signature of the function shows with the parameter at the cursor. Typing ( or , triggers it.

Code Lenses

Every $mixins declaration carries a Mixin applies to <count> elements lens on the line its entry opens. The count is elements of the merged model, not files: one element merged from several configuration files counts once, exactly as the hover lists it, and one a $remove takes out counts not at all. Invoking the lens peeks the same results find references gives for the declaration.

Code lenses need an editor that registers the command they invoke, which today is the VS Code extension.

Inlay Hints

  • Type hints show the data type after each parameter value, for example : u8.

  • Unit hints show the declared unit next to numeric values, for example MHz.

  • Override indicators appear in mergeable configurations on parameters that are shadowed by a higher priority file. ✎≠ marks an override with a different value and ✎= an override with the same value. The hint’s tooltip names the effective value and its source file. Such a parameter can be removed without changing the merged result.

  • ⇣= marks the effective value when a lower or equal priority file already sets the same value.

  • In definition files, each variable a constraint binds shows its type.

Code Actions

Remove unused value is offered on any parameter whose value is fully overridden by a higher priority file. Applying it deletes the redundant entry without changing the effective configuration.

Extract entity '<name>' to new file is offered on a nested entity of a mergeable configuration. Applying it creates <name>.cfg.json5 next to the current file, holding the entity’s content with a $path / $type anchor pointing back at it, and leaves the entity’s name, id and $type keys behind so the file still declares the anchor. See Working with Multiple Files for the fragment semantics.

The action is offered only when the definition merges entities across files, the file is user modifiable (see the $fileType priorities).

Extract properties to mixin '<name>' is offered on an entity or a struct of a mergeable configuration. Applying it moves the element’s properties into a $mixins declaration of the same file and leaves an $applyMixins behind, so the block becomes reusable on the element’s siblings. The element keeps what is its own rather than its type’s: name, id, $type, $description, $comment and its annotations. A line comment above a moved property moves with it, since it documents that property. The merged configuration is unchanged by it, only the file is.

Create mixin '<name>' is offered on an $applyMixins naming a mixin no $mixins entry declares. Applying it writes that entry into the same file, selecting the type of the element the name is written on.

Formatting

Configuration, definition, and .confu files are formatted with the canonical Confµgami style.

  • Full document formatting.

  • Range formatting rewrites only the lines the selection touches, so format-on-paste and format-modified-lines keep diffs minimal.

  • On-type formatting formats the line a } or , was typed on, and the line the cursor left after a newline.

A file with syntax errors is never modified. The .confu formatter: false setting disables formatting for the files it governs.

Go to Implementation

In the mergeable file modes, go to implementation on an entity, struct or parameter jumps to all source files that contribute to the merged element. For a parameter this includes the files whose value lost to a higher priority one. See Working with Multiple Files for the merge semantics.

Document Symbols

Configuration files provide an outline of their entities, usable via the editor’s symbol sidebar and breadcrumbs. Definition files list their elements, types, annotation types and constraints. The workspace symbol search finds configuration entities, definitions, types and constraints by name.

Rename

Entities in configuration files can be renamed, by name or by id. All ref values pointing to the renamed entity are updated across the workspace.

Mixins can be renamed from their $mixin declaration and from any $applyMixins naming them, and both rewrite the declaration and every application of the definition the file belongs to. A new name that is not an identifier, or that the definition already declares, is refused.

Semantic Highlighting

Semantic tokens are provided for definition and configuration elements, enabling context aware coloring beyond what a grammar based highlighter can provide. The assert and message of a constraint are colored by their expression syntax.

Workspace Index

On startup the server discovers all .def.json5, .def.json, .cfg.json5, and .cfg.json files in the workspace. File system changes are watched, so created, modified, and deleted files are picked up without an editor restart. Definition folders a .confu points to outside the workspace folders are watched as well, on editors supporting LSP 3.17 relative watch patterns (VS Code does). Folders whose .confu sets ignoreTraversal: true are excluded from discovery.