Skip to content

Commit 301cf90

Browse files
authored
fix generation issue on AST getReferenceType (#1861)
1 parent 72689f0 commit 301cf90

File tree

2 files changed

+62
-7
lines changed

2 files changed

+62
-7
lines changed

packages/langium-cli/src/generator/ast-generator.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,20 @@ function buildCrossReferenceTypes(astTypes: AstTypes): CrossReferenceType[] {
176176
});
177177
}
178178
}
179-
// Since the types are topologically sorted we can assume
180-
// that all super type properties have already been processed
179+
}
180+
181+
for (const typeInterface of astTypes.interfaces) {
182+
const superFeatures = new Set<string>();
181183
for (const superType of typeInterface.interfaceSuperTypes) {
182-
const superTypeCrossReferences = crossReferences.get(superType.name).map(e => ({
183-
...e,
184-
type: typeInterface.name
185-
}));
186-
crossReferences.addAll(typeInterface.name, superTypeCrossReferences);
184+
for (const superTypeCrossReference of crossReferences.get(superType.name)) {
185+
if (!superFeatures.has(superTypeCrossReference.feature)) {
186+
crossReferences.add(typeInterface.name, { ...superTypeCrossReference, type: typeInterface.name });
187+
superFeatures.add(superTypeCrossReference.feature);
188+
}
189+
}
187190
}
188191
}
192+
189193
return Array.from(crossReferences.values()).sort((a, b) => a.type.localeCompare(b.type));
190194
}
191195

packages/langium-cli/test/generator/ast-generator.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,54 @@ describe('Ast generator', () => {
438438
}
439439
}`
440440
);
441+
442+
testReferenceType('check all referenceIds are properly generated', `
443+
grammar TestGrammar
444+
445+
interface A {
446+
refA1: @A
447+
refB1: @B
448+
}
449+
interface B extends A {
450+
refB2: @B
451+
}
452+
interface C extends A, B {
453+
refC1: @C
454+
}
455+
interface D extends A, B {
456+
refD1: @D
457+
}
458+
`, expandToString`
459+
getReferenceType(refInfo: langium.ReferenceInfo): string {
460+
const referenceId = \`\${refInfo.container.$type}:\${refInfo.property}\`;
461+
switch (referenceId) {
462+
case 'A:refA1':
463+
case 'B:refA1':
464+
case 'C:refA1':
465+
case 'D:refA1': {
466+
return A;
467+
}
468+
case 'A:refB1':
469+
case 'B:refB2':
470+
case 'B:refB1':
471+
case 'C:refB1':
472+
case 'C:refB2':
473+
case 'D:refB1':
474+
case 'D:refB2': {
475+
return B;
476+
}
477+
case 'C:refC1': {
478+
return C;
479+
}
480+
case 'D:refD1': {
481+
return D;
482+
}
483+
default: {
484+
throw new Error(\`\${referenceId} is not a valid reference id.\`);
485+
}
486+
}
487+
}`
488+
);
441489
});
442490

443491
async function testTerminalConstants(grammar: string, expected: string) {
@@ -468,6 +516,9 @@ function testTypeMetaData(name: string, grammar: string, expected: string): void
468516
testGenerated(name, grammar, expected, 'getTypeMetaData', 'export const reflection');
469517
}
470518

519+
function testReferenceType(name: string, grammar: string, expected: string): void {
520+
testGenerated(name, grammar, expected, 'getReferenceType', 'getTypeMetaData');
521+
}
471522
function testGenerated(name: string, grammar: string, expected: string, start: string, end: string, startCount = 0): void {
472523
test(name, async () => {
473524
const result = (await parse(grammar)).parseResult;

0 commit comments

Comments
 (0)