TypeFox / xtext2langium

A tool for migrating an Xtext language to Langium
https://www.typefox.io/blog/xtext-to-langium
MIT License
7 stars 1 forks source link

Enumerations in dependent types file duplicate types in grammar file #5

Closed steve-hickman-epistimis closed 1 year ago

steve-hickman-epistimis commented 1 year ago

I have several XText grammars with dependencies as follows:

grammar com.epistimis.privacy.Privacy with com.epistimis.face.Face
grammar com.epistimis.face.Face with com.epistimis.uddl.Uddl
grammar com.epistimis.uddl.Uddl with org.eclipse.xtext.common.Terminals

When I generate from the Privacy grammar, I get the following files:

Privacy.langium
Face.langium
Face-types.langium
Uddl.langium
Uddl-types.langium
Terminals.langium

Face.xtext contains the following:

enum UoPClientServerRole:
    CLIENT='client' | SERVER='server'
;

enum UopFaceProfile:
    GENERAL_PURPOSE = 'GeneralPurpose' |
    SECURITY = 'Security' |
    SAFETY_BASE = 'SafetyBase' |
    SAFETY_EXTENDED = 'SafetyExtended'
;

enum UopDesignAssuranceLevel:
    A='a' | B='b' | C='c' | D='d' | E='e'
;

enum UopDesignAssuranceStandard:
    DO_178B_ED_12B='DO_178B_ED_12B' |
    DO_178C_ED_12C='DO_178C_ED_12C'
;

enum UopMessageExchangeType:
    INBOUND_MESSAGE='InboundMessage' |
    OUTBOUND_MESSAGE='OutboundMessage'
;

enum UopPartitionType:
    POSIX='POSIX' | ARINC653='ARINC653'
;

enum UopProgrammingLanguage:
    C='C' | CPP='cpp' | JAVA='Java' | ADA='Ada' 
    // EXTENSION: Additional languages not supported by FACE
    | GO='Go' | JS='Javascript' | PYTHON='Python' | RUST = 'Rust' | SQL='SQL'
;

enum UopSynchronizationStyle:
    BLOCKING='Blocking' | NON_BLOCKING='NonBlocking'
;

enum UopThreadType:
    FOREGROUND='Foreground'| BACKGROUND='Background'
;

Face.langium contains:

type UoPClientServerRole = 'client' | 'server';
UoPClientServerRole returns UoPClientServerRole:
    UoPClientServerRole_CLIENT | UoPClientServerRole_SERVER
;
UoPClientServerRole_CLIENT returns string: 'client' ;
UoPClientServerRole_SERVER returns string: 'server' ;

type UopFaceProfile = 'GeneralPurpose' | 'Security' | 'SafetyBase' | 'SafetyExtended';
UopFaceProfile returns UopFaceProfile:
    UopFaceProfile_GENERAL_PURPOSE | UopFaceProfile_SECURITY | UopFaceProfile_SAFETY_BASE | UopFaceProfile_SAFETY_EXTENDED
;
UopFaceProfile_GENERAL_PURPOSE returns string: 'GeneralPurpose' ;
UopFaceProfile_SECURITY returns string: 'Security' ;
UopFaceProfile_SAFETY_BASE returns string: 'SafetyBase' ;
UopFaceProfile_SAFETY_EXTENDED returns string: 'SafetyExtended' ;

type UopDesignAssuranceLevel = 'a' | 'b' | 'c' | 'd' | 'e';
UopDesignAssuranceLevel returns UopDesignAssuranceLevel:
    UopDesignAssuranceLevel_A | UopDesignAssuranceLevel_B | UopDesignAssuranceLevel_C | UopDesignAssuranceLevel_D | UopDesignAssuranceLevel_E
;
UopDesignAssuranceLevel_A returns string: 'a' ;
UopDesignAssuranceLevel_B returns string: 'b' ;
UopDesignAssuranceLevel_C returns string: 'c' ;
UopDesignAssuranceLevel_D returns string: 'd' ;
UopDesignAssuranceLevel_E returns string: 'e' ;

type UopDesignAssuranceStandard = 'DO_178B_ED_12B' | 'DO_178C_ED_12C';
UopDesignAssuranceStandard returns UopDesignAssuranceStandard:
    UopDesignAssuranceStandard_DO_178B_ED_12B | UopDesignAssuranceStandard_DO_178C_ED_12C
