-
Notifications
You must be signed in to change notification settings - Fork 61
/
statemachine-validator.ts
57 lines (53 loc) · 2.46 KB
/
statemachine-validator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/******************************************************************************
* Copyright 2021 TypeFox GmbH
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
import type { ValidationAcceptor, ValidationChecks } from 'langium';
import type { State, Statemachine, StatemachineAstType, Event } from './generated/ast.js';
import type { StatemachineServices } from './statemachine-module.js';
import { MultiMap } from 'langium';
export function registerValidationChecks(services: StatemachineServices) {
const registry = services.validation.ValidationRegistry;
const validator = services.validation.StatemachineValidator;
const checks: ValidationChecks<StatemachineAstType> = {
State: validator.checkStateNameStartsWithCapital,
Statemachine: validator.checkUniqueStatesAndEvents
};
registry.register(checks, validator);
}
export class StatemachineValidator {
/**
* Checks if the state name starts with a capital letter.
* @param state the state to check
* @param accept the acceptor to report errors
*/
checkStateNameStartsWithCapital(state: State, accept: ValidationAcceptor): void {
if (state.name) {
const firstChar = state.name.substring(0, 1);
if (firstChar.toUpperCase() !== firstChar) {
accept('warning', 'State name should start with a capital letter.', { node: state, property: 'name' });
}
}
}
/**
* Checks if there are duplicate state and event names.
* @param statemachine the statemachine to check
* @param accept the acceptor to report errors
*/
checkUniqueStatesAndEvents(statemachine: Statemachine, accept: ValidationAcceptor): void {
// check for duplicate state and event names and add them to the map
const names = new MultiMap<string, State | Event>();
const allSymbols = [...statemachine.states, ...statemachine.events];
for (const symbol of allSymbols) {
names.add(symbol.name, symbol);
}
for (const [name, symbols] of names.entriesGroupedByKey()) {
if (symbols.length > 1) {
for (const symbol of symbols) {
accept('error', `Duplicate identifier name: ${name}`, { node: symbol, property: 'name' });
}
}
}
}
}