aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/main/java/tools/refinery/language/resource
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/language/src/main/java/tools/refinery/language/resource')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/LoadOnDemandResourceDescriptionProvider.java52
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java4
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResource.java27
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescription.java106
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionManager.java19
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java99
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java (renamed from subprojects/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java)2
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/state/ImplicitVariableScope.java (renamed from subprojects/language/src/main/java/tools/refinery/language/resource/ImplicitVariableScope.java)2
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/state/NodeNameCollector.java (renamed from subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java)2
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/state/ProblemDerivedStateComputer.java (renamed from subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java)2
10 files changed, 292 insertions, 23 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/LoadOnDemandResourceDescriptionProvider.java b/subprojects/language/src/main/java/tools/refinery/language/resource/LoadOnDemandResourceDescriptionProvider.java
new file mode 100644
index 00000000..ccadb42d
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/LoadOnDemandResourceDescriptionProvider.java
@@ -0,0 +1,52 @@
1/*
2 * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.resource;
7
8import com.google.inject.Inject;
9import org.eclipse.emf.common.util.URI;
10import org.eclipse.emf.ecore.resource.Resource;
11import org.eclipse.emf.ecore.util.EcoreUtil;
12import org.eclipse.xtext.EcoreUtil2;
13import org.eclipse.xtext.resource.IResourceDescription;
14import org.eclipse.xtext.resource.IResourceDescriptions;
15import org.eclipse.xtext.resource.IResourceDescriptionsProvider;
16import org.eclipse.xtext.scoping.impl.GlobalResourceDescriptionProvider;
17
18public class LoadOnDemandResourceDescriptionProvider {
19 @Inject
20 private IResourceDescriptionsProvider resourceDescriptionsProvider;
21
22 @Inject
23 private GlobalResourceDescriptionProvider globalResourceDescriptionProvider;
24
25 private Resource context;
26 private IResourceDescriptions resourceDescriptions;
27
28 public void setContext(Resource context) {
29 if (this.context != null) {
30 throw new IllegalStateException("Context was already set");
31 }
32 this.context = context;
33 resourceDescriptions = resourceDescriptionsProvider.getResourceDescriptions(context.getResourceSet());
34 }
35
36 public IResourceDescription getResourceDescription(URI uri) {
37 if (this.context == null) {
38 throw new IllegalStateException("Context was not set");
39 }
40 var resourceDescription = resourceDescriptions.getResourceDescription(uri);
41 if (resourceDescription != null) {
42 return resourceDescription;
43 }
44 var importedResource = EcoreUtil2.getResource(context, uri.toString());
45 if (importedResource == null) {
46 return null;
47 }
48 // Force the {@code importedResource} to have all of its derived resource state installed.
49 EcoreUtil.resolveAll(importedResource);
50 return globalResourceDescriptionProvider.getResourceDescription(importedResource);
51 }
52}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java
index 29eaad84..c81431e5 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java
@@ -25,10 +25,10 @@ public class ProblemLocationInFileProvider extends DefaultLocationInFileProvider
25 } 25 }
26 26
27 protected ITextRegion getNodeTextRegion(Node node, RegionDescription query) { 27 protected ITextRegion getNodeTextRegion(Node node, RegionDescription query) {
28 if (ProblemUtil.isIndividualNode(node)) { 28 if (ProblemUtil.isDeclaredNode(node)) {
29 return super.doGetTextRegion(node, query); 29 return super.doGetTextRegion(node, query);
30 } 30 }
31 if (ProblemUtil.isNewNode(node)) { 31 if (ProblemUtil.isMultiNode(node)) {
32 EObject container = node.eContainer(); 32 EObject container = node.eContainer();
33 return doGetTextRegion(container, query); 33 return doGetTextRegion(container, query);
34 } 34 }
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResource.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResource.java
index 43239ffe..440a238e 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResource.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResource.java
@@ -20,9 +20,12 @@ import org.eclipse.xtext.linking.impl.IllegalNodeException;
20import org.eclipse.xtext.linking.impl.XtextLinkingDiagnostic; 20import org.eclipse.xtext.linking.impl.XtextLinkingDiagnostic;
21import org.eclipse.xtext.linking.lazy.LazyLinkingResource; 21import org.eclipse.xtext.linking.lazy.LazyLinkingResource;
22import org.eclipse.xtext.nodemodel.INode; 22import org.eclipse.xtext.nodemodel.INode;
23import org.eclipse.xtext.parser.IParseResult;
23import org.eclipse.xtext.resource.DerivedStateAwareResource; 24import org.eclipse.xtext.resource.DerivedStateAwareResource;
24import org.eclipse.xtext.util.Triple; 25import org.eclipse.xtext.util.Triple;
25import org.jetbrains.annotations.Nullable; 26import org.jetbrains.annotations.Nullable;
27import tools.refinery.language.model.problem.Problem;
28import tools.refinery.language.utils.ProblemUtil;
26 29
27import java.util.Arrays; 30import java.util.Arrays;
28import java.util.List; 31import java.util.List;
@@ -40,6 +43,30 @@ public class ProblemResource extends DerivedStateAwareResource {
40 */ 43 */
41 private int cyclicLinkingDetectionCounter = 0; 44 private int cyclicLinkingDetectionCounter = 0;
42 45
46 @Override
47 protected void updateInternalState(IParseResult oldParseResult, IParseResult newParseResult) {
48 if (isNewRootElement(oldParseResult, newParseResult) &&
49 newParseResult.getRootASTElement() instanceof Problem newRootProblem &&
50 !newRootProblem.isExplicitKind()) {
51 // Post-process the parsed model to set its URI-dependent module kind.
52 // We can't set the default module kind in {@link tools.refinery.language.serializer
53 // .ProblemTransientValueService}, because the {@link Problem} does not get added into the EMF resource
54 // before parsing is fully completed.
55 var defaultModuleKind = ProblemUtil.getDefaultModuleKind(getURI());
56 newRootProblem.setKind(defaultModuleKind);
57 }
58 super.updateInternalState(oldParseResult, newParseResult);
59 }
60
61 private boolean isNewRootElement(IParseResult oldParseResult, IParseResult newParseResult) {
62 if (oldParseResult == null) {
63 return true;
64 }
65 var oldRootAstElement = oldParseResult.getRootASTElement();
66 var newRootAstElement = newParseResult.getRootASTElement();
67 return oldRootAstElement != newRootAstElement;
68 }
69
43 /** 70 /**
44 * Tries to resolve a reference and emits a diagnostic if the reference is unresolvable or ambiguous. 71 * Tries to resolve a reference and emits a diagnostic if the reference is unresolvable or ambiguous.
45 * <p> 72 * <p>
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescription.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescription.java
new file mode 100644
index 00000000..498a7c57
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescription.java
@@ -0,0 +1,106 @@
1/*******************************************************************************
2 * Copyright (c) 2009, 2011 itemis AG (http://www.itemis.eu) and others.
3 * Copyright (c) 2024 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-2.0.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.language.resource;
10
11import org.apache.log4j.Logger;
12import org.eclipse.emf.common.util.TreeIterator;
13import org.eclipse.emf.ecore.EObject;
14import org.eclipse.emf.ecore.resource.Resource;
15import org.eclipse.emf.ecore.util.EcoreUtil;
16import org.eclipse.xtext.resource.IDefaultResourceDescriptionStrategy;
17import org.eclipse.xtext.resource.IEObjectDescription;
18import org.eclipse.xtext.resource.impl.DefaultResourceDescription;
19import org.eclipse.xtext.resource.impl.EObjectDescriptionLookUp;
20import org.eclipse.xtext.util.IAcceptor;
21import tools.refinery.language.naming.NamingUtil;
22
23import java.io.IOException;
24import java.util.*;
25
26/**
27 * A resource description that takes {@link ProblemResourceDescriptionStrategy#SHADOWING_KEY} into account when
28 * describing EObjects.
29 * <p>
30 * Based on {@link DefaultResourceDescription}.
31 */
32public class ProblemResourceDescription extends DefaultResourceDescription {
33 private static final Logger log = Logger.getLogger(ProblemResourceDescription.class);
34
35 private final IDefaultResourceDescriptionStrategy strategy;
36
37 public ProblemResourceDescription(Resource resource, IDefaultResourceDescriptionStrategy strategy) {
38 super(resource, strategy);
39 this.strategy = strategy;
40 }
41
42 /**
43 * Based on {@link DefaultResourceDescription#computeExportedObjects()}.
44 *
45 * @return The computed exported objects, taking shadowing into account.
46 */
47 @Override
48 protected List<IEObjectDescription> computeExportedObjects() {
49 if (!getResource().isLoaded()) {
50 try {
51 getResource().load(null);
52 } catch (IOException e) {
53 log.error(e.getMessage(), e);
54 return Collections.emptyList();
55 }
56 }
57 final Map<ProblemResourceDescriptionStrategy.ShadowingKey, List<IEObjectDescription>> nameToDescriptionsMap =
58 new LinkedHashMap<>();
59 IAcceptor<IEObjectDescription> acceptor = eObjectDescription -> {
60 var key = ProblemResourceDescriptionStrategy.getShadowingKey(eObjectDescription);
61 var descriptions = nameToDescriptionsMap.computeIfAbsent(key, ignored -> new ArrayList<>());
62 descriptions.add(eObjectDescription);
63 };
64 TreeIterator<EObject> allProperContents = EcoreUtil.getAllProperContents(getResource(), false);
65 while (allProperContents.hasNext()) {
66 EObject content = allProperContents.next();
67 if (!strategy.createEObjectDescriptions(content, acceptor)) {
68 allProperContents.prune();
69 }
70 }
71 return omitShadowedNames(nameToDescriptionsMap);
72 }
73
74 private static List<IEObjectDescription> omitShadowedNames(
75 Map<ProblemResourceDescriptionStrategy.ShadowingKey, List<IEObjectDescription>> nameToDescriptionsMap) {
76 final List<IEObjectDescription> exportedEObjects = new ArrayList<>();
77 for (var entry : nameToDescriptionsMap.entrySet()) {
78 var descriptions = entry.getValue();
79 if (NamingUtil.isFullyQualified(entry.getKey().name())) {
80 exportedEObjects.addAll(descriptions);
81 } else {
82 boolean foundPreferred = false;
83 for (var description : descriptions) {
84 if (ProblemResourceDescriptionStrategy.PREFERRED_NAME_TRUE.equals(
85 description.getUserData(ProblemResourceDescriptionStrategy.PREFERRED_NAME))) {
86 exportedEObjects.add(description);
87 foundPreferred = true;
88 }
89 }
90 if (!foundPreferred) {
91 exportedEObjects.addAll(descriptions);
92 }
93 }
94 }
95 return exportedEObjects;
96 }
97
98 // Based on {@code DerivedStateAwareResourceDescriptionManager#createResourceDescription}.
99 @Override
100 protected EObjectDescriptionLookUp getLookUp() {
101 if (lookup == null) {
102 lookup = new EObjectDescriptionLookUp(computeExportedObjects());
103 }
104 return lookup;
105 }
106}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionManager.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionManager.java
new file mode 100644
index 00000000..23ca139a
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionManager.java
@@ -0,0 +1,19 @@
1/*
2 * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.resource;
7
8import org.eclipse.emf.ecore.resource.Resource;
9import org.eclipse.xtext.resource.DerivedStateAwareResourceDescriptionManager;
10import org.eclipse.xtext.resource.IDefaultResourceDescriptionStrategy;
11import org.eclipse.xtext.resource.IResourceDescription;
12
13public class ProblemResourceDescriptionManager extends DerivedStateAwareResourceDescriptionManager {
14 @Override
15 protected IResourceDescription createResourceDescription(Resource resource,
16 IDefaultResourceDescriptionStrategy strategy) {
17 return new ProblemResourceDescription(resource, strategy);
18 }
19}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java
index c04c7d09..3080a78e 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java
@@ -8,44 +8,70 @@ package tools.refinery.language.resource;
8import com.google.common.collect.ImmutableMap; 8import com.google.common.collect.ImmutableMap;
9import com.google.inject.Inject; 9import com.google.inject.Inject;
10import com.google.inject.Singleton; 10import com.google.inject.Singleton;
11import com.google.inject.name.Named;
11import org.eclipse.emf.ecore.EObject; 12import org.eclipse.emf.ecore.EObject;
12import org.eclipse.xtext.EcoreUtil2; 13import org.eclipse.xtext.EcoreUtil2;
13import org.eclipse.xtext.naming.IQualifiedNameConverter; 14import org.eclipse.xtext.naming.IQualifiedNameConverter;
15import org.eclipse.xtext.naming.IQualifiedNameProvider;
14import org.eclipse.xtext.naming.QualifiedName; 16import org.eclipse.xtext.naming.QualifiedName;
15import org.eclipse.xtext.resource.EObjectDescription; 17import org.eclipse.xtext.resource.EObjectDescription;
16import org.eclipse.xtext.resource.IEObjectDescription; 18import org.eclipse.xtext.resource.IEObjectDescription;
17import org.eclipse.xtext.resource.impl.DefaultResourceDescriptionStrategy; 19import org.eclipse.xtext.resource.impl.DefaultResourceDescriptionStrategy;
18import org.eclipse.xtext.util.IAcceptor; 20import org.eclipse.xtext.util.IAcceptor;
21import tools.refinery.language.naming.ProblemQualifiedNameProvider;
22import tools.refinery.language.scoping.imports.ImportCollector;
19import tools.refinery.language.model.problem.*; 23import tools.refinery.language.model.problem.*;
20import tools.refinery.language.naming.NamingUtil; 24import tools.refinery.language.naming.NamingUtil;
21import tools.refinery.language.utils.ProblemUtil; 25import tools.refinery.language.utils.ProblemUtil;
22 26
23import java.util.Map; 27import java.util.Map;
28import java.util.stream.Collectors;
24 29
25@Singleton 30@Singleton
26public class ProblemResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy { 31public class ProblemResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy {
27 private static final String DATA_PREFIX = "tools.refinery.language.resource.ProblemResourceDescriptionStrategy."; 32 private static final String DATA_PREFIX = "tools.refinery.language.resource.ProblemResourceDescriptionStrategy.";
33
28 public static final String ARITY = DATA_PREFIX + "ARITY"; 34 public static final String ARITY = DATA_PREFIX + "ARITY";
29 public static final String ERROR_PREDICATE = DATA_PREFIX + "ERROR_PREDICATE"; 35 public static final String ERROR_PREDICATE = DATA_PREFIX + "ERROR_PREDICATE";
30 public static final String ERROR_PREDICATE_TRUE = "true"; 36 public static final String ERROR_PREDICATE_TRUE = "true";
37 public static final String SHADOWING_KEY = DATA_PREFIX + "SHADOWING_KEY";
38 public static final String SHADOWING_KEY_PROBLEM = "problem";
39 public static final String SHADOWING_KEY_NODE = "node";
40 public static final String SHADOWING_KEY_RELATION = "relation";
41 public static final String PREFERRED_NAME = DATA_PREFIX + "PREFERRED_NAME";
42 public static final String PREFERRED_NAME_TRUE = "true";
43 public static final String IMPORTS = DATA_PREFIX + "IMPORTS";
44 public static final String IMPORTS_SEPARATOR = "|";
45 public static final String MODULE_KIND = DATA_PREFIX + "MODULE_KIND";
31 public static final String COLOR_RELATION = DATA_PREFIX + "COLOR_RELATION"; 46 public static final String COLOR_RELATION = DATA_PREFIX + "COLOR_RELATION";
32 public static final String COLOR_RELATION_TRUE = "true"; 47 public static final String COLOR_RELATION_TRUE = "true";
33 48
34 @Inject 49 @Inject
35 private IQualifiedNameConverter qualifiedNameConverter; 50 private IQualifiedNameConverter qualifiedNameConverter;
36 51
52 @Inject
53 @Named(ProblemQualifiedNameProvider.NAMED_DELEGATE)
54 private IQualifiedNameProvider delegateQualifiedNameProvider;
55
56 @Inject
57 private ImportCollector importCollector;
58
37 @Override 59 @Override
38 public boolean createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) { 60 public boolean createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) {
39 if (!shouldExport(eObject)) { 61 if (!shouldExport(eObject)) {
40 return false; 62 return false;
41 } 63 }
64 var problem = EcoreUtil2.getContainerOfType(eObject, Problem.class);
65 var problemQualifiedName = getProblemQualifiedName(problem);
66 var userData = getUserData(eObject);
67 if (eObject.equals(problem)) {
68 acceptEObjectDescription(eObject, problemQualifiedName, QualifiedName.EMPTY, userData, true, acceptor);
69 return true;
70 }
42 var qualifiedName = getNameAsQualifiedName(eObject); 71 var qualifiedName = getNameAsQualifiedName(eObject);
43 if (qualifiedName == null) { 72 if (qualifiedName == null) {
44 return true; 73 return true;
45 } 74 }
46 var problem = EcoreUtil2.getContainerOfType(eObject, Problem.class);
47 var problemQualifiedName = getNameAsQualifiedName(problem);
48 var userData = getUserData(eObject);
49 QualifiedName lastQualifiedNameToExport = null; 75 QualifiedName lastQualifiedNameToExport = null;
50 if (shouldExportSimpleName(eObject)) { 76 if (shouldExportSimpleName(eObject)) {
51 lastQualifiedNameToExport = qualifiedName; 77 lastQualifiedNameToExport = qualifiedName;
@@ -82,24 +108,46 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti
82 if (NamingUtil.isNullOrEmpty(name)) { 108 if (NamingUtil.isNullOrEmpty(name)) {
83 return null; 109 return null;
84 } 110 }
85 return qualifiedNameConverter.toQualifiedName(name); 111 var qualifiedName = qualifiedNameConverter.toQualifiedName(name);
112 if (eObject instanceof Problem) {
113 return NamingUtil.stripRootPrefix(qualifiedName);
114 }
115 return qualifiedName;
86 } 116 }
87 117
88 protected boolean shouldExport(EObject eObject) { 118 protected QualifiedName getProblemQualifiedName(Problem problem) {
119 if (problem == null) {
120 return QualifiedName.EMPTY;
121 }
122 var qualifiedName = delegateQualifiedNameProvider.getFullyQualifiedName(problem);
123 return qualifiedName == null ? QualifiedName.EMPTY : qualifiedName;
124 }
125
126 public static boolean shouldExport(EObject eObject) {
89 if (eObject instanceof Variable) { 127 if (eObject instanceof Variable) {
90 // Variables are always private to the containing predicate definition. 128 // Variables are always private to the containing predicate definition.
91 return false; 129 return false;
92 } 130 }
93 if (eObject instanceof Node node) { 131 if (eObject instanceof Node node) {
94 // Only enum literals and new nodes are visible across problem files. 132 return !ProblemUtil.isImplicitNode(node);
95 return ProblemUtil.isIndividualNode(node) || ProblemUtil.isNewNode(node);
96 } 133 }
97 return true; 134 return true;
98 } 135 }
99 136
100 protected Map<String, String> getUserData(EObject eObject) { 137 protected Map<String, String> getUserData(EObject eObject) {
101 var builder = ImmutableMap.<String, String>builder(); 138 var builder = ImmutableMap.<String, String>builder();
102 if (eObject instanceof Relation relation) { 139 if (eObject instanceof Problem problem) {
140 builder.put(SHADOWING_KEY, SHADOWING_KEY_PROBLEM);
141 var explicitImports = importCollector.getDirectImports(eObject.eResource());
142 var importsString = explicitImports.toList().stream()
143 .map(importEntry -> importEntry.uri().toString())
144 .collect(Collectors.joining(IMPORTS_SEPARATOR));
145 builder.put(IMPORTS, importsString);
146 builder.put(MODULE_KIND, problem.getKind().getName());
147 } else if (eObject instanceof Node) {
148 builder.put(SHADOWING_KEY, SHADOWING_KEY_NODE);
149 } else if (eObject instanceof Relation relation) {
150 builder.put(SHADOWING_KEY, SHADOWING_KEY_RELATION);
103 int arity = ProblemUtil.getArity(relation); 151 int arity = ProblemUtil.getArity(relation);
104 builder.put(ARITY, Integer.toString(arity)); 152 builder.put(ARITY, Integer.toString(arity));
105 } 153 }
@@ -111,7 +159,7 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti
111 159
112 protected boolean shouldExportSimpleName(EObject eObject) { 160 protected boolean shouldExportSimpleName(EObject eObject) {
113 if (eObject instanceof Node node) { 161 if (eObject instanceof Node node) {
114 return !ProblemUtil.isNewNode(node); 162 return !ProblemUtil.isMultiNode(node);
115 } 163 }
116 if (eObject instanceof PredicateDefinition predicateDefinition) { 164 if (eObject instanceof PredicateDefinition predicateDefinition) {
117 return !ProblemUtil.isInvalidMultiplicityConstraint(predicateDefinition); 165 return !ProblemUtil.isInvalidMultiplicityConstraint(predicateDefinition);
@@ -125,20 +173,31 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti
125 } 173 }
126 174
127 private void acceptEObjectDescription(EObject eObject, QualifiedName prefix, QualifiedName qualifiedName, 175 private void acceptEObjectDescription(EObject eObject, QualifiedName prefix, QualifiedName qualifiedName,
128 Map<String, String> userData, boolean fullyQualified, 176 Map<String, String> userData, boolean preferredName,
129 IAcceptor<IEObjectDescription> acceptor) { 177 IAcceptor<IEObjectDescription> acceptor) {
130 var qualifiedNameWithPrefix = prefix == null ? qualifiedName : prefix.append(qualifiedName); 178 var qualifiedNameWithPrefix = prefix == null ? qualifiedName : prefix.append(qualifiedName);
131 Map<String, String> userDataWithFullyQualified; 179 var userDataWithPreference = userData;
132 if (fullyQualified && shouldColorRelation(eObject)) { 180 if (preferredName) {
133 userDataWithFullyQualified = ImmutableMap.<String, String>builder() 181 userDataWithPreference = ImmutableMap.<String, String>builder()
134 .putAll(userData) 182 .putAll(userData)
135 .put(COLOR_RELATION, COLOR_RELATION_TRUE) 183 .put(PREFERRED_NAME, PREFERRED_NAME_TRUE)
136 .build(); 184 .build();
137 } else {
138 userDataWithFullyQualified = userData;
139 } 185 }
140 var description = EObjectDescription.create(qualifiedNameWithPrefix, eObject, userDataWithFullyQualified); 186 var description = EObjectDescription.create(qualifiedNameWithPrefix, eObject, userDataWithPreference);
141 acceptor.accept(description); 187 acceptor.accept(description);
188 if (!preferredName) {
189 return;
190 }
191 var userDataWithFullyQualified = userDataWithPreference;
192 if (shouldColorRelation(eObject)) {
193 userDataWithFullyQualified = ImmutableMap.<String, String>builder()
194 .putAll(userDataWithPreference)
195 .put(COLOR_RELATION, COLOR_RELATION_TRUE)
196 .build();
197 }
198 var rootQualifiedName = NamingUtil.addRootPrefix(qualifiedNameWithPrefix);
199 var rootDescription = EObjectDescription.create(rootQualifiedName, eObject, userDataWithFullyQualified);
200 acceptor.accept(rootDescription);
142 } 201 }
143 202
144 private boolean shouldColorRelation(EObject eObject) { 203 private boolean shouldColorRelation(EObject eObject) {
@@ -146,6 +205,12 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti
146 return false; 205 return false;
147 } 206 }
148 return eObject instanceof ClassDeclaration || eObject instanceof EnumDeclaration; 207 return eObject instanceof ClassDeclaration || eObject instanceof EnumDeclaration;
208 }
209
210 public static ShadowingKey getShadowingKey(IEObjectDescription description) {
211 return new ShadowingKey(description.getName(), description.getUserData(SHADOWING_KEY));
212 }
149 213
214 public record ShadowingKey(QualifiedName name, String shadowingKey) {
150 } 215 }
151} 216}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java b/subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java
index 07c5da41..f0baf35f 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.resource; 6package tools.refinery.language.resource.state;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import com.google.inject.Singleton; 9import com.google.inject.Singleton;
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ImplicitVariableScope.java b/subprojects/language/src/main/java/tools/refinery/language/resource/state/ImplicitVariableScope.java
index e97c8287..e25887ad 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/ImplicitVariableScope.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/state/ImplicitVariableScope.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.resource; 6package tools.refinery.language.resource.state;
7 7
8import org.eclipse.emf.ecore.EObject; 8import org.eclipse.emf.ecore.EObject;
9import org.eclipse.xtext.linking.impl.LinkingHelper; 9import org.eclipse.xtext.linking.impl.LinkingHelper;
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java b/subprojects/language/src/main/java/tools/refinery/language/resource/state/NodeNameCollector.java
index e5deca4d..de4a607c 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/state/NodeNameCollector.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.resource; 6package tools.refinery.language.resource.state;
7 7
8import com.google.common.collect.ImmutableSet; 8import com.google.common.collect.ImmutableSet;
9import com.google.inject.Inject; 9import com.google.inject.Inject;
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java b/subprojects/language/src/main/java/tools/refinery/language/resource/state/ProblemDerivedStateComputer.java
index 31eb55a6..d905aa9a 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/state/ProblemDerivedStateComputer.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.resource; 6package tools.refinery.language.resource.state;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import com.google.inject.Provider; 9import com.google.inject.Provider;