Applied patch from heiko

This commit is contained in:
jkohnlein 2008-09-22 09:21:51 +00:00
parent 852acd7a2b
commit 17a48a5cc5
8 changed files with 442 additions and 147 deletions

View file

@ -27,6 +27,7 @@ import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtext.builtin.IXtextBuiltin;
import org.eclipse.xtext.impl.TypeRefImpl;
import org.eclipse.xtext.util.Strings;
/**
@ -256,10 +257,26 @@ public class GrammarUtil {
return getQualifiedName(rule.getType());
}
public static String getQualifiedName(TypeRef type) {
return (type.getAlias() != null ? type.getAlias() + "::" : "") + type.getName();
public static String getQualifiedName(String alias, String name) {
return (alias != null ? alias + "::" : "") + name;
}
public static String getQualifiedName(TypeRef type) {
return getQualifiedName(type.getAlias(), type.getName());
}
public static TypeRef getTypeRef(String qualifiedName) {
TypeRef result = XtextFactory.eINSTANCE.createTypeRef();
String[] split = qualifiedName.split("::");
if (split.length > 1) {
result.setAlias(split[0]);
result.setName(split[1]);
} else {
result.setName(qualifiedName);
}
return result;
}
public static boolean isAssigned(EObject e) {
return containingAssignment(e) != null;
}

View file

@ -26,6 +26,7 @@ import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.IGrammarAccess;
import org.eclipse.xtext.IMetamodelAccess;
import org.eclipse.xtext.ReferencedMetamodel;
import org.eclipse.xtext.TypeRef;
import org.eclipse.xtext.conversion.IValueConverterService;
import org.eclipse.xtext.service.Inject;
@ -119,18 +120,12 @@ public class GenericEcoreElementFactory implements IAstFactory {
}
public EClass getEClass(String fullTypeName) {
String[] split = fullTypeName.split("::");
String typeName = fullTypeName;
String alias = null;
if (split.length > 1) {
alias = split[0];
typeName = split[1];
}
EPackage pack = getEPackage(alias);
TypeRef typeRef = GrammarUtil.getTypeRef(fullTypeName);
EPackage pack = getEPackage(typeRef.getAlias());
if (pack == null) {
throw new IllegalStateException("Couldn't find any epackages for alias '" + alias + "'");
throw new IllegalStateException("Couldn't find any epackages for alias '" + typeRef.getAlias() + "'");
}
EClassifier classifier = pack.getEClassifier(typeName);
EClassifier classifier = pack.getEClassifier(typeRef.getName());
if (classifier instanceof EClass) {
return (EClass) classifier;
}

View file

@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.xtext.resource.metamodel;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.emf.ecore.EClass;
/**
* @author Jan Köhnlein - Initial contribution and API
*
*/
public class EClassInfo {
private EClass eClass;
private boolean isGenerated;
private Set<EClassInfo> superTypes = new HashSet<EClassInfo>();
public EClassInfo(EClass metaType, boolean isGenerated) {
super();
this.isGenerated = isGenerated;
this.eClass = metaType;
}
public EClass getEClass() {
return eClass;
}
public boolean isGenerated() {
return isGenerated;
}
public boolean addSupertype(EClassInfo superTypeInfo) {
return superTypes.add(superTypeInfo);
}
}

View file

