From dc1298b7055d514f8428614960b585bc90ffd05f Mon Sep 17 00:00:00 2001 From: jkohnlein Date: Mon, 22 Sep 2008 12:21:15 +0000 Subject: [PATCH] Next patch from Heiko See https://bugs.eclipse.org/bugs/show_bug.cgi?id=247406 --- .../src/org/eclipse/xtext/GrammarUtil.java | 12 ++ .../resource/metamodel/EClassifierInfo.java | 39 ++--- .../metamodel/Xtext2EcoreTransformer.java | 148 +++++++++--------- 3 files changed, 109 insertions(+), 90 deletions(-) diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/GrammarUtil.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/GrammarUtil.java index 43e082139..2ee4de2b5 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/GrammarUtil.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/GrammarUtil.java @@ -292,6 +292,18 @@ public class GrammarUtil { } return kws; } + + public static boolean isBooleanAssignment(Assignment a) { + return "?=".equals(a.getOperator()); + } + + public static boolean isSingleAssignment(Assignment a) { + return "=".equals(a.getOperator()); + } + + public static boolean isMultipleAssignment(Assignment a) { + return "+=".equals(a.getOperator()); + } public static boolean isOptionalCardinality(AbstractElement e) { return e.getCardinality() != null && (e.getCardinality().equals("?") || e.getCardinality().equals("*")); diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/EClassifierInfo.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/EClassifierInfo.java index 52d964641..f39a1b78d 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/EClassifierInfo.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/EClassifierInfo.java @@ -27,13 +27,13 @@ public abstract class EClassifierInfo { private EClassifier eClassifier; private boolean isGenerated; - + private EClassifierInfo(EClassifier metaType, boolean isGenerated) { super(); this.isGenerated = isGenerated; this.eClassifier = metaType; } - + public static EClassifierInfo createEClassInfo(EClass eClass, boolean isGenerated) { return new EClassInfo(eClass, isGenerated); } @@ -51,8 +51,9 @@ public abstract class EClassifierInfo { } public abstract boolean addSupertype(EClassifierInfo superTypeInfo); - public abstract boolean addFeature(String featureName, EClassifierInfo featureType); - + + public abstract boolean addFeature(String featureName, EClassifierInfo featureType, boolean isMultivalue); + static class EClassInfo extends EClassifierInfo { public EClassInfo(EClassifier metaType, boolean isGenerated) { @@ -61,32 +62,33 @@ public abstract class EClassifierInfo { @Override public boolean addSupertype(EClassifierInfo superTypeInfo) { - if(!isGenerated()){ + if (!isGenerated()) { throw new IllegalStateException("Generated Type cannot be modified."); } - if(!(superTypeInfo instanceof EClassInfo)) { + if (!(superTypeInfo instanceof EClassInfo)) { throw new IllegalArgumentException("superTypeInfo must represent EClass"); } - EClass eClass = (EClass)getEClass(); - EClass superEClass = (EClass)superTypeInfo.getEClass(); + EClass eClass = (EClass) getEClass(); + EClass superEClass = (EClass) superTypeInfo.getEClass(); return eClass.getESuperTypes().add(superEClass); } @Override - public boolean addFeature(String featureName, - EClassifierInfo featureType) { + public boolean addFeature(String featureName, EClassifierInfo featureType, boolean isMultivalue) { - EClassifier featureClassifier = featureType.getEClass(); - - EAttribute attribute = EcoreFactory.eINSTANCE.createEAttribute(); + EClassifier featureClassifier = featureType.getEClass(); + + EAttribute attribute = EcoreFactory.eINSTANCE.createEAttribute(); attribute.setName(featureName); attribute.setEType(featureClassifier); - - EList features = ((EClass)getEClass()).getEStructuralFeatures(); + attribute.setLowerBound(0); + attribute.setUpperBound(isMultivalue ? -1 : 1); + + EList features = ((EClass) getEClass()).getEStructuralFeatures(); return features.add(attribute); } } - + static class EDataTypeInfo extends EClassifierInfo { public EDataTypeInfo(EClassifier metaType, boolean isGenerated) { @@ -99,10 +101,9 @@ public abstract class EClassifierInfo { } @Override - public boolean addFeature(String featureName, - EClassifierInfo featureType) { + public boolean addFeature(String featureName, EClassifierInfo featureType, boolean isMultivalue) { throw new UnsupportedOperationException("Cannot add feature to simple datatype"); } - + } } diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/Xtext2EcoreTransformer.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/Xtext2EcoreTransformer.java index bd816a980..75e40c7bc 100644 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/Xtext2EcoreTransformer.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/resource/metamodel/Xtext2EcoreTransformer.java @@ -75,10 +75,10 @@ public class Xtext2EcoreTransformer { EClassifierInfo generatedEClass = findOrCreateEClass(rule); if (rule instanceof ParserRule) { ParserRule parserRule = (ParserRule) rule; - deriveTypesAndHierarchy(generatedEClass, parserRule - .getAlternatives()); + deriveTypesAndHierarchy(generatedEClass, parserRule.getAlternatives()); } - } catch (TransformationException e) { + } + catch (TransformationException e) { reportError(e.getMessage(), e.getErroneousElement()); } } @@ -93,7 +93,8 @@ public class Xtext2EcoreTransformer { if (rule instanceof ParserRule) { this.deriveFeatures((ParserRule) rule); } - } catch (TransformationException e) { + } + catch (TransformationException e) { reportError(e.getMessage(), e.getErroneousElement()); } } @@ -117,22 +118,29 @@ public class Xtext2EcoreTransformer { this.getEClassifierInfos().addAll(transformer.getEClassifierInfos()); } - private InterpretationContext deriveFeatures(InterpretationContext context, - AbstractElement element) throws TransformationException { + private InterpretationContext deriveFeatures(InterpretationContext context, AbstractElement element) + throws TransformationException { if (element instanceof Assignment) { Assignment assignment = (Assignment) element; context.addFeature(assignment); - } else if (element instanceof Group) { + } + else if (element instanceof Group) { Group group = (Group) element; return deriveFeatures(context, group.getAbstractTokens()); } + else if (element instanceof RuleCall && !GrammarUtil.isOptionalCardinality(element)) { + RuleCall ruleCall = (RuleCall) element; + AbstractRule calledRule = GrammarUtil.findRuleForName(grammar, ruleCall.getName()); + context = context.clone(); + context.currentType = findOrCreateEClass(calledRule); + } return context; } - private InterpretationContext deriveFeatures(InterpretationContext context, - EList elements) throws TransformationException { - for(AbstractElement element : elements) { + private InterpretationContext deriveFeatures(InterpretationContext context, EList elements) + throws TransformationException { + for (AbstractElement element : elements) { context = deriveFeatures(context, element); } return context; @@ -141,8 +149,7 @@ public class Xtext2EcoreTransformer { private void deriveFeatures(ParserRule rule) throws TransformationException { EClassifierInfo classInfo = findOrCreateEClass(rule); boolean isGenerated = classInfo.isGenerated(); - InterpretationContext context = new InterpretationContext(classInfo, - isGenerated, true); + InterpretationContext context = new InterpretationContext(classInfo, isGenerated, true); deriveFeatures(context, rule.getAlternatives()); } @@ -164,72 +171,80 @@ public class Xtext2EcoreTransformer { * @param alternatives * @throws TransformationException */ - private void deriveTypesAndHierarchy(EClassifierInfo ruleReturnType, - AbstractElement element) throws TransformationException { + private void deriveTypesAndHierarchy(EClassifierInfo ruleReturnType, AbstractElement element) + throws TransformationException { if (element instanceof RuleCall) { RuleCall ruleCall = (RuleCall) element; AbstractRule calledRule = GrammarUtil.calledRule(ruleCall); TypeRef calledRuleReturnTypeRef = getOrFakeReturnType(calledRule); addSuperType(calledRuleReturnTypeRef, ruleReturnType); - } else if (element instanceof Action) { + } + else if (element instanceof Action) { Action action = (Action) element; TypeRef actionTypeRef = action.getTypeName(); addSuperType(actionTypeRef, ruleReturnType); - } else if (element instanceof Group) { + } + else if (element instanceof Group) { Group group = (Group) element; deriveTypesAndHierarchy(ruleReturnType, group.getAbstractTokens()); - } else if (element instanceof Alternatives) { + } + else if (element instanceof Alternatives) { Alternatives alternatives = (Alternatives) element; deriveTypesAndHierarchy(ruleReturnType, alternatives.getGroups()); } } - private void deriveTypesAndHierarchy(EClassifierInfo ruleReturnType, - List elements) throws TransformationException { + private void deriveTypesAndHierarchy(EClassifierInfo ruleReturnType, List elements) + throws TransformationException { for (AbstractElement element : elements) { deriveTypesAndHierarchy(ruleReturnType, element); } } - private void addSuperType(TypeRef subTypeRef, EClassifierInfo superType) - throws TransformationException { + private void addSuperType(TypeRef subTypeRef, EClassifierInfo superType) throws TransformationException { EClassifierInfo calledRuleReturnType = findOrCreateEClass(subTypeRef); calledRuleReturnType.addSupertype(superType); } class InterpretationContext { - public InterpretationContext(EClassifierInfo currentType, - boolean isGeneratedType, boolean isRuleCallAllowed) { + public InterpretationContext(EClassifierInfo currentType, boolean isGeneratedType, boolean isRuleCallAllowed) { super(); this.currentType = currentType; this.isGeneratedType = isGeneratedType; this.isRuleCallAllowed = isRuleCallAllowed; } - public void addFeature(Assignment assignment) - throws TransformationException { + public void addFeature(Assignment assignment) throws TransformationException { String featureName = assignment.getFeature(); - RuleCall featureRuleCall = (RuleCall) assignment.getTerminal(); - AbstractRule featureTypeRule = GrammarUtil - .calledRule(featureRuleCall); - String featureTypeName = GrammarUtil - .getReturnTypeName(featureTypeRule); - EClassifierInfo featureTypeInfo = eClassifierInfos - .getInfo(featureTypeName); - if (featureTypeInfo == null) { - throw new TransformationException( - "Cannot resolve type of feature", assignment); + boolean isMultivalue = GrammarUtil.isMultipleAssignment(assignment); + EClassifierInfo featureTypeInfo; + + if (GrammarUtil.isBooleanAssignment(assignment)) { + featureTypeInfo = getEClassifierInfoOrThrowException("ecore::EBoolean", assignment); + isMultivalue = false; + } + else { + RuleCall featureRuleCall = (RuleCall) assignment.getTerminal(); + AbstractRule featureTypeRule = GrammarUtil.calledRule(featureRuleCall); + String featureTypeName = GrammarUtil.getReturnTypeName(featureTypeRule); + featureTypeInfo = getEClassifierInfoOrThrowException(featureTypeName, assignment); + } - currentType.addFeature(featureName, featureTypeInfo); + currentType.addFeature(featureName, featureTypeInfo, isMultivalue); + } - // TODO : fill Cardinality of attribute - // this.currentType.getEStructuralFeatures().add(attribute); + private EClassifierInfo getEClassifierInfoOrThrowException(String typeName, AbstractElement parserElement) + throws TransformationException { + EClassifierInfo featureTypeInfo = eClassifierInfos.getInfo(typeName); + if (featureTypeInfo == null) { + throw new TransformationException("Cannot resolve type " + typeName, parserElement); + } + return featureTypeInfo; } public InterpretationContext clone() { - return new InterpretationContext(currentType, isGeneratedType, - isRuleCallAllowed); + return new InterpretationContext(currentType, isGeneratedType, isRuleCallAllowed); } // TODO : Use set of types to reflect mandatory actions @@ -239,36 +254,33 @@ public class Xtext2EcoreTransformer { } private void collectEPackages() { - EList metamodelDeclarations = grammar - .getMetamodelDeclarations(); + EList metamodelDeclarations = grammar.getMetamodelDeclarations(); for (AbstractMetamodelDeclaration metamodelDeclaration : metamodelDeclarations) { if (metamodelDeclaration instanceof ReferencedMetamodel) { // load imported metamodel ReferencedMetamodel referencedMetamodel = (ReferencedMetamodel) metamodelDeclaration; - EPackage referencedEPackage = GrammarUtil - .loadEPackage(referencedMetamodel); + EPackage referencedEPackage = GrammarUtil.loadEPackage(referencedMetamodel); if (referencedEPackage == null) { - reportError("Cannot not load metamodel " - + referencedMetamodel.getUri(), referencedMetamodel); - } else { + reportError("Cannot not load metamodel " + referencedMetamodel.getUri(), referencedMetamodel); + } + else { String alias = referencedMetamodel.getAlias(); if (Strings.isEmpty(alias)) { - reportError("Referenced metamodels must have an alias", - referencedMetamodel); - } else { + reportError("Referenced metamodels must have an alias", referencedMetamodel); + } + else { collectClassInfosOf(referencedEPackage, alias); } } - } else if (metamodelDeclaration instanceof GeneratedMetamodel) { + } + else if (metamodelDeclaration instanceof GeneratedMetamodel) { // instantiate EPackages for generated metamodel GeneratedMetamodel generatedMetamodel = (GeneratedMetamodel) metamodelDeclaration; - EPackage generatedEPackage = EcoreFactory.eINSTANCE - .createEPackage(); + EPackage generatedEPackage = EcoreFactory.eINSTANCE.createEPackage(); generatedEPackage.setName(generatedMetamodel.getName()); generatedEPackage.setNsPrefix(generatedMetamodel.getName()); generatedEPackage.setNsURI(generatedMetamodel.getNsURI()); - String alias = Strings.emptyIfNull(generatedMetamodel - .getAlias()); + String alias = Strings.emptyIfNull(generatedMetamodel.getAlias()); generatedEPackages.put(alias, generatedEPackage); } } @@ -278,13 +290,12 @@ public class Xtext2EcoreTransformer { for (EClassifier eClassifier : referencedEPackage.getEClassifiers()) { if (eClassifier instanceof EClass) { EClass eClass = (EClass) eClassifier; - EClassifierInfo info = EClassifierInfo.createEClassInfo(eClass, - false); + EClassifierInfo info = EClassifierInfo.createEClassInfo(eClass, false); eClassifierInfos.addInfo(alias, eClassifier.getName(), info); - } else if (eClassifier instanceof EDataType) { + } + else if (eClassifier instanceof EDataType) { EDataType eDataType = (EDataType) eClassifier; - EClassifierInfo info = EClassifierInfo.createEDataTypeInfo( - eDataType, false); + EClassifierInfo info = EClassifierInfo.createEDataTypeInfo(eDataType, false); eClassifierInfos.addInfo(alias, eClassifier.getName(), info); } } @@ -299,19 +310,16 @@ public class Xtext2EcoreTransformer { } - private void raiseError(String message, EObject erroneousElement) - throws TransformationException { + private void raiseError(String message, EObject erroneousElement) throws TransformationException { throw new TransformationException(message, erroneousElement); } - private EClassifierInfo findOrCreateEClass(AbstractRule rule) - throws TransformationException { + private EClassifierInfo findOrCreateEClass(AbstractRule rule) throws TransformationException { TypeRef typeRef = getOrFakeReturnType(rule); return findOrCreateEClass(typeRef); } - private EClassifierInfo findOrCreateEClass(TypeRef typeRef) - throws TransformationException { + private EClassifierInfo findOrCreateEClass(TypeRef typeRef) throws TransformationException { EClassifierInfo info = eClassifierInfos.getInfo(typeRef); if (info == null) { info = createEClass(typeRef); @@ -319,12 +327,10 @@ public class Xtext2EcoreTransformer { return info; } - private EClassifierInfo createEClass(TypeRef typeRef) - throws TransformationException { + private EClassifierInfo createEClass(TypeRef typeRef) throws TransformationException { if (eClassifierInfos.getInfo(typeRef) != null) - throw new IllegalArgumentException( - "Cannot create EClass for same type twice" - + GrammarUtil.getQualifiedName(typeRef)); + throw new IllegalArgumentException("Cannot create EClass for same type twice" + + GrammarUtil.getQualifiedName(typeRef)); EClassifierInfo info; String typeRefAlias = Strings.emptyIfNull(typeRef.getAlias());