eclipse-langium / langium

Next-gen language engineering / DSL framework
https://langium.org/
MIT License
750 stars 68 forks source link

Make the `$container` type more precise in case of guard conditions #1300

Open JohannesMeierSE opened 1 year ago

JohannesMeierSE commented 1 year ago

The following simple and artificial example uses guard conditions in order to switch between different cases (excerpt):

Teacher:
    'teacher' name=ID values=Reused<true>;

Student:
    'student' name=ID values=Reused<false>;

Reused<condition>:
    <!condition> OneValue | <condition> TwoValues;

OneValue:
    'values' value=ID;
TwoValues:
    'values' valueOne=ID valueTwo=ID;

(The whole grammar with an instance can be found in the playground.)

For this grammar, Langium generates the following types in the ast.ts (excerpt):

export type Reused = OneValue | TwoValues;

export interface OneValue extends AstNode {
    readonly $container: Student | Teacher;
    readonly $type: 'OneValue';
    value: string
}

export interface TwoValues extends AstNode {
    readonly $container: Student | Teacher;
    readonly $type: 'TwoValues';
    valueOne: string
    valueTwo: string
}

From my point of view, the types of the $container properties could be more precise, i.e. only Student for OneValue and only Teacher for TwoValues. The current $container types are not wrong, but as a user of Langium, I would expect the following types, since the grammar clearly shows, that these types are enough:

export type Reused = OneValue | TwoValues;

export interface OneValue extends AstNode {
    readonly $container: Student;
    readonly $type: 'OneValue';
    value: string
}

export interface TwoValues extends AstNode {
    readonly $container: Teacher;
    readonly $type: 'TwoValues';
    valueOne: string
    valueTwo: string
}
JohannesMeierSE commented 1 year ago

If you think this issue is worth an improvement, I am willing to work on this issue!

spoenemann commented 1 year ago

Yes for such clear cases it would make sense to restrict the container type.