@ -0,0 +1,108 @@
/*******************************************************************************
* Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.xtext.resource.metamodel;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
/**
* @author Jan K?hnlein - Initial contribution and API
*
*/
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);
}
public static EClassifierInfo createEDataTypeInfo(EDataType eDataType, boolean isGenerated) {
return new EDataTypeInfo(eDataType, isGenerated);
}
public EClassifier getEClass() {
return eClassifier;
}
public boolean isGenerated() {
return isGenerated;
}
public abstract boolean addSupertype(EClassifierInfo superTypeInfo);
public abstract boolean addFeature(String featureName, EClassifierInfo featureType);
static class EClassInfo extends EClassifierInfo {
public EClassInfo(EClassifier metaType, boolean isGenerated) {
super(metaType, isGenerated);
}
@Override
public boolean addSupertype(EClassifierInfo superTypeInfo) {
if(!isGenerated()){
throw new IllegalStateException("Generated Type cannot be modified.");
}
if(!(superTypeInfo instanceof EClassInfo)) {
throw new IllegalArgumentException("superTypeInfo must represent EClass");
}
EClass eClass = (EClass)getEClass();
EClass superEClass = (EClass)superTypeInfo.getEClass();
return eClass.getESuperTypes().add(superEClass);
}
@Override
public boolean addFeature(String featureName,
EClassifierInfo featureType) {
EClassifier featureClassifier = featureType.getEClass();
EAttribute attribute = EcoreFactory.eINSTANCE.createEAttribute();
attribute.setName(featureName);
attribute.setEType(featureClassifier);
EList<EStructuralFeature> features = ((EClass)getEClass()).getEStructuralFeatures();
return features.add(attribute);
}
}
static class EDataTypeInfo extends EClassifierInfo {
public EDataTypeInfo(EClassifier metaType, boolean isGenerated) {
super(metaType, isGenerated);
}
@Override
public boolean addSupertype(EClassifierInfo superTypeInfo) {
throw new UnsupportedOperationException("Cannot add supertype to simple datatype");
}
@Override
public boolean addFeature(String featureName,
EClassifierInfo featureType) {
throw new UnsupportedOperationException("Cannot add feature to simple datatype");
}
}
}

View file

