Skip to content

Commit

Permalink
Infer optional properties for guarded groups (#1116)
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew committed Jul 19, 2023
1 parent 922d377 commit c28b8c5
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 6 deletions.
4 changes: 2 additions & 2 deletions packages/langium/src/grammar/internal-grammar-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import { escapeRegExp } from '../utils/regex-util';
export type Cardinality = '?' | '*' | '+' | undefined;
export type Operator = '=' | '+=' | '?=' | undefined;

export function isOptionalCardinality(cardinality?: Cardinality): boolean {
return cardinality === '?' || cardinality === '*';
export function isOptionalCardinality(cardinality?: Cardinality, element?: ast.AbstractElement): boolean {
return cardinality === '?' || cardinality === '*' || (ast.isGroup(element) && Boolean(element.guardCondition));
}

export function isArrayCardinality(cardinality?: Cardinality): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ function newTypePart(element?: ParserRule | Action | string): TypePart {
* @param element The given AST element, from which it's necessary to extract the type.
*/
function collectElement(graph: TypeGraph, current: TypePart, element: AbstractElement): TypePart {
const optional = isOptionalCardinality(element.cardinality);
const optional = isOptionalCardinality(element.cardinality, element);
if (isAlternatives(element)) {
const children: TypePart[] = [];
if (optional) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function findNextFeaturesInternal(options: { next: NextFeature, cardinalities: M
}
// Try to find the next elements of the parent
// Only do this if every following element is either optional or has been parsed as +
if (features.every(e => isOptionalCardinality(e.feature.cardinality) || isOptionalCardinality(cardinalities.get(e.feature)) || plus.has(e.feature))) {
if (features.every(e => isOptionalCardinality(e.feature.cardinality, e.feature) || isOptionalCardinality(cardinalities.get(e.feature)) || plus.has(e.feature))) {
features.push(...findNextFeaturesInternal({
next: {
feature: parent,
Expand Down Expand Up @@ -211,7 +211,7 @@ function findNextFeaturesInGroup(next: NextFeature<ast.Group>, index: number, ca
visited,
plus
}));
if (!isOptionalCardinality(firstFeature.feature.cardinality ?? cardinalities.get(firstFeature.feature))) {
if (!isOptionalCardinality(firstFeature.feature.cardinality ?? cardinalities.get(firstFeature.feature), firstFeature.feature)) {
break;
}
}
Expand Down Expand Up @@ -253,7 +253,7 @@ function interpretStackToken(stack: NextFeature[], token?: IToken): NextFeature[
for (const nextFeature of allNextFeatures) {
newStacks.push([...stack, nextFeature]);
}
if (!allNextFeatures.every(e => isOptionalCardinality(e.feature.cardinality) || isOptionalCardinality(cardinalities.get(e.feature)))) {
if (!allNextFeatures.every(e => isOptionalCardinality(e.feature.cardinality, e.feature) || isOptionalCardinality(cardinalities.get(e.feature)))) {
break;
}
}
Expand Down
13 changes: 13 additions & 0 deletions packages/langium/test/grammar/type-system/inferred-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ describe('Inferred types', () => {
`);
});

test('Should infer optional property for guarded group', async () => {
await expectTypes(`
A<G>: a=ID (<G> b=ID);
terminal ID returns string: /string/;
`, expandToString`
export interface A extends AstNode {
readonly $type: 'A';
a: string
b?: string
}
`);
});

test('Should correctly infer types using chained actions', async () => {
await expectTypes(`
A: a=ID ({infer B} b=ID ({infer C} c=ID)?)? d=ID;
Expand Down

0 comments on commit c28b8c5

Please sign in to comment.