mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 16:58:56 +00:00
Patch from Heiko Behrens (Knut) BUG 247406 [Core] Reimplement derivation of metamodel from Xtext grammar in Java
This commit is contained in:
parent
c59f92fa20
commit
8f5471e0e1
4 changed files with 228 additions and 63 deletions
|
@ -9,7 +9,6 @@
|
|||
package org.eclipse.xtext.resource.metamodel;
|
||||
|
||||
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;
|
||||
|
@ -17,7 +16,8 @@ import org.eclipse.emf.ecore.EStructuralFeature;
|
|||
import org.eclipse.emf.ecore.EcoreFactory;
|
||||
|
||||
/**
|
||||
* @author Jan K?hnlein - Initial contribution and API
|
||||
* @author Jan Köhnlein - Initial contribution and API
|
||||
* @author Heiko Behrens
|
||||
*
|
||||
*/
|
||||
public abstract class EClassifierInfo {
|
||||
|
@ -39,7 +39,7 @@ public abstract class EClassifierInfo {
|
|||
return new EDataTypeInfo(eDataType, isGenerated);
|
||||
}
|
||||
|
||||
public EClassifier getEClass() {
|
||||
public EClassifier getEClassifier() {
|
||||
return eClassifier;
|
||||
}
|
||||
|
||||
|
@ -65,24 +65,28 @@ public abstract class EClassifierInfo {
|
|||
if (!(superTypeInfo instanceof EClassInfo)) {
|
||||
throw new IllegalArgumentException("superTypeInfo must represent EClass");
|
||||
}
|
||||
EClass eClass = (EClass) getEClass();
|
||||
EClass superEClass = (EClass) superTypeInfo.getEClass();
|
||||
EClass eClass = (EClass) getEClassifier();
|
||||
EClass superEClass = (EClass) superTypeInfo.getEClassifier();
|
||||
return eClass.getESuperTypes().add(superEClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFeature(String featureName, EClassifierInfo featureType, boolean isMultivalue) {
|
||||
|
||||
EClassifier featureClassifier = featureType.getEClass();
|
||||
EClassifier featureClassifier = featureType.getEClassifier();
|
||||
EStructuralFeature newFeature;
|
||||
|
||||
EAttribute attribute = EcoreFactory.eINSTANCE.createEAttribute();
|
||||
attribute.setName(featureName);
|
||||
attribute.setEType(featureClassifier);
|
||||
attribute.setLowerBound(0);
|
||||
attribute.setUpperBound(isMultivalue ? -1 : 1);
|
||||
if (featureClassifier instanceof EClass)
|
||||
newFeature = EcoreFactory.eINSTANCE.createEReference();
|
||||
else
|
||||
newFeature = EcoreFactory.eINSTANCE.createEAttribute();
|
||||
newFeature.setName(featureName);
|
||||
newFeature.setEType(featureClassifier);
|
||||
newFeature.setLowerBound(0);
|
||||
newFeature.setUpperBound(isMultivalue ? -1 : 1);
|
||||
|
||||
EList<EStructuralFeature> features = ((EClass) getEClass()).getEStructuralFeatures();
|
||||
return features.add(attribute);
|
||||
EList<EStructuralFeature> features = ((EClass) getEClassifier()).getEStructuralFeatures();
|
||||
return features.add(newFeature);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,20 +8,23 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.resource.metamodel;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
import org.eclipse.emf.ecore.EClassifier;
|
||||
import org.eclipse.emf.ecore.EDataType;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.TypeRef;
|
||||
import org.eclipse.xtext.util.Pair;
|
||||
import org.eclipse.xtext.util.Strings;
|
||||
|
||||
/**
|
||||
* A possible extension would be to normalize the type hierarchy and remove
|
||||
* 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 EClassifierInfos {
|
||||
|
@ -47,5 +50,45 @@ public class EClassifierInfos {
|
|||
public void addAll(EClassifierInfos classInfos) {
|
||||
infoMap.putAll(classInfos.infoMap);
|
||||
}
|
||||
|
||||
|
||||
private String getCompatibleTypeNameOf(String typeA, String typeB) {
|
||||
EClassifier classifierA = getInfo(typeA).getEClassifier();
|
||||
EClassifier classifierB = getInfo(typeB).getEClassifier();
|
||||
if (classifierA.equals(classifierB))
|
||||
return typeA;
|
||||
if (classifierA instanceof EDataType || classifierB instanceof EDataType)
|
||||
throw new IllegalArgumentException(
|
||||
"Simple Datatypes (lexer rules or keywords) do not have a common supertype (" + typeA + ", "
|
||||
+ typeB + ")");
|
||||
|
||||
// TODO EClass commonSupertype = EcoreUtil2.getCommonCompatibleType((EClass) classifierA, (EClass) classifierB);
|
||||
EClass commonSupertype = classifierA.equals(classifierB) ? (EClass)classifierA : null;
|
||||
if(commonSupertype != null)
|
||||
return getQualifiedNameFor(commonSupertype);
|
||||
else
|
||||
return "ecore::EObject";
|
||||
}
|
||||
|
||||
private String getQualifiedNameFor(EClass eClass) {
|
||||
// lookup could be improved
|
||||
for (String key : infoMap.keySet()) {
|
||||
EClassifierInfo info = infoMap.get(key);
|
||||
if (info.getEClassifier().equals(eClass))
|
||||
return key;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCompatibleTypeNameOf(Collection<String> typeNames) {
|
||||
Iterator<String> i = typeNames.iterator();
|
||||
if (!i.hasNext())
|
||||
throw new IllegalArgumentException("Empty set of types cannot have a common super type.");
|
||||
|
||||
String result = i.next();
|
||||
while (i.hasNext())
|
||||
result = getCompatibleTypeNameOf(result, i.next());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,13 +15,17 @@ import java.util.Set;
|
|||
|
||||
import org.eclipse.xtext.AbstractElement;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.Alternatives;
|
||||
import org.eclipse.xtext.Assignment;
|
||||
import org.eclipse.xtext.CrossReference;
|
||||
import org.eclipse.xtext.GrammarUtil;
|
||||
import org.eclipse.xtext.Group;
|
||||
import org.eclipse.xtext.Keyword;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
|
||||
/**
|
||||
* @author Heiko Behrens - Initial contribution and API
|
||||
*
|
||||
* @see http://wiki.eclipse.org/Xtext/Documentation#Meta-Model_Inference
|
||||
*/
|
||||
public class Xtext2ECoreInterpretationContext {
|
||||
private EClassifierInfos eClassifierInfos;
|
||||
|
@ -62,17 +66,57 @@ public class Xtext2ECoreInterpretationContext {
|
|||
isMultivalue = false;
|
||||
}
|
||||
else {
|
||||
RuleCall featureRuleCall = (RuleCall) assignment.getTerminal();
|
||||
AbstractRule featureTypeRule = GrammarUtil.calledRule(featureRuleCall);
|
||||
String featureTypeName = GrammarUtil.getReturnTypeName(featureTypeRule);
|
||||
String featureTypeName = getTerminalTypeName(assignment.getTerminal());
|
||||
featureTypeInfo = getEClassifierInfoOrThrowException(featureTypeName, assignment);
|
||||
|
||||
}
|
||||
|
||||
for (EClassifierInfo type : currentTypes)
|
||||
type.addFeature(featureName, featureTypeInfo, isMultivalue);
|
||||
}
|
||||
|
||||
private String getTerminalTypeName(AbstractElement terminal) {
|
||||
if (terminal instanceof RuleCall) {
|
||||
RuleCall featureRuleCall = (RuleCall) terminal;
|
||||
AbstractRule featureTypeRule = GrammarUtil.calledRule(featureRuleCall);
|
||||
return GrammarUtil.getReturnTypeName(featureTypeRule);
|
||||
}
|
||||
else if (terminal instanceof CrossReference) {
|
||||
CrossReference crossReference = (CrossReference) terminal;
|
||||
return GrammarUtil.getQualifiedName(crossReference.getType());
|
||||
}
|
||||
else {
|
||||
// terminal is ParenthesizedElement
|
||||
// must be either: alternative of lexer rules and keywords or
|
||||
// alternative of parser rules
|
||||
return getCompatibleTypeNameOfAlternatives((Alternatives) terminal);
|
||||
}
|
||||
}
|
||||
|
||||
private String getCompatibleTypeNameOfAlternatives(AbstractElement element) {
|
||||
if (element instanceof Alternatives) {
|
||||
Alternatives alternative = (Alternatives) element;
|
||||
Set<String> typeNames = new HashSet<String>();
|
||||
for (AbstractElement group : alternative.getGroups())
|
||||
typeNames.add(getCompatibleTypeNameOfAlternatives(group));
|
||||
return eClassifierInfos.getCompatibleTypeNameOf(typeNames);
|
||||
}
|
||||
else if (element instanceof Group) {
|
||||
Group group = (Group) element;
|
||||
if (group.getAbstractTokens().size() != 1)
|
||||
throw new IllegalArgumentException("Group must have exactly one element.");
|
||||
return getCompatibleTypeNameOfAlternatives(group.getAbstractTokens().get(0));
|
||||
}
|
||||
else if (element instanceof RuleCall) {
|
||||
AbstractRule calledRule = GrammarUtil.calledRule((RuleCall) element);
|
||||
return GrammarUtil.getReturnTypeName(calledRule);
|
||||
}
|
||||
else if (element instanceof Keyword) {
|
||||
return "ecore::EString";
|
||||
}
|
||||
else
|
||||
throw new IllegalArgumentException("Terminal has no type");
|
||||
}
|
||||
|
||||
private EClassifierInfo getEClassifierInfoOrThrowException(String typeName, AbstractElement parserElement)
|
||||
throws TransformationException {
|
||||
EClassifierInfo featureTypeInfo = eClassifierInfos.getInfo(typeName);
|
||||
|
|
|
@ -7,23 +7,22 @@
|
|||
*******************************************************************************/
|
||||
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.emf.ecore.EReference;
|
||||
import org.eclipse.xtext.Grammar;
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.tests.AbstractGeneratorTest;
|
||||
|
||||
/**
|
||||
* @author Jan Köhnlein - Initial contribution and API
|
||||
* @author Heiko Behrens
|
||||
* @see http://wiki.eclipse.org/Xtext/Documentation#Meta-Model_Inference
|
||||
*/
|
||||
public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
||||
|
||||
|
@ -44,8 +43,8 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
assertNotNull(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private EAttribute assertFeatureConfiguration(EClass eClass, int attributeIndex, String featureName,
|
||||
|
||||
private EAttribute assertAttributeConfiguration(EClass eClass, int attributeIndex, String featureName,
|
||||
String featureTypeName) {
|
||||
EAttribute feature = eClass.getEAttributes().get(attributeIndex);
|
||||
assertEquals(featureName, feature.getName());
|
||||
|
@ -55,14 +54,26 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
return feature;
|
||||
}
|
||||
|
||||
private EAttribute assertFeatureConfiguration(EClass eClass, int attributeIndex, String featureName,
|
||||
private EAttribute assertAttributeConfiguration(EClass eClass, int attributeIndex, String featureName,
|
||||
String featureTypeName, int lowerBound, int upperBound) {
|
||||
EAttribute feature = assertFeatureConfiguration(eClass, attributeIndex, featureName, featureTypeName);
|
||||
EAttribute feature = assertAttributeConfiguration(eClass, attributeIndex, featureName, featureTypeName);
|
||||
assertEquals(lowerBound, feature.getLowerBound());
|
||||
assertEquals(upperBound, feature.getUpperBound());
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
private EReference assertReferenceConfiguration(EClass eClass, int referenceIndex, String featureName,
|
||||
String featureTypeName, int lowerBound, int upperBound) {
|
||||
EReference reference = eClass.getEReferences().get(referenceIndex);
|
||||
assertEquals(featureName, reference.getName());
|
||||
assertNotNull(reference.getEType());
|
||||
assertEquals(featureTypeName, reference.getEType().getName());
|
||||
assertEquals(lowerBound, reference.getLowerBound());
|
||||
assertEquals(upperBound, reference.getUpperBound());
|
||||
return reference;
|
||||
}
|
||||
|
||||
|
||||
public void testTypesOfImplicitSuperGrammar() throws Exception {
|
||||
final String xtextGrammar = "language test generate test 'http://test' MyRule: myFeature=INT;";
|
||||
|
@ -114,7 +125,7 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
assertNotNull(ruleA);
|
||||
|
||||
assertEquals(1, ruleA.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleA, 0, "featureA", "EInt");
|
||||
assertAttributeConfiguration(ruleA, 0, "featureA", "EInt");
|
||||
}
|
||||
|
||||
public void testBuiltInFeatureTypes() throws Exception {
|
||||
|
@ -124,9 +135,9 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
assertNotNull(ruleA);
|
||||
|
||||
assertEquals(3, ruleA.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleA, 0, "featureA", "EString");
|
||||
assertFeatureConfiguration(ruleA, 1, "featureB", "EInt");
|
||||
assertFeatureConfiguration(ruleA, 2, "featureC", "EString");
|
||||
assertAttributeConfiguration(ruleA, 0, "featureA", "EString");
|
||||
assertAttributeConfiguration(ruleA, 1, "featureB", "EInt");
|
||||
assertAttributeConfiguration(ruleA, 2, "featureC", "EString");
|
||||
}
|
||||
|
||||
public void testCardinalityOfFeatures() throws Exception {
|
||||
|
@ -136,9 +147,9 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
assertNotNull(ruleA);
|
||||
|
||||
assertEquals(3, ruleA.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleA, 0, "featureA", "EBoolean", 0, 1);
|
||||
assertFeatureConfiguration(ruleA, 1, "featureB", "EInt", 0, 1);
|
||||
assertFeatureConfiguration(ruleA, 2, "featureC", "EString", 0, -1);
|
||||
assertAttributeConfiguration(ruleA, 0, "featureA", "EBoolean", 0, 1);
|
||||
assertAttributeConfiguration(ruleA, 1, "featureB", "EInt", 0, 1);
|
||||
assertAttributeConfiguration(ruleA, 2, "featureC", "EString", 0, -1);
|
||||
}
|
||||
|
||||
public void testOptionalAssignmentsInGroup() throws Exception {
|
||||
|
@ -148,8 +159,8 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
|
||||
assertNotNull(ruleA);
|
||||
assertEquals(2, ruleA.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleA, 0, "featureA", "EBoolean", 0, 1);
|
||||
assertFeatureConfiguration(ruleA, 1, "featureB", "EInt", 0, -1);
|
||||
assertAttributeConfiguration(ruleA, 0, "featureA", "EBoolean", 0, 1);
|
||||
assertAttributeConfiguration(ruleA, 1, "featureB", "EInt", 0, -1);
|
||||
}
|
||||
|
||||
public void testFeaturesAndInheritanceOptionalRuleCall() throws Exception {
|
||||
|
@ -162,10 +173,10 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
assertNotNull(ruleB);
|
||||
|
||||
assertEquals(1, ruleA.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleA, 0, "featureA", "EInt");
|
||||
assertAttributeConfiguration(ruleA, 0, "featureA", "EInt");
|
||||
|
||||
assertEquals(1, ruleB.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleB, 0, "featureB", "EString");
|
||||
assertAttributeConfiguration(ruleB, 0, "featureB", "EString");
|
||||
}
|
||||
|
||||
public void testFeaturesAndInheritanceMandatoryRuleCall() throws Exception {
|
||||
|
@ -180,8 +191,8 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
assertEquals(0, ruleA.getEAttributes().size());
|
||||
|
||||
assertEquals(2, ruleB.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleB, 0, "featureA", "EInt");
|
||||
assertFeatureConfiguration(ruleB, 1, "featureB", "EString");
|
||||
assertAttributeConfiguration(ruleB, 0, "featureA", "EInt");
|
||||
assertAttributeConfiguration(ruleB, 1, "featureB", "EString");
|
||||
}
|
||||
|
||||
public void testFeaturesAndInheritanceOfMandatoryAlternativeRuleCalls() throws Exception {
|
||||
|
@ -205,12 +216,12 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
// test all features are separated
|
||||
assertEquals(0, ruleA.getEAttributes().size());
|
||||
assertEquals(2, ruleB.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleB, 0, "featureA", "EString");
|
||||
assertFeatureConfiguration(ruleB, 1, "featureB", "EString");
|
||||
assertAttributeConfiguration(ruleB, 0, "featureA", "EString");
|
||||
assertAttributeConfiguration(ruleB, 1, "featureB", "EString");
|
||||
assertEquals(3, ruleC.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleC, 0, "featureC1", "EString");
|
||||
assertFeatureConfiguration(ruleC, 1, "featureA", "EString");
|
||||
assertFeatureConfiguration(ruleC, 2, "featureC2", "EString");
|
||||
assertAttributeConfiguration(ruleC, 0, "featureC1", "EString");
|
||||
assertAttributeConfiguration(ruleC, 1, "featureA", "EString");
|
||||
assertAttributeConfiguration(ruleC, 2, "featureC2", "EString");
|
||||
}
|
||||
|
||||
public void testFeaturesAndInheritanceOfOptionalOptionalRuleCalls() throws Exception {
|
||||
|
@ -233,12 +244,12 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
|
||||
// test all features are separated
|
||||
assertEquals(1, ruleA.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleA, 0, "featureA", "EString");
|
||||
assertAttributeConfiguration(ruleA, 0, "featureA", "EString");
|
||||
assertEquals(1, ruleB.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleB, 0, "featureB", "EString");
|
||||
assertAttributeConfiguration(ruleB, 0, "featureB", "EString");
|
||||
assertEquals(2, ruleC.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleC, 0, "featureC1", "EString");
|
||||
assertFeatureConfiguration(ruleC, 1, "featureC2", "EString");
|
||||
assertAttributeConfiguration(ruleC, 0, "featureC1", "EString");
|
||||
assertAttributeConfiguration(ruleC, 1, "featureC2", "EString");
|
||||
}
|
||||
|
||||
public void testFeaturesAndInheritanceOfNestedRuleCalls() throws Exception {
|
||||
|
@ -265,20 +276,83 @@ public class Xtext2EcoreTransformerTests extends AbstractGeneratorTest {
|
|||
|
||||
// test all features are separated
|
||||
assertEquals(2, ruleA.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleA, 0, "featureBC", "EString");
|
||||
assertFeatureConfiguration(ruleA, 1, "featureA", "EString");
|
||||
assertAttributeConfiguration(ruleA, 0, "featureBC", "EString");
|
||||
assertAttributeConfiguration(ruleA, 1, "featureA", "EString");
|
||||
assertEquals(1, ruleB.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleB, 0, "featureB2", "EString");
|
||||
assertAttributeConfiguration(ruleB, 0, "featureB2", "EString");
|
||||
assertEquals(4, ruleC.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleC, 0, "featureC1", "EString");
|
||||
assertFeatureConfiguration(ruleC, 1, "featureCD", "EString");
|
||||
assertFeatureConfiguration(ruleC, 2, "featureA", "EString");
|
||||
assertFeatureConfiguration(ruleC, 3, "featureC2", "EString");
|
||||
assertAttributeConfiguration(ruleC, 0, "featureC1", "EString");
|
||||
assertAttributeConfiguration(ruleC, 1, "featureCD", "EString");
|
||||
assertAttributeConfiguration(ruleC, 2, "featureA", "EString");
|
||||
assertAttributeConfiguration(ruleC, 3, "featureC2", "EString");
|
||||
assertEquals(4, ruleD.getEAttributes().size());
|
||||
assertFeatureConfiguration(ruleD, 0, "featureD1", "EString");
|
||||
assertFeatureConfiguration(ruleD, 1, "featureCD", "EString");
|
||||
assertFeatureConfiguration(ruleD, 2, "featureA", "EString");
|
||||
assertFeatureConfiguration(ruleD, 3, "featureD2", "EString");
|
||||
assertAttributeConfiguration(ruleD, 0, "featureD1", "EString");
|
||||
assertAttributeConfiguration(ruleD, 1, "featureCD", "EString");
|
||||
assertAttributeConfiguration(ruleD, 2, "featureA", "EString");
|
||||
assertAttributeConfiguration(ruleD, 3, "featureD2", "EString");
|
||||
}
|
||||
|
||||
public void testAssignedRuleCall() throws Exception {
|
||||
final String grammar = "language test generate test 'http://test' RuleA: callA1=RuleB callA2+=RuleB simpleFeature=ID; RuleB: featureB=ID;";
|
||||
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());
|
||||
assertAttributeConfiguration(ruleA, 0, "simpleFeature", "EString");
|
||||
assertEquals(2, ruleA.getEReferences().size());
|
||||
assertReferenceConfiguration(ruleA, 0, "callA1", "RuleB", 0, 1);
|
||||
assertReferenceConfiguration(ruleA, 1, "callA2", "RuleB", 0, -1);
|
||||
assertEquals(1, ruleB.getEAttributes().size());
|
||||
assertAttributeConfiguration(ruleB, 0, "featureB", "EString");
|
||||
}
|
||||
|
||||
public void testAssignedCrossReference() throws Exception {
|
||||
final String grammar = "language test generate test 'http://test' RuleA: refA1=[TypeB] refA2+=[TypeB|RuleB] simpleFeature=ID; RuleB returns TypeB: featureB=ID;";
|
||||
EPackage ePackage = getEPackageFromGrammar(grammar);
|
||||
assertEquals(2, ePackage.getEClassifiers().size());
|
||||
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
|
||||
assertNotNull(ruleA);
|
||||
EClass typeB = (EClass) ePackage.getEClassifier("TypeB");
|
||||
assertNotNull(typeB);
|
||||
|
||||
assertEquals(1, ruleA.getEAttributes().size());
|
||||
assertAttributeConfiguration(ruleA, 0, "simpleFeature", "EString");
|
||||
assertEquals(2, ruleA.getEReferences().size());
|
||||
assertReferenceConfiguration(ruleA, 0, "refA1", "TypeB", 0, 1);
|
||||
assertReferenceConfiguration(ruleA, 1, "refA2", "TypeB", 0, -1);
|
||||
assertEquals(1, typeB.getEAttributes().size());
|
||||
assertAttributeConfiguration(typeB, 0, "featureB", "EString");
|
||||
}
|
||||
|
||||
public void testAssignedParenthesizedElement() throws Exception {
|
||||
final String grammar = "language test generate test 'http://test' RuleA: featureA1?=(RuleB) refA1=(RuleB) refA2=(RuleB|RuleC) refA3+=(RuleB|RuleC|RuleD) refA4=(RuleB|RuleD) featureA2+=('a'|'b'); RuleB returns TypeB: RuleC? featureB=ID; RuleC: featureC=ID; RuleD returns TypeB: featureD=ID;";
|
||||
EPackage ePackage = getEPackageFromGrammar(grammar);
|
||||
assertEquals(3, ePackage.getEClassifiers().size());
|
||||
EClass ruleA = (EClass) ePackage.getEClassifier("RuleA");
|
||||
assertNotNull(ruleA);
|
||||
assertEquals(0, ruleA.getESuperTypes().size());
|
||||
EClass typeB = (EClass) ePackage.getEClassifier("TypeB");
|
||||
assertNotNull(typeB);
|
||||
assertEquals(0, typeB.getESuperTypes().size());
|
||||
EClass ruleC = (EClass) ePackage.getEClassifier("RuleC");
|
||||
assertNotNull(ruleC);
|
||||
assertEquals(1, ruleC.getESuperTypes().size());
|
||||
assertEquals(typeB, ruleC.getESuperTypes().get(0));
|
||||
|
||||
assertEquals(2, ruleA.getEAttributes().size());
|
||||
assertAttributeConfiguration(ruleA, 0, "featureA1", "EBoolean");
|
||||
assertAttributeConfiguration(ruleA, 1, "featureA2", "EString", 0, -1);
|
||||
|
||||
assertEquals(4, ruleA.getEReferences().size());
|
||||
assertReferenceConfiguration(ruleA, 0, "refA1", "TypeB", 0, 1);
|
||||
// TODO should be common compatible type according to #248430
|
||||
assertReferenceConfiguration(ruleA, 1, "refA2", "EObject", 0, 1);
|
||||
assertReferenceConfiguration(ruleA, 2, "refA3", "EObject", 0, -1);
|
||||
assertReferenceConfiguration(ruleA, 3, "refA4", "TypeB", 0, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue