mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 00:38:56 +00:00
Applied patch from heiko
This commit is contained in:
parent
852acd7a2b
commit
17a48a5cc5
8 changed files with 442 additions and 147 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue