Skip to content

Commit

Permalink
Merge pull request #570 from Systems-Modeling/ST6RI-752
Browse files Browse the repository at this point in the history
ST6RI-752 Reimplement Xtext workarounds using Xtext parse postprocessing
  • Loading branch information
seidewitz authored Jun 13, 2024
2 parents c2f26cd + 0d27360 commit fbb3f98
Show file tree
Hide file tree
Showing 46 changed files with 1,283 additions and 703 deletions.
4 changes: 2 additions & 2 deletions kerml/src/examples/Simple Tests/Dependencies.kerml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ package Dependencies {

import System::*;

// dependency Use from 'Application Layer' to 'Service Layer';
// dependency from 'Service Layer' to 'Data Layer';
dependency Use from 'Application Layer' to 'Service Layer';
dependency from 'Service Layer' to 'Data Layer';

feature x;
feature y;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*****************************************************************************
* SysML 2 Pilot Implementation
* Copyright (c) 2020-2021 Model Driven Solutions, Inc.
* Copyright (c) 2020-2021, 2024 Model Driven Solutions, Inc.
* Copyright (c) 2024 Budapest University of Technology and Economics
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
Expand All @@ -20,23 +21,32 @@
* Contributors:
* Zoltan Ujhelyi, MDS
* Ed Seidewitz, MDS
* Kristóf Marussy, BME
*
*****************************************************************************/
package org.omg.kerml.xtext.scoping;

import java.util.Objects;

import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.diagnostics.IDiagnosticConsumer;
import org.eclipse.xtext.linking.lazy.LazyLinker;
import org.omg.sysml.lang.sysml.Comment;
import org.omg.sysml.lang.sysml.Documentation;
import org.omg.sysml.lang.sysml.SysMLPackage;
import org.eclipse.xtext.util.OnChangeEvictingCache;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;
import org.omg.sysml.lang.sysml.Element;
import org.omg.sysml.lang.sysml.SysMLPackage;
import org.omg.sysml.util.ElementUtil;

import com.google.inject.Inject;

public class KerMLLinker extends LazyLinker {

@Inject
private OnChangeEvictingCache cache;

@Override
protected void clearReferences(EObject obj) {
super.clearReferences(obj);
Expand All @@ -50,30 +60,33 @@ protected void clearReference(EObject obj, EReference ref) {
if (
// The Relationship#source and #target features are overridden
// in each subtype to provide specific derived implementations that
// are regenerated each time they are accessed so there is no need to
// delete them; and as of May 2020, generic references are not supported
// in concrete syntax, making it a safe to not clear them during linking.
// are recomputed when accessed so they should not be cleared.
Objects.equals(ref, SysMLPackage.Literals.RELATIONSHIP__SOURCE) ||
Objects.equals(ref, SysMLPackage.Literals.RELATIONSHIP__TARGET) ||

// The Relationship#relatedElement feature is a derived union in the
// abstract syntax model, but it is implemented as a manual derivation,
// which is overridden as necessary in subtypes, so there is no need to
// delete it.
Objects.equals(ref, SysMLPackage.Literals.RELATIONSHIP__RELATED_ELEMENT) ||

// The Annotation#annotatingElement feature, which is not composite, is
// redefined by Documentation#documentingComment, which is composite.
// Clearing annotedElement spuriously clears the documentedElement, which
// then does not get a proxy because it is composite (containment).
// Annotation#annotatingElement has the opposite feature
// AnnotatingElement#Annotation, which also should not be cleared.
obj instanceof Documentation && Objects.equals(ref, SysMLPackage.Literals.ANNOTATION__ANNOTATING_ELEMENT) ||
obj instanceof Comment && obj.eContainer() instanceof Documentation &&
Objects.equals(ref, SysMLPackage.Literals.ANNOTATING_ELEMENT__ANNOTATION)
Objects.equals(ref, SysMLPackage.Literals.RELATIONSHIP__TARGET)
) {
return;
}
super.clearReference(obj, ref);
}

@Override
protected void doLinkModel(EObject model, IDiagnosticConsumer consumer) {
super.doLinkModel(model, consumer);
postProcessAllCrossReferences(model);
}

protected void postProcessAllCrossReferences(EObject model) {
cache.execWithoutCacheClear(model.eResource(), new IUnitOfWork.Void<Resource>() {
@Override
public void process(Resource state) throws Exception {
TreeIterator<EObject> iterator = getAllLinkableContents(model);
while (iterator.hasNext()) {
EObject obj = iterator.next();
if (obj instanceof Element) {
ElementUtil.postProcess((Element)obj);
}
}
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ protected InvocationExpression instantiateInvocation(InvocationExpression expres
for (FeatureTyping typing: expression.getOwnedTyping()) {
FeatureTyping newTyping = SysMLFactory.eINSTANCE.createFeatureTyping();
newTyping.setType(typing.getType());
newTyping.setTypedFeature(instantiation);
instantiation.getOwnedRelationship().add(newTyping);
}

Expand All @@ -99,6 +100,7 @@ protected InvocationExpression instantiateInvocation(InvocationExpression expres
for (Feature redefinedFeature: FeatureUtil.getRedefinedFeaturesWithComputedOf(parameter, null)) {
Redefinition newRedefinition = SysMLFactory.eINSTANCE.createRedefinition();
newRedefinition.setRedefinedFeature(redefinedFeature);
newRedefinition.setRedefiningFeature(newParameter);
newParameter.getOwnedRelationship().add(newRedefinition);
}

Expand Down
68 changes: 68 additions & 0 deletions org.omg.sysml/src/org/omg/sysml/adapter/AnnotationAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*******************************************************************************
* SysML 2 Pilot Implementation
* Copyright (c) 2024 Model Driven Solutions, Inc.
* Copyright (c) 2024 Budapest University of Technology and Economics
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of theGNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @license LGPL-3.0-or-later <http://spdx.org/licenses/LGPL-3.0-or-later>
*
*******************************************************************************/

package org.omg.sysml.adapter;

import org.omg.sysml.lang.sysml.AnnotatingElement;
import org.omg.sysml.lang.sysml.Annotation;
import org.omg.sysml.lang.sysml.Element;
import org.omg.sysml.lang.sysml.SysMLPackage;

public class AnnotationAdapter extends RelationshipAdapter {

public AnnotationAdapter(Annotation element) {
super(element);
}

@Override
public Annotation getTarget() {
return (Annotation)super.getTarget();
}

@Override
public void postProcess() {
Annotation obj = getTarget();

// If the Annotation is not owned by an AnnotatingElement, then the annotatedElement is the owningRelatedElement.
Object annotatedElement = obj.eGet(SysMLPackage.Literals.ANNOTATION__ANNOTATED_ELEMENT, false);
if (annotatedElement == null) {
Element owningRelatedElement = obj.getOwningRelatedElement();
if (!(owningRelatedElement instanceof AnnotatingElement)) {
obj.setAnnotatedElement(owningRelatedElement);
}
}

// If there is no annotatingElement set, then set the AnnotatingElement to the owningRelatedElement,
// if it is an AnnotatingElement, otherwise set it to the first ownedRelatedElement that is an
// AnnotatingElement (if any).
Object annotatingElement = obj.eGet(SysMLPackage.Literals.ANNOTATION__ANNOTATING_ELEMENT, false);
if (annotatingElement == null) {
Element owner = obj.getOwningRelatedElement();
obj.setAnnotatingElement((AnnotatingElement)
(owner instanceof AnnotatingElement? owner:
obj.getOwnedRelatedElement().stream().
filter(AnnotatingElement.class::isInstance).
findFirst().orElse(null)));
}
}

}
71 changes: 71 additions & 0 deletions org.omg.sysml/src/org/omg/sysml/adapter/ConjugationAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*******************************************************************************
* SysML 2 Pilot Implementation
* Copyright (c) 2024 Model Driven Solutions, Inc.
* Copyright (c) 2024 Budapest University of Technology and Economics
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of theGNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @license LGPL-3.0-or-later <http://spdx.org/licenses/LGPL-3.0-or-later>
*
*******************************************************************************/

package org.omg.sysml.adapter;

import org.eclipse.emf.common.util.EList;
import org.omg.sysml.lang.sysml.Conjugation;
import org.omg.sysml.lang.sysml.Element;
import org.omg.sysml.lang.sysml.SysMLPackage;
import org.omg.sysml.lang.sysml.Type;

public class ConjugationAdapter extends RelationshipAdapter {

public ConjugationAdapter(Conjugation element) {
super(element);
}

@Override
public Conjugation getTarget() {
return (Conjugation)super.getTarget();
}

@Override
public void postProcess() {
Conjugation obj = getTarget();

// If the conjugatedType is not set, then set it to the owningRelatedElement, if this is a Type,
// otherwise set it to the first ownedRelatedElement.
Object conjugatedType = obj.eGet(SysMLPackage.Literals.CONJUGATION__CONJUGATED_TYPE, false);
if (conjugatedType == null) {
Element owner = obj.getOwningRelatedElement();
if (owner instanceof Type) {
obj.setConjugatedType((Type)owner);
} else {
EList<Element> ownedRelatedElements = obj.getOwnedRelatedElement();
if (!ownedRelatedElements.isEmpty()) {
obj.setConjugatedType((Type)ownedRelatedElements.get(0));
}
}
}

// If the originalType is not set, set it to the last ownedRelatedElement.
Object originalType = obj.eGet(SysMLPackage.Literals.CONJUGATION__ORIGINAL_TYPE, false);
if (originalType == null) {
EList<Element> ownedRelatedElements = obj.getOwnedRelatedElement();
if (!ownedRelatedElements.isEmpty()) {
obj.setOriginalType((Type)ownedRelatedElements.get(ownedRelatedElements.size() - 1));
}
}
}

}
48 changes: 48 additions & 0 deletions org.omg.sysml/src/org/omg/sysml/adapter/DependencyAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*******************************************************************************
* SysML 2 Pilot Implementation
* Copyright (c) 2024 Model Driven Solutions, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @license LGPL-3.0-or-later <http://spdx.org/licenses/LGPL-3.0-or-later>
*
*******************************************************************************/

package org.omg.sysml.adapter;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EObjectResolvingEList;
import org.omg.sysml.lang.sysml.Dependency;
import org.omg.sysml.lang.sysml.Element;

public class DependencyAdapter extends RelationshipAdapter {

public DependencyAdapter(Dependency element) {
super(element);
}

public Dependency getTarget() {
return (Dependency)super.getTarget();
}

public void postProcess() {
Dependency target = getTarget();

// Add all ownedRelatedElements to supplier.
EObjectResolvingEList<Element> suppliers = (EObjectResolvingEList<Element>)target.getSupplier();
EList<Element> ownedRelatedElements = target.getOwnedRelatedElement();
ownedRelatedElements.stream().forEachOrdered(suppliers::addUnique);
}

}
59 changes: 59 additions & 0 deletions org.omg.sysml/src/org/omg/sysml/adapter/DifferencingAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*******************************************************************************
* SysML 2 Pilot Implementation
* Copyright (c) 2024 Model Driven Solutions, Inc.
* Copyright (c) 2024 Budapest University of Technology and Economics
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of theGNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @license LGPL-3.0-or-later <http://spdx.org/licenses/LGPL-3.0-or-later>
*
*******************************************************************************/

package org.omg.sysml.adapter;

import org.eclipse.emf.common.util.EList;
import org.omg.sysml.lang.sysml.Differencing;
import org.omg.sysml.lang.sysml.Element;
import org.omg.sysml.lang.sysml.Feature;
import org.omg.sysml.lang.sysml.SysMLPackage;

public class DifferencingAdapter extends RelationshipAdapter {

public DifferencingAdapter(Differencing element) {
super(element);
}

@Override
public Differencing getTarget() {
return (Differencing)super.getTarget();
}

@Override
public void postProcess() {
Differencing obj = getTarget();

// If a Differencing is parsed targeting a Feature chain, then the differencingType will be empty,
// but the Differencing will own the differencingType. So, in this case, the differencingType should
// be set to the (last) ownedRelatedelement.
Object differencingType = obj.eGet(SysMLPackage.Literals.DIFFERENCING__DIFFERENCING_TYPE, false);
if (differencingType == null) {
// Handle a differencingType that is a Feature chain.
EList<Element> ownedRelatedElements = obj.getOwnedRelatedElement();
if (!ownedRelatedElements.isEmpty()) {
obj.setDifferencingType((Feature)ownedRelatedElements.get(ownedRelatedElements.size() - 1));
}
}
}

}
Loading

0 comments on commit fbb3f98

Please sign in to comment.