mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 00:38:56 +00:00
parsetree reconstructor refactoring (part 1)
This commit is contained in:
parent
6b9615f578
commit
db307dea71
5 changed files with 122 additions and 102 deletions
|
@ -10,8 +10,6 @@
|
|||
package org.eclipse.xtext;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.parsetree.NodeUtil;
|
||||
import org.eclipse.xtext.parsetree.XtextGrammarTestParseTreeConstructor;
|
||||
import org.eclipse.xtext.tests.AbstractGeneratorTest;
|
||||
|
||||
/**
|
||||
|
@ -32,12 +30,4 @@ public class XtextGrammarTest extends AbstractGeneratorTest {
|
|||
assertWithXtend("'name'","parserRules.first().alternatives.feature",grammar);
|
||||
}
|
||||
|
||||
public void testSerialization() throws Exception {
|
||||
String model = "generate foo 'bar' Foo : ( 'stuff' '{' '}' STRING ) ? ;";
|
||||
EObject grammar = (EObject) getModel(model);
|
||||
XtextGrammarTestParseTreeConstructor ptc = (XtextGrammarTestParseTreeConstructor) getParseTreeConstructor();
|
||||
ptc.update(grammar);
|
||||
assertEquals(model, NodeUtil.getNodeAdapter(grammar).getParserNode().serialize());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
package org.eclipse.xtext.parsetree.reconstr;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.parsetree.IParseTreeConstructor;
|
||||
import org.eclipse.xtext.parsetree.NodeUtil;
|
||||
import org.eclipse.xtext.parsetree.reconstr.callbacks.SimpleSerializingCallback;
|
||||
import org.eclipse.xtext.tests.AbstractGeneratorTest;
|
||||
import org.eclipse.xtext.xtext2ecore.EcoreModelComparator;
|
||||
|
||||
public class ComplexReconstrTest extends AbstractGeneratorTest {
|
||||
|
||||
|
@ -34,16 +34,21 @@ public class ComplexReconstrTest extends AbstractGeneratorTest {
|
|||
private String parseAndSerialize(String model) throws Exception {
|
||||
EObject result = (EObject) getModel(model);
|
||||
IParseTreeConstructor con = getParseTreeConstructor();
|
||||
con.update(result);
|
||||
String resultString = NodeUtil.getRootNode(result).serialize();
|
||||
return resultString;
|
||||
SimpleSerializingCallback callback = new SimpleSerializingCallback(getValueConverterService());
|
||||
con.update(result,callback);
|
||||
return callback.toString();
|
||||
}
|
||||
|
||||
public void testNormalizableCompositeNodesIncluded() throws Exception {
|
||||
reconstructAndCompare("a");
|
||||
reconstructAndCompare("a + b");
|
||||
}
|
||||
|
||||
private void reconstructAndCompare(String mymodel) throws Exception, InterruptedException {
|
||||
EObject model = getModel(mymodel);
|
||||
EObject model2 = getModel(parseAndSerialize(mymodel));
|
||||
EcoreModelComparator ecoreModelComparator = new EcoreModelComparator();
|
||||
assertFalse(ecoreModelComparator.modelsDiffer(model, model2));
|
||||
}
|
||||
|
||||
// public void testNormalizableCompositeNodesIncluded() throws Exception {
|
||||
// EObject model = getModel("a");
|
||||
// IParseTreeConstructor con = getParseTreeConstructor();
|
||||
// con.update(model);
|
||||
// CompositeNode node = NodeUtil.getRootNode(model);
|
||||
// assertEquals("Op",((RuleCall)node.getGrammarElement()).getName());
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
package org.eclipse.xtext.parsetree.reconstr;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.parsetree.IParseTreeConstructor;
|
||||
import org.eclipse.xtext.parsetree.NodeUtil;
|
||||
import org.eclipse.xtext.parsetree.reconstr.callbacks.SimpleSerializingCallback;
|
||||
import org.eclipse.xtext.testlanguages.SimpleExpressionsStandaloneSetup;
|
||||
import org.eclipse.xtext.tests.AbstractGeneratorTest;
|
||||
|
||||
|
@ -31,19 +30,15 @@ public class SimpleReconstrTest extends AbstractGeneratorTest {
|
|||
private String parseAndSerialize(String model) throws Exception {
|
||||
EObject result = (EObject) getModel(model);
|
||||
IParseTreeConstructor con = getParseTreeConstructor();
|
||||
con.update(result);
|
||||
String resultString = NodeUtil.getRootNode(result).serialize();
|
||||
return resultString;
|
||||
SimpleSerializingCallback callback = new SimpleSerializingCallback(getValueConverterService());
|
||||
con.update(result, callback);
|
||||
return callback.toString();
|
||||
}
|
||||
|
||||
public void testSimpleExpressions() throws Exception {
|
||||
with(SimpleExpressionsStandaloneSetup.class);
|
||||
String model = "a + b - c * d / e";
|
||||
EObject result = (EObject) getModel(model);
|
||||
IParseTreeConstructor con = getParseTreeConstructor();
|
||||
con.update(result);
|
||||
String resultString = NodeUtil.getRootNode(result).serialize();
|
||||
assertEquals(model,resultString);
|
||||
assertEquals(model,parseAndSerialize(model));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,10 +22,11 @@ import org.eclipse.emf.ecore.resource.ResourceSet;
|
|||
import org.eclipse.m2t.type.emf.EmfRegistryMetaModel;
|
||||
import org.eclipse.xtext.GenerateAllTestGrammars;
|
||||
import org.eclipse.xtext.XtextStandaloneSetup;
|
||||
import org.eclipse.xtext.conversion.IValueConverterService;
|
||||
import org.eclipse.xtext.parser.IAstFactory;
|
||||
import org.eclipse.xtext.parser.IParser;
|
||||
import org.eclipse.xtext.parsetree.CompositeNode;
|
||||
import org.eclipse.xtext.parsetree.IParseTreeConstructor;
|
||||
import org.eclipse.xtext.parsetree.reconstr.IParseTreeConstructor;
|
||||
import org.eclipse.xtext.resource.IResourceFactory;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.resource.XtextResourceSet;
|
||||
|
@ -89,17 +90,21 @@ public abstract class AbstractGeneratorTest extends TestCase {
|
|||
return ServiceRegistry.getService(currentLanguageDescriptor, IParser.class);
|
||||
}
|
||||
|
||||
protected IAstFactory getASTFactory() throws Exception {
|
||||
protected IAstFactory getASTFactory() {
|
||||
return ServiceRegistry.getService(currentLanguageDescriptor, IAstFactory.class);
|
||||
}
|
||||
|
||||
protected IParseTreeConstructor getParseTreeConstructor() throws Exception {
|
||||
protected IParseTreeConstructor getParseTreeConstructor() {
|
||||
return ServiceRegistry.getService(currentLanguageDescriptor, IParseTreeConstructor.class);
|
||||
}
|
||||
|
||||
protected IResourceFactory getResourceFactory() throws Exception {
|
||||
protected IResourceFactory getResourceFactory() {
|
||||
return ServiceRegistry.getService(currentLanguageDescriptor, IResourceFactory.class);
|
||||
}
|
||||
|
||||
protected IValueConverterService getValueConverterService() {
|
||||
return ServiceRegistry.getService(currentLanguageDescriptor, IValueConverterService.class);
|
||||
}
|
||||
|
||||
// parse methods
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ import org.eclipse.emf.ecore.EObject;
|
|||
import org.eclipse.emf.ecore.EReference;
|
||||
import org.eclipse.emf.ecore.EStructuralFeature;
|
||||
import org.eclipse.emf.ecore.resource.Resource;
|
||||
import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil;
|
||||
|
||||
/**
|
||||
* @author Jan Köhnlein
|
||||
|
@ -37,78 +39,101 @@ import org.eclipse.emf.ecore.resource.Resource;
|
|||
*/
|
||||
public class EcoreModelComparator {
|
||||
|
||||
private Map<String, Object> options;
|
||||
private IMatchEngine matchEngine;
|
||||
private List<EStructuralFeature> ignoredFeatures = new ArrayList<EStructuralFeature>();
|
||||
private Map<String, Object> options;
|
||||
private IMatchEngine matchEngine;
|
||||
private List<EStructuralFeature> ignoredFeatures = new ArrayList<EStructuralFeature>();
|
||||
|
||||
public EcoreModelComparator() {
|
||||
options = new HashMap<String, Object>();
|
||||
options.put(MatchOptions.OPTION_DISTINCT_METAMODELS, Boolean.TRUE);
|
||||
matchEngine = new GenericMatchEngine();
|
||||
}
|
||||
public EcoreModelComparator() {
|
||||
options = new HashMap<String, Object>();
|
||||
options.put(MatchOptions.OPTION_DISTINCT_METAMODELS, Boolean.TRUE);
|
||||
matchEngine = new GenericMatchEngine();
|
||||
}
|
||||
|
||||
public boolean modelsDiffer(Resource left, Resource right) throws InterruptedException {
|
||||
MatchModel matchModel = matchEngine.resourceMatch(left, right, options);
|
||||
return modelsDiffer(matchModel);
|
||||
}
|
||||
public boolean modelsDiffer(Resource left, Resource right) throws InterruptedException {
|
||||
MatchModel matchModel = matchEngine.resourceMatch(left, right, options);
|
||||
return modelsDiffer(matchModel);
|
||||
}
|
||||
|
||||
public boolean modelsDiffer(EObject left, EObject right) throws InterruptedException {
|
||||
MatchModel matchModel = matchEngine.modelMatch(left, right, options);
|
||||
return modelsDiffer(matchModel);
|
||||
}
|
||||
public boolean modelsDiffer(EObject left, EObject right) throws InterruptedException {
|
||||
try {
|
||||
addSyntheticResource(left);
|
||||
addSyntheticResource(right);
|
||||
MatchModel matchModel = matchEngine.modelMatch(left, right, options);
|
||||
return modelsDiffer(matchModel);
|
||||
} finally {
|
||||
removeSyntheticResource(left);
|
||||
removeSyntheticResource(right);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean modelsDiffer(MatchModel matchModel) {
|
||||
boolean modelsDiffer = false;
|
||||
DiffModel diffModel = DiffService.doDiff(matchModel);
|
||||
if (diffModel != null) {
|
||||
for (DiffElement diffElement : diffModel.getOwnedElements()) {
|
||||
modelsDiffer |= checkDiff(diffElement);
|
||||
}
|
||||
}
|
||||
return modelsDiffer;
|
||||
}
|
||||
private class SyntheticResource extends ResourceImpl {
|
||||
|
||||
}
|
||||
|
||||
public void addIgnoredFeature(EStructuralFeature feature) {
|
||||
ignoredFeatures.add(feature);
|
||||
}
|
||||
private void removeSyntheticResource(EObject o) {
|
||||
if (o.eResource() instanceof SyntheticResource) {
|
||||
o.eResource().getContents().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkDiff(DiffElement diffElement) {
|
||||
boolean hasDiff = false;
|
||||
if (!ignoreDiff(diffElement)) {
|
||||
printDiff(diffElement);
|
||||
hasDiff = true;
|
||||
}
|
||||
for (DiffElement childDiffElement : diffElement.getSubDiffElements()) {
|
||||
hasDiff |= checkDiff(childDiffElement);
|
||||
}
|
||||
return hasDiff;
|
||||
}
|
||||
private void addSyntheticResource(EObject o) {
|
||||
if (o.eResource() == null) {
|
||||
new SyntheticResource().getContents().add(EcoreUtil.getRootContainer(o));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean ignoreDiff(DiffElement diffElement) {
|
||||
if (diffElement instanceof AttributeChange) {
|
||||
return ignoredFeatures.contains(((AttributeChange) diffElement).getAttribute());
|
||||
} else if (diffElement instanceof ReferenceChange) {
|
||||
return ignoredFeatures.contains(((ReferenceChange) diffElement).getReference());
|
||||
}
|
||||
return diffElement instanceof DiffGroup;
|
||||
}
|
||||
private boolean modelsDiffer(MatchModel matchModel) {
|
||||
boolean modelsDiffer = false;
|
||||
DiffModel diffModel = DiffService.doDiff(matchModel);
|
||||
if (diffModel != null) {
|
||||
for (DiffElement diffElement : diffModel.getOwnedElements()) {
|
||||
modelsDiffer |= checkDiff(diffElement);
|
||||
}
|
||||
}
|
||||
return modelsDiffer;
|
||||
}
|
||||
|
||||
private void printDiff(DiffElement diffElement) {
|
||||
if (diffElement instanceof AttributeChange) {
|
||||
AttributeChange change = (AttributeChange) diffElement;
|
||||
EAttribute attribute = change.getAttribute();
|
||||
System.err.println("Detected attribute difference: " + attribute.getName());
|
||||
System.err.println("\t" + change.getLeftElement());
|
||||
System.err.println("\t" + change.getRightElement());
|
||||
} else if (diffElement instanceof ReferenceChange) {
|
||||
ReferenceChange change = (ReferenceChange) diffElement;
|
||||
EReference reference = change.getReference();
|
||||
System.err.println("Detected reference difference: " + reference.getName());
|
||||
System.err.println("\t" + change.getLeftElement());
|
||||
System.err.println("\t" + change.getRightElement());
|
||||
} else {
|
||||
// TODO: add more sysouts here...
|
||||
System.err.println(diffElement.toString());
|
||||
}
|
||||
}
|
||||
public void addIgnoredFeature(EStructuralFeature feature) {
|
||||
ignoredFeatures.add(feature);
|
||||
}
|
||||
|
||||
private boolean checkDiff(DiffElement diffElement) {
|
||||
boolean hasDiff = false;
|
||||
if (!ignoreDiff(diffElement)) {
|
||||
printDiff(diffElement);
|
||||
hasDiff = true;
|
||||
}
|
||||
for (DiffElement childDiffElement : diffElement.getSubDiffElements()) {
|
||||
hasDiff |= checkDiff(childDiffElement);
|
||||
}
|
||||
return hasDiff;
|
||||
}
|
||||
|
||||
private boolean ignoreDiff(DiffElement diffElement) {
|
||||
if (diffElement instanceof AttributeChange) {
|
||||
return ignoredFeatures.contains(((AttributeChange) diffElement).getAttribute());
|
||||
} else if (diffElement instanceof ReferenceChange) {
|
||||
return ignoredFeatures.contains(((ReferenceChange) diffElement).getReference());
|
||||
}
|
||||
return diffElement instanceof DiffGroup;
|
||||
}
|
||||
|
||||
private void printDiff(DiffElement diffElement) {
|
||||
if (diffElement instanceof AttributeChange) {
|
||||
AttributeChange change = (AttributeChange) diffElement;
|
||||
EAttribute attribute = change.getAttribute();
|
||||
System.err.println("Detected attribute difference: " + attribute.getName());
|
||||
System.err.println("\t" + change.getLeftElement());
|
||||
System.err.println("\t" + change.getRightElement());
|
||||
} else if (diffElement instanceof ReferenceChange) {
|
||||
ReferenceChange change = (ReferenceChange) diffElement;
|
||||
EReference reference = change.getReference();
|
||||
System.err.println("Detected reference difference: " + reference.getName());
|
||||
System.err.println("\t" + change.getLeftElement() +" "+reference.getName()+" = "+change.getLeftElement().eGet(reference));
|
||||
System.err.println("\t" + change.getRightElement()+" "+reference.getName()+" = "+change.getRightElement().eGet(reference));
|
||||
} else {
|
||||
// TODO: add more sysouts here...
|
||||
System.err.println(diffElement.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue