Skip to main content
Version: 0.0.18

Validation and diagnostics

Validation in the context of Jayvee can be understood as semantic analysis of Jayvee models. The purpose is to uncover errors in models besides lexing, parsing and linking errors that the Langium framework already detects out of the box. In case such errors are found, the language server makes the IDE display a diagnostic. This means that the location of the error is underlined and an error message is shown.

For example, each pipeline is expected to contain at least one starting block that requires no input. Therefore, the language server analyzes every pipeline in a Jayvee model and checks for the presence of such a starting block. In case no such block is found, the IDE underlines the pipeline definition in a red color and displays an error message.

How to implement validation

For arbitrary AST nodes

In the file validation-registry.ts of the language server, there is a registry containing validation functions for various AST nodes. A validation function provided for a certain kind of AST node is called for every occurrence of such a node in a Jayvee model. E.g. when registering a validation function for PipelineDefinition nodes, that function gets called once for each pipeline.

A validation function always operates on a single, concrete AST node. Besides the AST node, a ValidationContext object is passed to the function for reporting diagnostics via its accept method.

The overall validation for a specific kind of AST node is usually subdivided into smaller checks that are called sequentially. This potentially allows aborting the validation early, i.e. before all checks were run. Aborting early may be useful if errors were reported during previous checks. This can be determined via the ValidationContext which keeps track whether any errors occurred so far.

A practical example where this plays a role are blocks: When the type of a block is unknown to the language server, it makes no sense to validate inputs / outputs and properties of that block. So, in case an error was reported during the check of the block type, the validation of that block is discontinued at that point.

For properties of blocks and constraints

Validating property values of blocks / constraints works a bit differently because their individual validation is already incorporated into the overall validation framework.

In general, the validation logic for a property values is located in the meta information of the block type / constraint type. There, properties are defined using the PropertySpecification interface. In order to add validation logic to a certain property, a validation function needs to be added to that property.

For more complex validations that need to take multiple property values into account, it is also possible to provide a more general validation function which operates on the entire PropertyBody AST node.

See text-range-selector-meta-inf.ts for an example which includes both cases described above.

Reporting diagnostics

During validation, diagnostics can be reported by calling the accept method of the given ValidationContext object.

The call requires the severity of the diagnostic (error, warning, info or hint), the error message and its location. The location is described by a DiagnosticInfo object which contains the affected AST node and optionally some further restrictions. For more details, have a look at the DiagnosticInfo interface by Langium.

Common issues

When working on validations, a diagnostic with the following message may unexpectedly occur: An error occurred during validation: ...

Such a diagnostic is generated by the Langium framework if an error object is thrown within the validation. In most cases, the reason is the access of an undefined AST node property or an AssertionError. For more details on such errors and how to avoid them, have a look at the documentation on how to work with the AST.

One way locate the origin of such errors is to debug the Jayvee VS Code extension, see here for more details. Another possibility is to debug the interpreter and set appropriate breakpoints in the language server codebase.