aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language-ide/src/main/java/tools
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-11-06 00:13:48 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-11-17 12:41:34 +0100
commit9b6eeb1e77b05e2c2c0be5dcb285bbef128ab1f0 (patch)
tree1a40c4d5ef9fa2482a9e4e65805a02f0b341d815 /subprojects/language-ide/src/main/java/tools
parentfeat(language): validate unique names (diff)
downloadrefinery-9b6eeb1e77b05e2c2c0be5dcb285bbef128ab1f0.tar.gz
refinery-9b6eeb1e77b05e2c2c0be5dcb285bbef128ab1f0.tar.zst
refinery-9b6eeb1e77b05e2c2c0be5dcb285bbef128ab1f0.zip
feat(language-ide): content assist filtering
Diffstat (limited to 'subprojects/language-ide/src/main/java/tools')
-rw-r--r--subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java94
1 files changed, 89 insertions, 5 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 9bbce54b..8c787dfd 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
@@ -6,7 +6,9 @@
6package tools.refinery.language.ide.contentassist; 6package tools.refinery.language.ide.contentassist;
7 7
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import org.eclipse.emf.ecore.EClass;
9import org.eclipse.emf.ecore.EObject; 10import org.eclipse.emf.ecore.EObject;
11import org.eclipse.emf.ecore.EReference;
10import org.eclipse.emf.ecore.util.EcoreUtil; 12import org.eclipse.emf.ecore.util.EcoreUtil;
11import org.eclipse.xtext.CrossReference; 13import org.eclipse.xtext.CrossReference;
12import org.eclipse.xtext.GrammarUtil; 14import org.eclipse.xtext.GrammarUtil;
@@ -16,10 +18,14 @@ import org.eclipse.xtext.naming.QualifiedName;
16import org.eclipse.xtext.nodemodel.util.NodeModelUtils; 18import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
17import org.eclipse.xtext.resource.IEObjectDescription; 19import org.eclipse.xtext.resource.IEObjectDescription;
18import org.eclipse.xtext.scoping.IScope; 20import org.eclipse.xtext.scoping.IScope;
19import tools.refinery.language.model.problem.Problem; 21import org.eclipse.xtext.xtext.CurrentTypeFinder;
22import org.jetbrains.annotations.Nullable;
23import tools.refinery.language.model.problem.*;
20import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; 24import tools.refinery.language.resource.ProblemResourceDescriptionStrategy;
21import tools.refinery.language.validation.ReferenceCounter; 25import tools.refinery.language.utils.BuiltinSymbols;
26import tools.refinery.language.utils.ProblemDesugarer;
22import tools.refinery.language.utils.ProblemUtil; 27import tools.refinery.language.utils.ProblemUtil;
28import tools.refinery.language.validation.ReferenceCounter;
23 29
24import java.util.ArrayList; 30import java.util.ArrayList;
25import java.util.HashMap; 31import java.util.HashMap;
@@ -28,8 +34,14 @@ import java.util.Objects;
28 34
29public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider { 35public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider {
30 @Inject 36 @Inject
37 private CurrentTypeFinder currentTypeFinder;
38
39 @Inject
31 private ReferenceCounter referenceCounter; 40 private ReferenceCounter referenceCounter;
32 41
42 @Inject
43 private ProblemDesugarer desugarer;
44
33 @Override 45 @Override
34 protected Iterable<IEObjectDescription> queryScope(IScope scope, CrossReference crossReference, 46 protected Iterable<IEObjectDescription> queryScope(IScope scope, CrossReference crossReference,
35 ContentAssistContext context) { 47 ContentAssistContext context) {
@@ -49,7 +61,7 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider
49 for (var candidates : eObjectDescriptionsByName.values()) { 61 for (var candidates : eObjectDescriptionsByName.values()) {
50 if (candidates.size() == 1) { 62 if (candidates.size() == 1) {
51 var candidate = candidates.get(0); 63 var candidate = candidates.get(0);
52 if (shouldBeVisible(candidate)) { 64 if (shouldBeVisible(candidate, crossReference, context)) {
53 eObjectDescriptions.add(candidate); 65 eObjectDescriptions.add(candidate);
54 } 66 }
55 } 67 }
@@ -81,9 +93,81 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider
81 return true; 93 return true;
82 } 94 }
83 95
84 protected boolean shouldBeVisible(IEObjectDescription candidate) { 96 protected boolean shouldBeVisible(IEObjectDescription candidate, CrossReference crossReference,
97 ContentAssistContext context) {
85 var errorPredicate = candidate.getUserData(ProblemResourceDescriptionStrategy.ERROR_PREDICATE); 98 var errorPredicate = candidate.getUserData(ProblemResourceDescriptionStrategy.ERROR_PREDICATE);
86 return !ProblemResourceDescriptionStrategy.ERROR_PREDICATE_TRUE.equals(errorPredicate); 99 if (ProblemResourceDescriptionStrategy.ERROR_PREDICATE_TRUE.equals(errorPredicate)) {
100 return false;
101 }
102
103 var eReference = getEReference(crossReference);
104 if (eReference == null) {
105 return true;
106 }
107
108 var builtinSymbolsOption = desugarer.getBuiltinSymbols(context.getRootModel());
109 if (builtinSymbolsOption.isEmpty()) {
110 return true;
111 }
112 var builtinSymbols = builtinSymbolsOption.get();
113
114 var candidateEObjectOrProxy = candidate.getEObjectOrProxy();
115
116 if (eReference.equals(ProblemPackage.Literals.REFERENCE_DECLARATION__REFERENCE_TYPE) &&
117 context.getCurrentModel() instanceof ReferenceDeclaration referenceDeclaration &&
118 (referenceDeclaration.getKind() == ReferenceKind.CONTAINMENT ||
119 referenceDeclaration.getKind() == ReferenceKind.CONTAINER)) {
120 // Containment or container references must have a class type.
121 // We don't support {@code node} as a container or contained type.
122 return ProblemPackage.Literals.CLASS_DECLARATION.isSuperTypeOf(candidate.getEClass()) &&
123 !builtinSymbols.node().equals(candidateEObjectOrProxy);
124 }
125
126 if (eReference.equals(ProblemPackage.Literals.REFERENCE_DECLARATION__REFERENCE_TYPE) ||
127 eReference.equals(ProblemPackage.Literals.PARAMETER__PARAMETER_TYPE) ||
128 eReference.equals(ProblemPackage.Literals.TYPE_SCOPE__TARGET_TYPE)) {
129 if (builtinSymbols.exists().equals(candidateEObjectOrProxy)) {
130 return false;
131 }
132 var arity = candidate.getUserData(ProblemResourceDescriptionStrategy.ARITY);
133 return arity == null || arity.equals("1");
134 }
135
136 if (eReference.equals(ProblemPackage.Literals.CLASS_DECLARATION__SUPER_TYPES)) {
137 return supertypeShouldBeVisible(candidate, context, builtinSymbols, candidateEObjectOrProxy);
138 }
139
140 if (eReference.equals(ProblemPackage.Literals.ASSERTION__RELATION)) {
141 // Currently, we don't support assertions on the {@code contains} relation.
142 return !builtinSymbols.contains().equals(candidateEObjectOrProxy) &&
143 !builtinSymbols.contained().equals(candidateEObjectOrProxy);
144 }
145
146 return true;
147 }
148
149 private boolean supertypeShouldBeVisible(IEObjectDescription candidate, ContentAssistContext context,
150 BuiltinSymbols builtinSymbols, EObject candidateEObjectOrProxy) {
151 if (!ProblemPackage.Literals.CLASS_DECLARATION.isSuperTypeOf(candidate.getEClass()) ||
152 builtinSymbols.node().equals(candidateEObjectOrProxy) ||
153 builtinSymbols.contained().equals(candidateEObjectOrProxy)) {
154 return false;
155 }
156 if (context.getCurrentModel() instanceof ClassDeclaration classDeclaration &&
157 candidateEObjectOrProxy instanceof ClassDeclaration candidateClassDeclaration) {
158 return !classDeclaration.equals(candidateClassDeclaration) &&
159 !classDeclaration.getSuperTypes().contains(candidateClassDeclaration);
160 }
161 return true;
162 }
163
164 @Nullable
165 private EReference getEReference(CrossReference crossReference) {
166 var type = currentTypeFinder.findCurrentTypeAfter(crossReference);
167 if (!(type instanceof EClass eClass)) {
168 return null;
169 }
170 return GrammarUtil.getReference(crossReference, eClass);
87 } 171 }
88 172
89 protected EObject getCurrentValue(CrossReference crossRef, ContentAssistContext context) { 173 protected EObject getCurrentValue(CrossReference crossRef, ContentAssistContext context) {