eclipse / xtext

Eclipse Xtext™ is a language development framework
http://www.eclipse.org/Xtext
Eclipse Public License 2.0
766 stars 320 forks source link

Cannot use enum from base model for property of external model element #2433

Open dpetroff opened 2 years ago

dpetroff commented 2 years ago

Consider the following three grammars that generate ecore models:

An error Cannot find compatible feature property in sealed EClass ParentModel from imported package http://www.xtext.org/example/mydsl2/MyDsl2: The existing attribute 'property' has an incompatible type 'Property'. The expected type is 'Property'. prevents using the property from ParentModel in the ChildModel rule.

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
  greetings+=Greeting*;

Greeting:
  'Hello' name=ID '!';

enum Property:
  'ONE;
grammar org.xtext.example.mydsl2.MyDsl2 with org.xtext.example.mydsl.MyDsl

generate myDsl2 "http://www.xtext.org/example/mydsl2/MyDsl2"

ParentModel:
  property=Property;
grammar org.xtext.example.mydsl3.MyDsl3 with org.xtext.example.mydsl.MyDsl

generate myDsl3 "http://www.xtext.org/example/mydsl3/MyDsl3"
import "http://www.xtext.org/example/mydsl2/MyDsl2" as parent

ChildModel:
  ParentProperty;

fragment ParentProperty returns parent::ParentModel:
  property=Property; // Error here.

Note that the fragment rule was used to avoid the Generated package 'myDsl3' may not be empty error and is not necessary to trigger the issue:

ChildModel returns parent::ParentModel:
  property=Property; // Error here as well.

In this case there is no subclass at all, yet the error persists, even if the generate directive was removed from the grammar entirely.

Attached gradle setup reproducing the issue: org.xtext.example.mydsl.parent.zip

cdietrich commented 2 years ago

@szarnekow any idea?

szarnekow commented 2 years ago

I think it's related to the fact that each language "links" its parent language again when it's being processed. EClassifierInfo.EClassInfo.containsCompatibleFeature(String, boolean, boolean, EClassifier, StringBuilder) might need special handling similar to what is done for EClasses since EEnum might be inferred (contrary to EDataType in general)

cdietrich commented 2 years ago

yes the parent package and enum seems to be loaded twice funnily it seems to work when i put all grammars in one project and run this workflow

module org.xtext.example.mydsl.GenerateMyDsl

import org.eclipse.xtext.xtext.generator.*
import org.eclipse.xtext.xtext.generator.model.project.*

var rootPath = ".."

Workflow {

    component = XtextGenerator {
        configuration = {
            project = StandardProjectConfig {
                baseName = "org.xtext.example.mydsl"
                rootPath = rootPath
                runtimeTest = {
                    enabled = true
                }
                eclipsePlugin = {
                    enabled = true
                }
                eclipsePluginTest = {
                    enabled = true
                }
                createEclipseMetaData = true
            }
            code = {
                encoding = "UTF-8"
                lineDelimiter = "\n"
                fileHeader = "/*\n * generated by Xtext \${version}\n */"
                preferXtendStubs = false
            }
        }
        language = StandardLanguage {
            name = "org.xtext.example.mydsl.MyDsl"
            fileExtensions = "mydsl"
            serializer = {
                generateStub = false
            }
            validator = {
            // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
            // Generates checks for @Deprecated grammar annotations, an IssueProvider and a corresponding PropertyPage
                generateDeprecationValidation = true
            }
            generator = {
                generateXtendStub = true
            }
            junitSupport = {
                junitVersion = "5"
            }
        }
        language = StandardLanguage {
            name = "org.xtext.example.mydsl.MyDsl2"
            fileExtensions = "mydsl2"
            referencedResource = "platform:/resource/org.xtext.example.mydsl/src/org/xtext/example/mydsl/MyDsl.xtext"
            serializer = {
                generateStub = false
            }
            validator = {
            // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
            // Generates checks for @Deprecated grammar annotations, an IssueProvider and a corresponding PropertyPage
                generateDeprecationValidation = true
            }
            generator = {
                generateXtendStub = true
            }
            junitSupport = {
                junitVersion = "5"
            }
        }
        language = StandardLanguage {
            name = "org.xtext.example.mydsl.MyDsl3"
            fileExtensions = "mydsl3"
            referencedResource = "platform:/resource/org.xtext.example.mydsl/src/org/xtext/example/mydsl/MyDsl.xtext"
            referencedResource = "platform:/resource/org.xtext.example.mydsl/src/org/xtext/example/mydsl/MyDsl2.xtext"
            serializer = {
                generateStub = false
            }
            validator = {
            // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
            // Generates checks for @Deprecated grammar annotations, an IssueProvider and a corresponding PropertyPage
                generateDeprecationValidation = true
            }
            generator = {
                generateXtendStub = true
            }
            junitSupport = {
                junitVersion = "5"
            }
        }
    }
}
szarnekow commented 2 years ago

run this workflow

In that case, it'll work since the super grammar is only processed once per resource set.