From 86a21430ec40c5f44973ceab3815f52e73b93980 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sat, 26 Jun 2021 22:12:19 +0200 Subject: Opposite reference scope --- .../viatra/solver/language/ProblemUtil.java | 58 +++++++++++++++++++++- .../language/scoping/ProblemScopeProvider.java | 21 ++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) (limited to 'org.eclipse.viatra.solver.language.parent') diff --git a/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java b/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java index 0151e0c0..3e7d515f 100644 --- a/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java +++ b/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java @@ -1,17 +1,37 @@ package org.eclipse.viatra.solver.language; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; import org.eclipse.viatra.solver.language.model.problem.Node; +import org.eclipse.viatra.solver.language.model.problem.Problem; import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; +import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; import org.eclipse.viatra.solver.language.model.problem.Variable; +import org.eclipse.viatra.solver.language.scoping.ProblemGlobalScopeProvider; +import com.google.common.collect.ImmutableList; import com.google.inject.Singleton; @Singleton -public class ProblemUtil { +public final class ProblemUtil { + private ProblemUtil() { + throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); + } + public static final String SINGLETON_VARIABLE_PREFIX = "_"; public static final String ENUM_NODE_NAME_QUOTE = "'"; + public static final String NODE_CLASS_NAME = "node"; + public static boolean isSingletonVariableName(String name) { return name != null && name.startsWith(SINGLETON_VARIABLE_PREFIX); } @@ -28,4 +48,40 @@ public class ProblemUtil { public static boolean isNewNode(Node node) { return node.eContainingFeature() == ProblemPackage.Literals.CLASS_DECLARATION__NEW_NODE; } + + public static Optional getBuiltInLibrary(EObject context) { + return Optional.ofNullable(context.eResource()).map(Resource::getResourceSet) + .map(resourceSet -> resourceSet.getResource(ProblemGlobalScopeProvider.BULTIN_LIBRARY_URI, true)) + .map(Resource::getContents).filter(contents -> !contents.isEmpty()).map(contents -> contents.get(0)) + .filter(Problem.class::isInstance).map(Problem.class::cast); + } + + public static Optional getNodeClassDeclaration(EObject context) { + return getBuiltInLibrary(context).flatMap(problem -> problem.getStatements().stream() + .filter(ClassDeclaration.class::isInstance).map(ClassDeclaration.class::cast) + .filter(declaration -> NODE_CLASS_NAME.equals(declaration.getName())).findFirst()); + } + + public static Collection getSuperclassesAndSelf(ClassDeclaration classDeclaration) { + Set found = new HashSet<>(); + getNodeClassDeclaration(classDeclaration).ifPresent(found::add); + Deque queue = new ArrayDeque<>(); + queue.addLast(classDeclaration); + while (!queue.isEmpty()) { + ClassDeclaration current = queue.removeFirst(); + if (!found.contains(current)) { + found.add(current); + queue.addAll(current.getSuperTypes()); + } + } + return found; + } + + public static Collection getAllReferenceDeclarations(ClassDeclaration classDeclaration) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (ClassDeclaration superclass : getSuperclassesAndSelf(classDeclaration)) { + builder.addAll(superclass.getReferenceDeclarations()); + } + return builder.build(); + } } diff --git a/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java b/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java index 1849e647..c639f24c 100644 --- a/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java +++ b/org.eclipse.viatra.solver.language.parent/org.eclipse.viatra.solver.language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java @@ -4,15 +4,20 @@ package org.eclipse.viatra.solver.language.scoping; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; +import org.eclipse.viatra.solver.language.ProblemUtil; import org.eclipse.viatra.solver.language.model.problem.Argument; +import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier; import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; +import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; import org.eclipse.viatra.solver.language.model.problem.Variable; +import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.Scopes; @@ -30,6 +35,8 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider { IScope scope = super.getScope(context, reference); if (reference == ProblemPackage.Literals.ARGUMENT__VARIABLE) { return getVariableScope(context, scope); + } else if (reference == ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE) { + return getOppositeScope(context, scope); } return scope; } @@ -57,4 +64,18 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider { } return Scopes.scopeFor(variables); } + + protected IScope getOppositeScope(EObject context, IScope delegateScope) { + ReferenceDeclaration referenceDeclaration = EcoreUtil2.getContainerOfType(context, ReferenceDeclaration.class); + if (referenceDeclaration == null) { + return delegateScope; + } + ClassDeclaration classDeclaration = referenceDeclaration.getReferenceType(); + if (classDeclaration == null) { + return delegateScope; + } + Collection referenceDeclarations = ProblemUtil + .getAllReferenceDeclarations(classDeclaration); + return Scopes.scopeFor(referenceDeclarations, delegateScope); + } } -- cgit v1.2.3-70-g09d2