diff options
Diffstat (limited to 'subprojects/language-ide/src')
3 files changed, 83 insertions, 20 deletions
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java index 166b4400..a09a475b 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -15,14 +15,16 @@ import org.eclipse.xtext.EcoreUtil2; | |||
15 | import org.eclipse.xtext.GrammarUtil; | 15 | import org.eclipse.xtext.GrammarUtil; |
16 | import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext; | 16 | import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext; |
17 | import org.eclipse.xtext.ide.editor.contentassist.IdeCrossrefProposalProvider; | 17 | import org.eclipse.xtext.ide.editor.contentassist.IdeCrossrefProposalProvider; |
18 | import org.eclipse.xtext.naming.QualifiedName; | ||
19 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | 18 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; |
20 | import org.eclipse.xtext.resource.IEObjectDescription; | 19 | import org.eclipse.xtext.resource.IEObjectDescription; |
21 | import org.eclipse.xtext.scoping.IScope; | 20 | import org.eclipse.xtext.scoping.IScope; |
22 | import org.eclipse.xtext.xtext.CurrentTypeFinder; | 21 | import org.eclipse.xtext.xtext.CurrentTypeFinder; |
23 | import org.jetbrains.annotations.Nullable; | 22 | import org.jetbrains.annotations.Nullable; |
24 | import tools.refinery.language.model.problem.*; | 23 | import tools.refinery.language.model.problem.*; |
24 | import tools.refinery.language.naming.NamingUtil; | ||
25 | import tools.refinery.language.naming.ProblemQualifiedNameConverter; | ||
25 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; | 26 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; |
27 | import tools.refinery.language.scoping.imports.ImportCollector; | ||
26 | import tools.refinery.language.utils.BuiltinSymbols; | 28 | import tools.refinery.language.utils.BuiltinSymbols; |
27 | import tools.refinery.language.utils.ProblemDesugarer; | 29 | import tools.refinery.language.utils.ProblemDesugarer; |
28 | import tools.refinery.language.utils.ProblemUtil; | 30 | import tools.refinery.language.utils.ProblemUtil; |
@@ -43,17 +45,18 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
43 | @Inject | 45 | @Inject |
44 | private ProblemDesugarer desugarer; | 46 | private ProblemDesugarer desugarer; |
45 | 47 | ||
48 | @Inject | ||
49 | private ImportCollector importCollector; | ||
50 | |||
46 | @Override | 51 | @Override |
47 | protected Iterable<IEObjectDescription> queryScope(IScope scope, CrossReference crossReference, | 52 | protected Iterable<IEObjectDescription> queryScope(IScope scope, CrossReference crossReference, |
48 | ContentAssistContext context) { | 53 | ContentAssistContext context) { |
49 | var eObjectDescriptionsByName = new HashMap<QualifiedName, List<IEObjectDescription>>(); | 54 | var eObjectDescriptionsByName = new HashMap<ProblemResourceDescriptionStrategy.ShadowingKey, |
55 | List<IEObjectDescription>>(); | ||
50 | for (var candidate : super.queryScope(scope, crossReference, context)) { | 56 | for (var candidate : super.queryScope(scope, crossReference, context)) { |
51 | if (isExistingObject(candidate, crossReference, context)) { | 57 | if (isExistingObject(candidate, crossReference, context)) { |
52 | // {@code getQualifiedName()} will refer to the full name for objects that are loaded from the global | 58 | var shadowingKey = ProblemResourceDescriptionStrategy.getShadowingKey(candidate); |
53 | // scope, but {@code getName()} returns the qualified name that we set in | 59 | var candidateList = eObjectDescriptionsByName.computeIfAbsent(shadowingKey, |
54 | // {@code ProblemResourceDescriptionStrategy}. | ||
55 | var qualifiedName = candidate.getName(); | ||
56 | var candidateList = eObjectDescriptionsByName.computeIfAbsent(qualifiedName, | ||
57 | ignored -> new ArrayList<>()); | 60 | ignored -> new ArrayList<>()); |
58 | candidateList.add(candidate); | 61 | candidateList.add(candidate); |
59 | } | 62 | } |
@@ -61,7 +64,7 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
61 | var eObjectDescriptions = new ArrayList<IEObjectDescription>(); | 64 | var eObjectDescriptions = new ArrayList<IEObjectDescription>(); |
62 | for (var candidates : eObjectDescriptionsByName.values()) { | 65 | for (var candidates : eObjectDescriptionsByName.values()) { |
63 | if (candidates.size() == 1) { | 66 | if (candidates.size() == 1) { |
64 | var candidate = candidates.get(0); | 67 | var candidate = candidates.getFirst(); |
65 | if (shouldBeVisible(candidate, crossReference, context)) { | 68 | if (shouldBeVisible(candidate, crossReference, context)) { |
66 | eObjectDescriptions.add(candidate); | 69 | eObjectDescriptions.add(candidate); |
67 | } | 70 | } |
@@ -96,6 +99,11 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
96 | 99 | ||
97 | protected boolean shouldBeVisible(IEObjectDescription candidate, CrossReference crossReference, | 100 | protected boolean shouldBeVisible(IEObjectDescription candidate, CrossReference crossReference, |
98 | ContentAssistContext context) { | 101 | ContentAssistContext context) { |
102 | if (NamingUtil.isFullyQualified(candidate.getName()) && | ||
103 | !context.getPrefix().startsWith(ProblemQualifiedNameConverter.DELIMITER)) { | ||
104 | // Do not propose names with a root prefix unless explicitly asked for. | ||
105 | return false; | ||
106 | } | ||
99 | var errorPredicate = candidate.getUserData(ProblemResourceDescriptionStrategy.ERROR_PREDICATE); | 107 | var errorPredicate = candidate.getUserData(ProblemResourceDescriptionStrategy.ERROR_PREDICATE); |
100 | if (ProblemResourceDescriptionStrategy.ERROR_PREDICATE_TRUE.equals(errorPredicate)) { | 108 | if (ProblemResourceDescriptionStrategy.ERROR_PREDICATE_TRUE.equals(errorPredicate)) { |
101 | return false; | 109 | return false; |
@@ -106,6 +114,10 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
106 | return true; | 114 | return true; |
107 | } | 115 | } |
108 | 116 | ||
117 | if (eReference == ProblemPackage.Literals.IMPORT_STATEMENT__IMPORTED_MODULE) { | ||
118 | return importedModuleShouldBeVisible(candidate, context); | ||
119 | } | ||
120 | |||
109 | var candidateEObjectOrProxy = candidate.getEObjectOrProxy(); | 121 | var candidateEObjectOrProxy = candidate.getEObjectOrProxy(); |
110 | 122 | ||
111 | if (eReference.equals(ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE) && | 123 | if (eReference.equals(ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE) && |
@@ -123,6 +135,20 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
123 | candidateEObjectOrProxy); | 135 | candidateEObjectOrProxy); |
124 | } | 136 | } |
125 | 137 | ||
138 | private boolean importedModuleShouldBeVisible(IEObjectDescription candidate, ContentAssistContext context) { | ||
139 | var moduleKind = candidate.getUserData(ProblemResourceDescriptionStrategy.MODULE_KIND); | ||
140 | if (!ModuleKind.MODULE.getName().equals(moduleKind)) { | ||
141 | return false; | ||
142 | } | ||
143 | var resource = context.getResource(); | ||
144 | var candidateResourceUri = candidate.getEObjectURI().trimFragment(); | ||
145 | if (candidateResourceUri.equals(resource.getURI())) { | ||
146 | return false; | ||
147 | } | ||
148 | var imports = importCollector.getDirectImports(resource); | ||
149 | return !imports.toUriSet().contains(candidateResourceUri); | ||
150 | } | ||
151 | |||
126 | private static boolean oppositeShouldBeVisible(ReferenceDeclaration candidateReferenceDeclaration, | 152 | private static boolean oppositeShouldBeVisible(ReferenceDeclaration candidateReferenceDeclaration, |
127 | ContentAssistContext context) { | 153 | ContentAssistContext context) { |
128 | var referenceDeclaration = EcoreUtil2.getContainerOfType(context.getCurrentModel(), | 154 | var referenceDeclaration = EcoreUtil2.getContainerOfType(context.getCurrentModel(), |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java index f64d4066..891c73c7 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java | |||
@@ -29,7 +29,7 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
29 | private static final String CONTAINMENT_CLASS = "containment"; | 29 | private static final String CONTAINMENT_CLASS = "containment"; |
30 | private static final String ERROR_CLASS = "error"; | 30 | private static final String ERROR_CLASS = "error"; |
31 | private static final String NODE_CLASS = "node"; | 31 | private static final String NODE_CLASS = "node"; |
32 | private static final String INDIVIDUAL_NODE_CLASS = "individual"; | 32 | private static final String ATOM_NODE_CLASS = "atom"; |
33 | private static final String NEW_NODE_CLASS = "new"; | 33 | private static final String NEW_NODE_CLASS = "new"; |
34 | 34 | ||
35 | @Inject | 35 | @Inject |
@@ -99,7 +99,7 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
99 | 99 | ||
100 | protected String[] getHighlightClass(EObject eObject, EReference reference) { | 100 | protected String[] getHighlightClass(EObject eObject, EReference reference) { |
101 | boolean isError = ProblemUtil.isError(eObject); | 101 | boolean isError = ProblemUtil.isError(eObject); |
102 | if (ProblemUtil.isBuiltIn(eObject)) { | 102 | if (ProblemUtil.isBuiltIn(eObject) && !(eObject instanceof Problem)) { |
103 | var className = isError ? ERROR_CLASS : BUILTIN_CLASS; | 103 | var className = isError ? ERROR_CLASS : BUILTIN_CLASS; |
104 | return new String[]{className}; | 104 | return new String[]{className}; |
105 | } | 105 | } |
@@ -137,10 +137,10 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
137 | if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE) { | 137 | if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE) { |
138 | classesBuilder.add(NODE_CLASS); | 138 | classesBuilder.add(NODE_CLASS); |
139 | } | 139 | } |
140 | if (ProblemUtil.isIndividualNode(node)) { | 140 | if (ProblemUtil.isAtomNode(node)) { |
141 | classesBuilder.add(INDIVIDUAL_NODE_CLASS); | 141 | classesBuilder.add(ATOM_NODE_CLASS); |
142 | } | 142 | } |
143 | if (ProblemUtil.isNewNode(node)) { | 143 | if (ProblemUtil.isMultiNode(node)) { |
144 | classesBuilder.add(NEW_NODE_CLASS); | 144 | classesBuilder.add(NEW_NODE_CLASS); |
145 | } | 145 | } |
146 | } | 146 | } |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/TypeHashProvider.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/TypeHashProvider.java index f75ecdb2..dd9f1053 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/TypeHashProvider.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/TypeHashProvider.java | |||
@@ -11,10 +11,13 @@ import com.google.inject.Singleton; | |||
11 | import org.eclipse.xtext.EcoreUtil2; | 11 | import org.eclipse.xtext.EcoreUtil2; |
12 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | 12 | import org.eclipse.xtext.naming.IQualifiedNameConverter; |
13 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | 13 | import org.eclipse.xtext.naming.IQualifiedNameProvider; |
14 | import org.eclipse.xtext.resource.IResourceDescription; | ||
14 | import org.eclipse.xtext.scoping.IScopeProvider; | 15 | import org.eclipse.xtext.scoping.IScopeProvider; |
16 | import org.eclipse.xtext.scoping.impl.GlobalResourceDescriptionProvider; | ||
15 | import org.eclipse.xtext.util.IResourceScopeCache; | 17 | import org.eclipse.xtext.util.IResourceScopeCache; |
16 | import tools.refinery.language.model.problem.*; | 18 | import tools.refinery.language.model.problem.*; |
17 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; | 19 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; |
20 | import tools.refinery.language.scoping.imports.ImportCollector; | ||
18 | import tools.refinery.language.utils.ProblemUtil; | 21 | import tools.refinery.language.utils.ProblemUtil; |
19 | 22 | ||
20 | import java.util.*; | 23 | import java.util.*; |
@@ -36,6 +39,12 @@ public class TypeHashProvider { | |||
36 | @Inject | 39 | @Inject |
37 | private IQualifiedNameConverter qualifiedNameConverter; | 40 | private IQualifiedNameConverter qualifiedNameConverter; |
38 | 41 | ||
42 | @Inject | ||
43 | private ImportCollector importCollector; | ||
44 | |||
45 | @Inject | ||
46 | private GlobalResourceDescriptionProvider globalResourceDescriptionProvider; | ||
47 | |||
39 | public String getTypeHash(Relation relation) { | 48 | public String getTypeHash(Relation relation) { |
40 | if (!(relation instanceof ClassDeclaration || relation instanceof EnumDeclaration) || | 49 | if (!(relation instanceof ClassDeclaration || relation instanceof EnumDeclaration) || |
41 | ProblemUtil.isBuiltIn(relation)) { | 50 | ProblemUtil.isBuiltIn(relation)) { |
@@ -55,13 +64,15 @@ public class TypeHashProvider { | |||
55 | } | 64 | } |
56 | 65 | ||
57 | private Map<String, String> computeHashes(Problem problem) { | 66 | private Map<String, String> computeHashes(Problem problem) { |
67 | var resourceDescriptions = getResourceDescriptions(problem); | ||
58 | var qualifiedNameStrings = new TreeSet<String>(); | 68 | var qualifiedNameStrings = new TreeSet<String>(); |
59 | var scope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION); | 69 | for (var resourceDescription : resourceDescriptions) { |
60 | for (var description : scope.getAllElements()) { | 70 | for (var description : resourceDescription.getExportedObjectsByType(ProblemPackage.Literals.RELATION)) { |
61 | if (ProblemResourceDescriptionStrategy.COLOR_RELATION_TRUE.equals( | 71 | if (ProblemResourceDescriptionStrategy.COLOR_RELATION_TRUE.equals( |
62 | description.getUserData(ProblemResourceDescriptionStrategy.COLOR_RELATION))) { | 72 | description.getUserData(ProblemResourceDescriptionStrategy.COLOR_RELATION))) { |
63 | var qualifiedNameString = qualifiedNameConverter.toString(description.getQualifiedName()); | 73 | var qualifiedNameString = qualifiedNameConverter.toString(description.getQualifiedName()); |
64 | qualifiedNameStrings.add(qualifiedNameString); | 74 | qualifiedNameStrings.add(qualifiedNameString); |
75 | } | ||
65 | } | 76 | } |
66 | } | 77 | } |
67 | var stringList = new ArrayList<>(qualifiedNameStrings); | 78 | var stringList = new ArrayList<>(qualifiedNameStrings); |
@@ -90,4 +101,30 @@ public class TypeHashProvider { | |||
90 | } | 101 | } |
91 | return mapBuilder.build(); | 102 | return mapBuilder.build(); |
92 | } | 103 | } |
104 | |||
105 | private List<IResourceDescription> getResourceDescriptions(Problem problem) { | ||
106 | var resource = problem.eResource(); | ||
107 | if (resource == null) { | ||
108 | return List.of(); | ||
109 | } | ||
110 | var resourceDescriptions = new ArrayList<IResourceDescription>(); | ||
111 | var resourceDescription = globalResourceDescriptionProvider.getResourceDescription(resource); | ||
112 | if (resourceDescription != null) { | ||
113 | resourceDescriptions.add(resourceDescription); | ||
114 | } | ||
115 | var resourceSet = resource.getResourceSet(); | ||
116 | if (resourceSet != null) { | ||
117 | for (var importedUri : importCollector.getAllImports(resource).toUriSet()) { | ||
118 | var importedResource = resourceSet.getResource(importedUri, false); | ||
119 | if (importedResource != null) { | ||
120 | var importedResourceDescription = globalResourceDescriptionProvider.getResourceDescription( | ||
121 | importedResource); | ||
122 | if (importedResourceDescription != null) { | ||
123 | resourceDescriptions.add(importedResourceDescription); | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | return resourceDescriptions; | ||
129 | } | ||
93 | } | 130 | } |