;
UopDesignAssuranceStandard_DO_178B_ED_12B returns string: 'DO_178B_ED_12B' ;
UopDesignAssuranceStandard_DO_178C_ED_12C returns string: 'DO_178C_ED_12C' ;

type UopMessageExchangeType = 'InboundMessage' | 'OutboundMessage';
UopMessageExchangeType returns UopMessageExchangeType:
    UopMessageExchangeType_INBOUND_MESSAGE | UopMessageExchangeType_OUTBOUND_MESSAGE
;
UopMessageExchangeType_INBOUND_MESSAGE returns string: 'InboundMessage' ;
UopMessageExchangeType_OUTBOUND_MESSAGE returns string: 'OutboundMessage' ;

type UopPartitionType = 'POSIX' | 'ARINC653';
UopPartitionType returns UopPartitionType:
    UopPartitionType_POSIX | UopPartitionType_ARINC653
;
UopPartitionType_POSIX returns string: 'POSIX' ;
UopPartitionType_ARINC653 returns string: 'ARINC653' ;

type UopProgrammingLanguage = 'C' | 'cpp' | 'Java' | 'Ada' | 'Go' | 'Javascript' | 'Python' | 'Rust' | 'SQL';
UopProgrammingLanguage returns UopProgrammingLanguage:
    UopProgrammingLanguage_C | UopProgrammingLanguage_CPP | UopProgrammingLanguage_JAVA | UopProgrammingLanguage_ADA | UopProgrammingLanguage_GO | UopProgrammingLanguage_JS | UopProgrammingLanguage_PYTHON | UopProgrammingLanguage_RUST | UopProgrammingLanguage_SQL
;
UopProgrammingLanguage_C returns string: 'C' ;
UopProgrammingLanguage_CPP returns string: 'cpp' ;
UopProgrammingLanguage_JAVA returns string: 'Java' ;
UopProgrammingLanguage_ADA returns string: 'Ada' ;
UopProgrammingLanguage_GO returns string: 'Go' ;
UopProgrammingLanguage_JS returns string: 'Javascript' ;
UopProgrammingLanguage_PYTHON returns string: 'Python' ;
UopProgrammingLanguage_RUST returns string: 'Rust' ;
UopProgrammingLanguage_SQL returns string: 'SQL' ;

type UopSynchronizationStyle = 'Blocking' | 'NonBlocking';
UopSynchronizationStyle returns UopSynchronizationStyle:
    UopSynchronizationStyle_BLOCKING | UopSynchronizationStyle_NON_BLOCKING
;
UopSynchronizationStyle_BLOCKING returns string: 'Blocking' ;
UopSynchronizationStyle_NON_BLOCKING returns string: 'NonBlocking' ;

type UopThreadType = 'Foreground' | 'Background';
UopThreadType returns UopThreadType:
    UopThreadType_FOREGROUND | UopThreadType_BACKGROUND
;
UopThreadType_FOREGROUND returns string: 'Foreground' ;
UopThreadType_BACKGROUND returns string: 'Background' ;

Face-types.langium contains

type UopProgrammingLanguage = UopProgrammingLanguage_C | UopProgrammingLanguage_CPP | UopProgrammingLanguage_JAVA | UopProgrammingLanguage_ADA | UopProgrammingLanguage_GO | UopProgrammingLanguage_JS | UopProgrammingLanguage_PYTHON | UopProgrammingLanguage_RUST | UopProgrammingLanguage_SQL;
type UopProgrammingLanguage_C = 'C';
type UopProgrammingLanguage_CPP = 'cpp';
type UopProgrammingLanguage_JAVA = 'Java';
type UopProgrammingLanguage_ADA = 'Ada';
type UopProgrammingLanguage_GO = 'Go';
type UopProgrammingLanguage_JS = 'Javascript';
type UopProgrammingLanguage_PYTHON = 'Python';
type UopProgrammingLanguage_RUST = 'Rust';
type UopProgrammingLanguage_SQL = 'SQL';

type UopPartitionType = UopPartitionType_POSIX | UopPartitionType_ARINC653;
type UopPartitionType_POSIX = 'POSIX';
type UopPartitionType_ARINC653 = 'ARINC653';

