Skip to content

Commit

Permalink
217: first implementation of modified elements
Browse files Browse the repository at this point in the history
  • Loading branch information
LorenzoBettini committed Jul 23, 2020
1 parent d1c9197 commit 4204fbe
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.junit.runner.RunWith
import static org.assertj.core.api.Assertions.assertThat
import static org.mockito.Mockito.*
import edelta.resource.derivedstate.EdeltaDerivedStateHelper
import edelta.resource.derivedstate.EdeltaModifiedElements

@RunWith(XtextRunner)
@InjectWith(EdeltaInjectorProvider)
Expand All @@ -50,6 +51,7 @@ class EdeltaInterpreterResourceListenerTest extends EdeltaAbstractTest {
var EPackage ePackage
var Resource resource
var EdeltaENamedElementXExpressionMap enamedElementXExpressionMap
var EdeltaModifiedElements modifiedElements
var Provider<String> stringProvider

@Before
Expand All @@ -62,6 +64,7 @@ class EdeltaInterpreterResourceListenerTest extends EdeltaAbstractTest {
]
resource = "".parse.eResource
enamedElementXExpressionMap = derivedStateHelper.getEnamedElementXExpressionMap(resource)
modifiedElements = derivedStateHelper.getModifiedElements(resource)
listener = new EdeltaInterpreterResourceListener(
cache, resource, derivedStateHelper, diagnosticHelper
)
Expand Down Expand Up @@ -261,6 +264,17 @@ class EdeltaInterpreterResourceListenerTest extends EdeltaAbstractTest {
assertThat(resource.validate).hasSize(1)
}

@Test
def void testModifiedElementsIsUpdatedWhenNameIsChanged() {
val currentExpression = mock(XExpression)
listener.setCurrentExpression(currentExpression)
val element = ePackage.EClassifiers.get(0)
// change the name
element.name = "Modified"
assertThat(modifiedElements)
.containsExactlyInAnyOrder(element, ePackage)
}

def createEObjectDiagnosticMock(EObject problematicObject) {
mock(EObjectDiagnosticImpl) => [
when(getProblematicObject).thenReturn(problematicObject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import edelta.interpreter.EdeltaInterpreterResourceListener;
import edelta.resource.derivedstate.EdeltaDerivedStateHelper;
import edelta.resource.derivedstate.EdeltaENamedElementXExpressionMap;
import edelta.resource.derivedstate.EdeltaModifiedElements;
import edelta.tests.EdeltaAbstractTest;
import edelta.tests.EdeltaInjectorProvider;
import edelta.validation.EdeltaValidator;
Expand Down Expand Up @@ -73,6 +74,8 @@ public String get() {

private EdeltaENamedElementXExpressionMap enamedElementXExpressionMap;

private EdeltaModifiedElements modifiedElements;

private Provider<String> stringProvider;

@Before
Expand All @@ -93,6 +96,7 @@ public void setup() {
this.ePackage = _doubleArrow;
this.resource = this._parseHelper.parse("").eResource();
this.enamedElementXExpressionMap = this.derivedStateHelper.getEnamedElementXExpressionMap(this.resource);
this.modifiedElements = this.derivedStateHelper.getModifiedElements(this.resource);
EdeltaInterpreterResourceListener _edeltaInterpreterResourceListener = new EdeltaInterpreterResourceListener(
this.cache, this.resource, this.derivedStateHelper, this.diagnosticHelper);
this.listener = _edeltaInterpreterResourceListener;
Expand Down Expand Up @@ -293,6 +297,15 @@ public void testEClassCycleWhenAddingSuperType() {
Assertions.<Issue>assertThat(this._validationTestHelper.validate(this.resource)).hasSize(1);
}

@Test
public void testModifiedElementsIsUpdatedWhenNameIsChanged() {
final XExpression currentExpression = Mockito.<XExpression>mock(XExpression.class);
this.listener.setCurrentExpression(currentExpression);
final EClassifier element = this.ePackage.getEClassifiers().get(0);
element.setName("Modified");
Assertions.<ENamedElement>assertThat(this.modifiedElements).containsExactlyInAnyOrder(element, this.ePackage);
}

public EObjectDiagnosticImpl createEObjectDiagnosticMock(final EObject problematicObject) {
EObjectDiagnosticImpl _mock = Mockito.<EObjectDiagnosticImpl>mock(EObjectDiagnosticImpl.class);
final Procedure1<EObjectDiagnosticImpl> _function = (EObjectDiagnosticImpl it) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import static org.eclipse.emf.ecore.EcorePackage.Literals.*;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
Expand All @@ -20,6 +23,7 @@
import edelta.lib.EdeltaLibrary;
import edelta.resource.derivedstate.EdeltaDerivedStateHelper;
import edelta.resource.derivedstate.EdeltaENamedElementXExpressionMap;
import edelta.resource.derivedstate.EdeltaModifiedElements;
import edelta.util.EdeltaModelUtil;
import edelta.validation.EdeltaValidator;

Expand Down Expand Up @@ -48,25 +52,29 @@ public class EdeltaInterpreterResourceListener extends EContentAdapter {

private EdeltaLibrary lib = new EdeltaLibrary();

private EdeltaModifiedElements modifiedElements;

public EdeltaInterpreterResourceListener(IResourceScopeCache cache, Resource resource,
EdeltaDerivedStateHelper derivedStateHelper,
EdeltaInterpreterDiagnosticHelper diagnosticHelper) {
this.cache = cache;
this.resource = resource;
this.enamedElementXExpressionMap = derivedStateHelper.getEnamedElementXExpressionMap(resource);
this.modifiedElements = derivedStateHelper.getModifiedElements(resource);
this.diagnosticHelper = diagnosticHelper;
}

@Override
public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
final Object feature = notification.getFeature();
final Object notifier = notification.getNotifier();
final Object newValue = notification.getNewValue();
if (feature == ENAMED_ELEMENT__NAME) {
enamedElementXExpressionMap.put(
(ENamedElement) notification.getNotifier(),
(ENamedElement) notifier,
currentExpression);
} else {
final Object newValue = notification.getNewValue();
if (notification.getEventType() == Notification.ADD &&
newValue instanceof ENamedElement) {
enamedElementXExpressionMap.put(
Expand All @@ -78,11 +86,29 @@ public void notifyChanged(Notification notification) {
checkCycles(feature, newValue);
}
}
updateModifiedelements(notifier, new HashSet<>());
updateModifiedelements(newValue, new HashSet<>());
cache.clear(resource);
clearIssues(resource.getErrors());
clearIssues(resource.getWarnings());
}

private void updateModifiedelements(Object element, Set<EObject> seen) {
/*
* we have to avoid stack overflows in case of cycles; we break the cycle for
* supertype hierarchy, but when doing so we get another notification and in
* that case the cycle it's still there
*/
if (element instanceof ENamedElement) {
final var enamedElement = (ENamedElement) element;
if (seen.contains(enamedElement))
return;
seen.add(enamedElement);
modifiedElements.add(enamedElement);
updateModifiedelements(enamedElement.eContainer(), seen);
}
}

private void checkCycles(final Object feature, final Object newValue) {
if (feature == EPACKAGE__ESUBPACKAGES) {
EPackage subPackage = (EPackage) newValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class EdeltaDerivedState extends AdapterImpl {
private EdeltaEcoreReferenceExpressionStateMap ecoreReferenceExpressionStateMap = new EdeltaEcoreReferenceExpressionStateMap();
private EdeltaENamedElementXExpressionMap enamedElementXExpressionMap = new EdeltaENamedElementXExpressionMap();
private EdeltaUnresolvedEcoreReferences unresolvedEcoreReferences = new EdeltaUnresolvedEcoreReferences();
private EdeltaModifiedElements modifiedElements = new EdeltaModifiedElements();

@Override
public boolean isAdapterForType(final Object type) {
Expand All @@ -41,11 +42,17 @@ public EdeltaUnresolvedEcoreReferences getUnresolvedEcoreReferences() {
return unresolvedEcoreReferences;
}

public EdeltaModifiedElements getModifiedElements() {
return modifiedElements;
}

public void clear() {
copiedEPackagesMap.clear();
ecoreReferenceStateMap.clear();
ecoreReferenceExpressionStateMap.clear();
enamedElementXExpressionMap.clear();
unresolvedEcoreReferences.clear();
modifiedElements.clear();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,8 @@ public void setAccessibleElements(EdeltaEcoreReferenceExpression ecoreRefExp,
.setAccessibleElements(accessibleElements);
}

public EdeltaModifiedElements getModifiedElements(Resource resource) {
return getOrInstallAdapter(resource).getModifiedElements();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
*
*/
package edelta.resource.derivedstate;

import java.util.HashSet;

import org.eclipse.emf.ecore.ENamedElement;

/**
* Keeps track of {@link ENamedElement}s that have been modified during the
* interpretation.
*
* @author Lorenzo Bettini
*
*/
public class EdeltaModifiedElements extends HashSet<ENamedElement> {

private static final long serialVersionUID = 1L;

}

0 comments on commit 4204fbe

Please sign in to comment.