1.9 KB62 lines
Blame
1import type { ValidationAcceptor, ValidationChecks } from 'langium';
2import type { MermaidAstType, Treemap } from '../generated/ast.js';
3import type { TreemapServices } from './module.js';
4
5/**
6 * Register custom validation checks.
7 */
8export function registerValidationChecks(services: TreemapServices) {
9 const validator = services.validation.TreemapValidator;
10 const registry = services.validation.ValidationRegistry;
11 if (registry) {
12 // Use any to bypass type checking since we know Treemap is part of the AST
13 // but the type system is having trouble with it
14 const checks: ValidationChecks<MermaidAstType> = {
15 Treemap: validator.checkSingleRoot.bind(validator),
16 // Remove unused validation for TreemapRow
17 };
18 registry.register(checks, validator);
19 }
20}
21
22/**
23 * Implementation of custom validations.
24 */
25export class TreemapValidator {
26 /**
27 * Validates that a treemap has only one root node.
28 * A root node is defined as a node that has no indentation.
29 */
30 checkSingleRoot(doc: Treemap, accept: ValidationAcceptor): void {
31 let rootNodeIndentation;
32
33 for (const row of doc.TreemapRows) {
34 // Skip non-node items or items without a type
35 if (!row.item) {
36 continue;
37 }
38
39 if (
40 rootNodeIndentation === undefined && // Check if this is a root node (no indentation)
41 row.indent === undefined
42 ) {
43 rootNodeIndentation = 0;
44 } else if (row.indent === undefined) {
45 // If we've already found a root node, report an error
46 accept('error', 'Multiple root nodes are not allowed in a treemap.', {
47 node: row,
48 property: 'item',
49 });
50 } else if (
51 rootNodeIndentation !== undefined &&
52 rootNodeIndentation >= parseInt(row.indent, 10)
53 ) {
54 accept('error', 'Multiple root nodes are not allowed in a treemap.', {
55 node: row,
56 property: 'item',
57 });
58 }
59 }
60 }
61}
62