Skip to content

Commit

Permalink
improvements after the second review
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesMeierSE committed Apr 15, 2024
1 parent 8952ee1 commit a6ee465
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
18 changes: 12 additions & 6 deletions packages/langium/src/grammar/validation/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -802,9 +802,8 @@ export class LangiumGrammarValidator {
// new map to store usage information of the assignments
const map: Map<string, AssignmentUse> = new Map();

// top-down traversal
// top-down traversal for all starting nodes
for (const node of startNodes) {
// TODO dürfen mehr als 1 Action auftauchen? ansonsten funktioniert das hier nicht so ganz wie gedacht!
this.checkNodeRegardingAssignmentNumbers(node, 1, map, accept);
}

Expand Down Expand Up @@ -839,7 +838,7 @@ export class LangiumGrammarValidator {
// Search for assignments in used fragments as well, since their property values are stored in the current object.
// But do not search in calls of regular parser rules, since parser rules create new objects.
if (ast.isRuleCall(currentNode) && ast.isParserRule(currentNode.rule.ref) && currentNode.rule.ref.fragment) {
this.checkNodeRegardingAssignmentNumbers(currentNode.rule.ref.definition, currentMultiplicity, map, accept); // TODO fragment rules are evaluated multiple times!
this.checkNodeRegardingAssignmentNumbers(currentNode.rule.ref.definition, currentMultiplicity, map, accept);
}

// rewriting actions are a special case for assignments
Expand All @@ -851,6 +850,7 @@ export class LangiumGrammarValidator {
if (ast.isGroup(currentNode) || ast.isUnorderedGroup(currentNode) || ast.isAlternatives(currentNode)) {
const mapAllAlternatives: Map<string, AssignmentUse> = new Map(); // store assignments for Alternatives separately
let nodesForNewObject: AstNode[] = [];
// check all elements inside the current group
for (const child of currentNode.elements) {
if (ast.isAction(child)) {
// Actions are a special case: a new object is created => following assignments are put into the new object
Expand Down Expand Up @@ -1120,7 +1120,15 @@ function findLookAheadGroup(rule: AstNode | undefined): ast.TerminalGroup | unde
}
}

/*
* Internal helper stuff for collecting information about assignments to features and their cardinalities
*/

interface AssignmentUse {
/**
* Collects assignments for the same feature, while an Action represents a "special assignment", when it is a rewrite action.
* The Set is used in order not to store the same assignment multiple times.
*/
assignments: Set<ast.Assignment | ast.Action>;
/**
* Note, that this number is not exact and "estimates the potential number",
Expand All @@ -1145,9 +1153,7 @@ function storeAssignmentUse(map: Map<string, AssignmentUse>, feature: string, in
}

function mergeAssignmentUse(mapSoure: Map<string, AssignmentUse>, mapTarget: Map<string, AssignmentUse>, counterOperation: (s: number, t: number) => number = (s, t) => s + t): void {
for (const sourceEntry of mapSoure.entries()) {
const key = sourceEntry[0];
const source = sourceEntry[1];
for (const [key, source] of mapSoure.entries()) {
const target = mapTarget.get(key);
if (target) {
source.assignments.forEach(a => target.assignments.add(a));
Expand Down
10 changes: 10 additions & 0 deletions packages/langium/test/grammar/grammar-validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,16 @@ describe('Assignments with = instead of +=', () => {
expect(validation.diagnostics.length).toBe(0);
});

test('no problem with actions: three assignments into three different objects', async () => {
const validation = await validate(getGrammar(`
entry Model infers Expression:
Person (operator=('+' | '-') right=Person {infer Model.left=current} right=Person {infer Model.left=current} right=Person)?;
Person infers Expression:
{infer Person} 'person' name=ID ;
`));
expect(validation.diagnostics.length).toBe(0);
});

test('actions: the rewrite part is a special assignment, which needs to be checked as well!', async () => {
const validation = await validate(getGrammar(`
entry Model infers Expression:
Expand Down

0 comments on commit a6ee465

Please sign in to comment.