type UopFaceProfile = UopFaceProfile_GENERAL_PURPOSE | UopFaceProfile_SECURITY | UopFaceProfile_SAFETY_BASE | UopFaceProfile_SAFETY_EXTENDED;
type UopFaceProfile_GENERAL_PURPOSE = 'GeneralPurpose';
type UopFaceProfile_SECURITY = 'Security';
type UopFaceProfile_SAFETY_BASE = 'SafetyBase';
type UopFaceProfile_SAFETY_EXTENDED = 'SafetyExtended';

type UopDesignAssuranceLevel = UopDesignAssuranceLevel_A | UopDesignAssuranceLevel_B | UopDesignAssuranceLevel_C | UopDesignAssuranceLevel_D | UopDesignAssuranceLevel_E;
type UopDesignAssuranceLevel_A = 'a';
type UopDesignAssuranceLevel_B = 'b';
type UopDesignAssuranceLevel_C = 'c';
type UopDesignAssuranceLevel_D = 'd';
type UopDesignAssuranceLevel_E = 'e';

type UopDesignAssuranceStandard = UopDesignAssuranceStandard_DO_178B_ED_12B | UopDesignAssuranceStandard_DO_178C_ED_12C;
type UopDesignAssuranceStandard_DO_178B_ED_12B = 'DO_178B_ED_12B';
type UopDesignAssuranceStandard_DO_178C_ED_12C = 'DO_178C_ED_12C';

type UopThreadType = UopThreadType_FOREGROUND | UopThreadType_BACKGROUND;
type UopThreadType_FOREGROUND = 'Foreground';
type UopThreadType_BACKGROUND = 'Background';

type UopSynchronizationStyle = UopSynchronizationStyle_BLOCKING | UopSynchronizationStyle_NON_BLOCKING;
type UopSynchronizationStyle_BLOCKING = 'Blocking';
type UopSynchronizationStyle_NON_BLOCKING = 'NonBlocking';

type UopMessageExchangeType = UopMessageExchangeType_INBOUND_MESSAGE | UopMessageExchangeType_OUTBOUND_MESSAGE;
type UopMessageExchangeType_INBOUND_MESSAGE = 'InboundMessage';
type UopMessageExchangeType_OUTBOUND_MESSAGE = 'OutboundMessage';

Note the duplicated type definitions for the enums. In Face.langium, the type is defined using the literal string values as alternatives. In Face-types.langium, the type is defined using the value types as alternatives. At best, this seems like duplication. It could also be the cause of the following errors (this example from the UopClientServerRole rule in Face.langium):

This rule is declared but never referenced.langium
This parser rule does not create an object. Add a primitive return type or an action to the start of the rule to force object instantiation.langium
A type 'UoPClientServerRole' is not expected in a rule that returns type 'UoPClientServerRole'.

Note that I can't add a return type defined in Face-types.langium to Face.langium without importing Face-types.langium into Face.langium. Doing that will transitively import Uddl-types.langium into Face.langium which results in the problem described in issue #3

dhuebner commented 1 year ago

@steve-hickman-epistimis Thank you for the detailed report!

In Face-types.langium, the type is defined using the value types as alternatives. At best, this seems like duplication.

Maybe it was a copy-paste error, but I can't find UopClientServerRole in Face-types.langium

This parser rule does not create an object. Add a primitive return type or an action to the start of the rule to force object instantiation.langium

This is a known bug in Langium validation. Should be fixed soon.

A type 'UoPClientServerRole' is not expected in a rule that returns type 'UoPClientServerRole'.

This is also a Langium TypeSystem issue.

I will keep this issue open to verify errors are fixed after the upcoming release.

steve-hickman-epistimis commented 1 year ago

Maybe it was a copy-paste error, but I can't find UopClientServerRole in Face-types.langium

Very observant. I'm looking at the just regenerated file - it's not there. I wonder why that particular enum was not duplicated? Is there something unique about it being the first enum in the XText grammar?

dhuebner commented 1 year ago

Validation issues mentioned here are no longer reported in the current 2.0.1 Langium release

dhuebner commented 1 year ago

I can't reproduce your issue with the current state of your project when generating the FACE language. Also I can not access https://github.com/Epistimis/Privacy repository.

steve-hickman-epistimis commented 1 year ago

It appears that the current version of xtext2langium no longer generates the '-types.langium' files - so, yes, this appears to be resolved.

dhuebner commented 1 year ago

@steve-hickman-epistimis The initial idea was to generate -types.langium if one explicitly uses a predefined metamodel (e.g. xcore). In your case, where you are using generated EMF, it is not needed as types can be inferred by the Langium framework.