From 02b3bb9b7856f5e308b3ff1f92ec3059c1ac672b Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Tue, 15 Aug 2023 17:11:49 +0200 Subject: [PATCH] add implicit ID rule call for cross refs to getAllReachableRules Fixes #1151 Signed-off-by: Christian Dietrich --- packages/langium/src/utils/grammar-util.ts | 6 ++- .../langium/test/utils/grammar-util.test.ts | 42 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/langium/src/utils/grammar-util.ts b/packages/langium/src/utils/grammar-util.ts index ef018bfc0..c41ef0ac7 100644 --- a/packages/langium/src/utils/grammar-util.ts +++ b/packages/langium/src/utils/grammar-util.ts @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2021-2022 TypeFox GmbH + * Copyright 2021-2023 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. ******************************************************************************/ @@ -75,6 +75,10 @@ function ruleDfs(rule: ast.AbstractRule, visitedSet: Set, allTerminals: if (refRule && !visitedSet.has(refRule.name)) { ruleDfs(refRule, visitedSet, allTerminals); } + } else if (ast.isCrossReference(node)) { + if (node.terminal === undefined) { + visitedSet.add("ID") + } } }); } diff --git a/packages/langium/test/utils/grammar-util.test.ts b/packages/langium/test/utils/grammar-util.test.ts index 5a4b7b46c..f75a4683d 100644 --- a/packages/langium/test/utils/grammar-util.test.ts +++ b/packages/langium/test/utils/grammar-util.test.ts @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2022 TypeFox GmbH + * Copyright 2022-2023 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. ******************************************************************************/ @@ -36,4 +36,44 @@ describe('Grammar Utils', () => { expect(reachableRules).toContain('Ws'); }); + test('ID implicit called should be returned by getAllReachableRules', async () => { + // [A] is short for [A:ID] thus the ID rule is needed by the parser and getAllReachableRules should return ID + const input = ` + grammar HelloWorld + + entry Model: A|B; + A: name=STRING; + B: ref=[A]; + terminal ID: /[_a-zA-Z][\w_]*/; + terminal STRING: /"(\\.|[^"\\])*"|'(\\.|[^'\\])*'/; + `; + const output = await parse(input); + + // act + const reachableRules = [...getAllReachableRules(output.parseResult.value, true)].map(r => r.name); + + // assert + expect(reachableRules).toContain('ID'); + }); + + test('ID not implicit called should not be returned by getAllReachableRules', async () => { + // no implicit ID rule call in cross ref + const input = ` + grammar HelloWorld + + entry Model: A|B; + A: name=STRING; + B: ref=[A:STRING]; + terminal ID: /[_a-zA-Z][\w_]*/; + terminal STRING: /"(\\.|[^"\\])*"|'(\\.|[^'\\])*'/; + `; + const output = await parse(input); + + // act + const reachableRules = [...getAllReachableRules(output.parseResult.value, true)].map(r => r.name); + + // assert + expect(reachableRules).not.toContain('ID'); + }); + });