@ -11,6 +11,7 @@ package org.eclipse.xtext.resource.metamodel;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.TypeRef;
import org.eclipse.xtext.util.Pair;
import org.eclipse.xtext.util.Strings;
@ -20,33 +21,31 @@ import org.eclipse.xtext.util.Strings;
* redundant supertype references. We currently don't think thats necessary as
* EMF handles multiple inheritance gracefully.
*
* @author Jan Köhnlein - Initial contribution and API
* @author Jan K?hnlein - Initial contribution and API
*
*/
public class EClassInfos {
public class EClassifierInfos {
class Key extends Pair<String, String> {
public Key(String firstElement, String secondElement) {
super(firstElement, secondElement);
}
private Map<String, EClassifierInfo> infoMap = new HashMap<String, EClassifierInfo>();
public boolean addInfo(TypeRef typeRef, EClassifierInfo metatypeInfo) {
return infoMap.put(GrammarUtil.getQualifiedName(typeRef), metatypeInfo) != metatypeInfo;
}
private Map<Key, EClassInfo> infoMap = new HashMap<Key, EClassInfo>();
public boolean addInfo(TypeRef typeRef, EClassInfo metatypeInfo) {
return infoMap.put(key(typeRef), metatypeInfo) != metatypeInfo;
public boolean addInfo(String alias, String name, EClassifierInfo metatypeInfo) {
return infoMap.put(GrammarUtil.getQualifiedName(alias, name), metatypeInfo) != metatypeInfo;
}
public boolean addInfo(String alias, String name, EClassInfo metatypeInfo) {
return infoMap.put(new Key(alias, name), metatypeInfo) != metatypeInfo;
public EClassifierInfo getInfo(TypeRef typeRef) {
return getInfo(GrammarUtil.getQualifiedName(typeRef));
}
public EClassInfo getInfo(TypeRef typeRef) {
return infoMap.get(key(typeRef));
public EClassifierInfo getInfo(String qualifiedName) {
return infoMap.get(qualifiedName);
}
private Key key(TypeRef typeRef) {
return new Key(Strings.emptyIfNull(typeRef.getAlias()), typeRef.getName());
public void addAll(EClassifierInfos classInfos) {
infoMap.putAll(classInfos.infoMap);
}
}

View file

@ -14,8 +14,10 @@ import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcoreFactory;
@ -24,15 +26,16 @@ import org.eclipse.xtext.AbstractMetamodelDeclaration;
import org.eclipse.xtext.AbstractRule;
import org.eclipse.xtext.Action;
import org.eclipse.xtext.Alternatives;
import org.eclipse.xtext.Assignment;
import org.eclipse.xtext.GeneratedMetamodel;
import org.eclipse.xtext.Grammar;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.Group;
import org.eclipse.xtext.LexerRule;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.ReferencedMetamodel;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.TypeRef;
import org.eclipse.xtext.XtextFactory;
import org.eclipse.xtext.util.Strings;
/**
@ -44,7 +47,7 @@ public class Xtext2EcoreTransformer {
private Grammar grammar;
private Map<String, EPackage> generatedEPackages;
private Grammar superGrammar;
private EClassInfos eClassInfos;
private EClassifierInfos eClassifierInfos;
public Xtext2EcoreTransformer() {
}
@ -58,7 +61,9 @@ public class Xtext2EcoreTransformer {
this.grammar = grammar;
generatedEPackages = new HashMap<String, EPackage>();
superGrammar = GrammarUtil.getSuperGrammar(grammar);
eClassInfos = new EClassInfos();
eClassifierInfos = new EClassifierInfos();
if (superGrammar != null)
collectEClassInfosOfSuperGrammar();
collectEPackages();
// create types:
@ -66,19 +71,14 @@ public class Xtext2EcoreTransformer {
// - typeref in actions
for (AbstractRule rule : grammar.getRules()) {
// - return types (lexer and parser rules)
TypeRef ruleReturnTypeRef = rule.getType();
try {
if (ruleReturnTypeRef == null) {
ruleReturnTypeRef = XtextFactory.eINSTANCE.createTypeRef();
ruleReturnTypeRef.setName(rule.getName());
}
EClassInfo generatedEClass = findOrCreateEClass(ruleReturnTypeRef);
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());
}
}
@ -88,6 +88,15 @@ public class Xtext2EcoreTransformer {
// - assignments
// - feature in actions
// multiplicity!
for (AbstractRule rule : grammar.getRules()) {
try {
if (rule instanceof ParserRule) {
this.deriveFeatures((ParserRule) rule);
}
} catch (TransformationException e) {
reportError(e.getMessage(), e.getErroneousElement());
}
}
// type hierarchy
// - rule calls (optionality)
@ -102,6 +111,51 @@ public class Xtext2EcoreTransformer {
return new ArrayList<EPackage>(generatedEPackages.values());
}
private void collectEClassInfosOfSuperGrammar() {
Xtext2EcoreTransformer transformer = new Xtext2EcoreTransformer();
transformer.transform(superGrammar);
this.getEClassifierInfos().addAll(transformer.getEClassifierInfos());
}
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) {
Group group = (Group) element;
return deriveFeatures(context, group.getAbstractTokens());
}
return context;
}
private InterpretationContext deriveFeatures(InterpretationContext context,
EList<AbstractElement> elements) throws TransformationException {
for(AbstractElement element : elements) {
context = deriveFeatures(context, element);
}
return context;
}
private void deriveFeatures(ParserRule rule) throws TransformationException {
EClassifierInfo classInfo = findOrCreateEClass(rule);
boolean isGenerated = classInfo.isGenerated();
InterpretationContext context = new InterpretationContext(classInfo,
isGenerated, true);
deriveFeatures(context, rule.getAlternatives());
}
// TODO : Try to get rid of
private TypeRef getOrFakeReturnType(AbstractRule rule) {
TypeRef result = rule.getType();
if (result == null) {
String returnTypeName = GrammarUtil.getReturnTypeName(rule);
result = GrammarUtil.getTypeRef(returnTypeName);
}
return result;
}
private void fillGeneratedPackages() {
}
@ -110,101 +164,132 @@ public class Xtext2EcoreTransformer {
* @param alternatives
* @throws TransformationException
*/
private void deriveTypesAndHierarchy(EClassInfo 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 = calledRule.getType();
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(EClassInfo ruleReturnType, List<AbstractElement> elements)
throws TransformationException {
private void deriveTypesAndHierarchy(EClassifierInfo ruleReturnType,
List<AbstractElement> elements) throws TransformationException {
for (AbstractElement element : elements) {
deriveTypesAndHierarchy(ruleReturnType, element);
}
}
private void addSuperType(TypeRef subTypeRef, EClassInfo superType) throws TransformationException {
EClassInfo calledRuleReturnType = findOrCreateEClass(subTypeRef);
private void addSuperType(TypeRef subTypeRef, EClassifierInfo superType)
throws TransformationException {
EClassifierInfo calledRuleReturnType = findOrCreateEClass(subTypeRef);
calledRuleReturnType.addSupertype(superType);
}
class InterpretationContext {
public InterpretationContext(EClass currentType, boolean isGeneratedType, boolean isRuleCallAllowed) {
public InterpretationContext(EClassifierInfo currentType,
boolean isGeneratedType, boolean isRuleCallAllowed) {
super();
this.currentType = currentType;
this.isGeneratedType = isGeneratedType;
this.isRuleCallAllowed = isRuleCallAllowed;
}
public InterpretationContext clone() {
return new InterpretationContext(currentType, isGeneratedType, isRuleCallAllowed);
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);
}
currentType.addFeature(featureName, featureTypeInfo);
// TODO : fill Cardinality of attribute
// this.currentType.getEStructuralFeatures().add(attribute);
}
EClass currentType;
public InterpretationContext clone() {
return new InterpretationContext(currentType, isGeneratedType,
isRuleCallAllowed);
}
// TODO : Use set of types to reflect mandatory actions
EClassifierInfo currentType;
boolean isGeneratedType;
boolean isRuleCallAllowed = true;
}
private InterpretationContext interpretElement(AbstractElement element, EClass returnType) {
// TODO: implement
return null;
}
private void collectEPackages() {
EList<AbstractMetamodelDeclaration> metamodelDeclarations = grammar.getMetamodelDeclarations();
EList<AbstractMetamodelDeclaration> 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 {
for (EClassifier eClassifier : referencedEPackage.getEClassifiers()) {
if (eClassifier instanceof EClass) {
EClassInfo info = new EClassInfo((EClass) eClassifier, false);
eClassInfos.addInfo(alias, eClassifier.getName(), info);
}
}
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);
}
}
}
private void collectClassInfosOf(EPackage referencedEPackage, String alias) {
for (EClassifier eClassifier : referencedEPackage.getEClassifiers()) {
if (eClassifier instanceof EClass) {
EClass eClass = (EClass) eClassifier;
EClassifierInfo info = EClassifierInfo.createEClassInfo(eClass,
false);
eClassifierInfos.addInfo(alias, eClassifier.getName(), info);
} else if (eClassifier instanceof EDataType) {
EDataType eDataType = (EDataType) eClassifier;
EClassifierInfo info = EClassifierInfo.createEDataTypeInfo(
eDataType, false);
eClassifierInfos.addInfo(alias, eClassifier.getName(), info);
}
}
}
/**
* @param string
* @param generatedMetamodel
@ -214,26 +299,50 @@ 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 EClassInfo findOrCreateEClass(TypeRef typeRef) throws TransformationException {
EClassInfo info = eClassInfos.getInfo(typeRef);
private EClassifierInfo findOrCreateEClass(AbstractRule rule)
throws TransformationException {
TypeRef typeRef = getOrFakeReturnType(rule);
return findOrCreateEClass(typeRef);
}
private EClassifierInfo findOrCreateEClass(TypeRef typeRef)
throws TransformationException {
EClassifierInfo info = eClassifierInfos.getInfo(typeRef);
if (info == null) {
String typeRefAlias = Strings.emptyIfNull(typeRef.getAlias());
String typeRefName = typeRef.getName();
EPackage generatedEPackage = generatedEPackages.get(typeRefAlias);
if (generatedEPackage == null) {
raiseError("Cannot create type in alias " + typeRefAlias, typeRef);
}
EClass generatedEClass = EcoreFactory.eINSTANCE.createEClass();
generatedEClass.setName(typeRefName);
generatedEPackage.getEClassifiers().add(generatedEClass);
info = new EClassInfo(generatedEClass, true);
eClassInfos.addInfo(typeRef, info);
info = createEClass(typeRef);
}
return info;
}
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));
EClassifierInfo info;
String typeRefAlias = Strings.emptyIfNull(typeRef.getAlias());
String typeRefName = typeRef.getName();
EPackage generatedEPackage = generatedEPackages.get(typeRefAlias);
if (generatedEPackage == null) {
raiseError("Cannot create type in alias " + typeRefAlias, typeRef);
}
EClass generatedEClass = EcoreFactory.eINSTANCE.createEClass();
generatedEClass.setName(typeRefName);
generatedEPackage.getEClassifiers().add(generatedEClass);
info = EClassifierInfo.createEClassInfo(generatedEClass, true);
eClassifierInfos.addInfo(typeRef, info);
return info;
}
public EClassifierInfos getEClassifierInfos() {
return eClassifierInfos;
}
}

View file

@ -40,6 +40,7 @@ public class AutoTestSuite {
suite.addTestSuite(org.eclipse.xtext.parsetree.reconstr.WhitespacePreservingCallbackTest.class);
suite.addTestSuite(org.eclipse.xtext.reference.CommentOnEofBug_234135_Test.class);
suite.addTestSuite(org.eclipse.xtext.reference.LeafNodeBug_234132_Test.class);
suite.addTestSuite(org.eclipse.xtext.resource.metamodel.Xtext2EcoreTransformerTests.class);
suite.addTestSuite(org.eclipse.xtext.typeresolution.XtextUtilConstructionTest.class);
suite.addTestSuite(org.eclipse.xtext.xtext2ecore.ActionTest.class);
suite.addTestSuite(org.eclipse.xtext.xtext2ecore.BootstrapModelTest.class);

View file

@ -7,11 +7,16 @@
*******************************************************************************/
package org.eclipse.xtext.resource.metamodel;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.impl.AESCipherImpl;
import org.eclipse.xtext.AbstractRule;
import org.eclipse.xtext.Grammar;
import org.eclipse.xtext.XtextStandaloneSetup;
@ -28,18 +33,122 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
with(XtextStandaloneSetup.class);
}
public void testRuleWithoutExplicitReturnType() throws Exception {
Grammar grammar = (Grammar) getModel("language test generate test 'http://test' MyRule: myFeature=INT;");
EList<AbstractRule> rules = grammar.getRules();
AbstractRule firstRule = rules.get(0);
assertNull(firstRule.getType());
private EPackage getEPackageFromGrammar(String xtextGrammar)
throws Exception {
Grammar grammar = (Grammar) getModel(xtextGrammar);
Xtext2EcoreTransformer xtext2EcoreTransformer = new Xtext2EcoreTransformer();
List<EPackage> metamodels = xtext2EcoreTransformer.transform(grammar);
assertTrue(metamodels != null && !metamodels.isEmpty());
EPackage firstEPackage = metamodels.get(0);
EList<EClassifier> classifiers = firstEPackage.getEClassifiers();
assertNotNull(metamodels);
assertEquals(1, metamodels.size());
EPackage result = metamodels.get(0);
assertNotNull(result);
return result;
}
private void assertFeatureConfiguration(EClass eClass, int attributeIndex,
String featureName, String featureTypeName) {
EAttribute feature = eClass.getEAttributes().get(attributeIndex);
assertEquals(featureName, feature.getName());
assertNotNull(feature.getEType());
assertEquals(featureTypeName, feature.getEType().getName());
}
public void testTypesOfImplicitSuperGrammar() throws Exception {
final String xtextGrammar = "language test generate test 'http://test' MyRule: myFeature=INT;";
Grammar grammar = (Grammar) getModel(xtextGrammar);
Xtext2EcoreTransformer transformer = new Xtext2EcoreTransformer();
transformer.transform(grammar);
// directly from grammar
assertNotNull(transformer.getEClassifierInfos().getInfo("MyRule"));
// ecore data types
assertNotNull(transformer.getEClassifierInfos().getInfo("ecore::EString"));
assertNotNull(transformer.getEClassifierInfos().getInfo("ecore::EInt"));
}
public void testRuleWithoutExplicitReturnType() throws Exception {
final String grammar = "language test generate test 'http://test' MyRule: myFeature=INT;";
EPackage ePackage = getEPackageFromGrammar(grammar);
EList<EClassifier> classifiers = ePackage.getEClassifiers();
assertEquals(1, classifiers.size());
EClassifier implicitlyDefinedMetatype = classifiers.get(0);
assertEquals("MyRule", implicitlyDefinedMetatype.getName());
}
public void testRulesWithExplicitReturnType() throws Exception {
final String grammar = "language test generate test 'http://test' RuleA returns TypeA: featureA=INT; RuleB returns TypeB: featureB= INT;";
EPackage ePackage = getEPackageFromGrammar(grammar);
assertEquals(2, ePackage.getEClassifiers().size());
assertNotNull(ePackage.getEClassifier("TypeA"));
assertNotNull(ePackage.getEClassifier("TypeB"));
}
public void testSimpleHierarchy() throws Exception {
final String grammar = "language test generate test 'http://test' RuleA: RuleB; RuleB: featureB= INT;";
EPackage ePackage = getEPackageFromGrammar(grammar);
assertEquals(2, ePackage.getEClassifiers().size());
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
assertNotNull(ruleA);
EClass ruleB = (EClass) ePackage.getEClassifier("RuleB");
assertNotNull(ruleB);
assertTrue(ruleA.getESuperTypes().isEmpty());
assertEquals(1, ruleB.getESuperTypes().size());
EClass superClass = ruleB.getESuperTypes().get(0);
assertEquals(ruleA, superClass);
}
public void testSingleFeatures() throws Exception {
final String grammar = "language test generate test 'http://test' RuleA: featureA=INT;";
EPackage ePackage = getEPackageFromGrammar(grammar);
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
assertNotNull(ruleA);
assertEquals(1, ruleA.getEAttributes().size());
assertFeatureConfiguration(ruleA, 0, "featureA", "EInt");
}
public void testBuiltInFeatureTypes() throws Exception {
final String grammar = "language test generate test 'http://test' RuleA: featureA=ID featureB=INT featureC=STRING;";
EPackage ePackage = getEPackageFromGrammar(grammar);
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
assertNotNull(ruleA);
assertEquals(3, ruleA.getEAttributes().size());
assertFeatureConfiguration(ruleA, 0, "featureA", "EString");
assertFeatureConfiguration(ruleA, 1, "featureB", "EInt");
assertFeatureConfiguration(ruleA, 2, "featureC", "EString");
}
public void testFeatureAndInheritanceOptionalRuleCall() throws Exception {
final String grammar = "language test generate test 'http://test' RuleA: RuleB? featureA=INT; RuleB: featureB=STRING;";
EPackage ePackage = getEPackageFromGrammar(grammar);
assertEquals(2, ePackage.getEClassifiers().size());
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
assertNotNull(ruleA);
EClass ruleB = (EClass) ePackage.getEClassifier("RuleB");
assertNotNull(ruleB);
assertEquals(1, ruleA.getEAttributes().size());
assertFeatureConfiguration(ruleA, 0, "featureA", "EInt");
assertEquals(1, ruleB.getEAttributes().size());
assertFeatureConfiguration(ruleB, 0, "featureB", "EString");
}
public void _testFeatureAndInheritanceMandatoryRuleCall() throws Exception {
final String grammar = "language test generate test 'http://test' RuleA: RuleB featureA=INT; RuleB: featureB=STRING;";
EPackage ePackage = getEPackageFromGrammar(grammar);
assertEquals(2, ePackage.getEClassifiers().size());
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
assertNotNull(ruleA);
EClass ruleB = (EClass) ePackage.getEClassifier("RuleB");
assertNotNull(ruleB);
assertEquals(0, ruleA.getEAttributes().size());
assertEquals(2, ruleB.getEAttributes().size());
assertFeatureConfiguration(ruleB, 0, "featureA", "EInt");
assertFeatureConfiguration(ruleB, 1, "featureB", "EString");
}
}