From e3ce708fcf63c5082c300f835041da16f3baa58b Mon Sep 17 00:00:00 2001 From: Panagiotis Kourouklidis <22411884+pkourouklidis@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:22:19 +0100 Subject: [PATCH] The context and return types of a contributed operation can be a union --- .../NumberOperationContributor.java | 10 ++++++++++ .../contributors/OperationContributor.java | 7 +++++++ .../StringOperationContributor.java | 5 +++-- .../eol/staticanalyser/EolStaticAnalyser.java | 20 ++++++++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/NumberOperationContributor.java b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/NumberOperationContributor.java index ec6db3cc8a..2026e61277 100644 --- a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/NumberOperationContributor.java +++ b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/NumberOperationContributor.java @@ -9,7 +9,12 @@ ******************************************************************************/ package org.eclipse.epsilon.eol.execute.operations.contributors; +import java.util.Arrays; +import java.util.List; import java.util.stream.LongStream; + +import org.eclipse.epsilon.eol.types.EolPrimitiveType; +import org.eclipse.epsilon.eol.types.EolType; import org.eclipse.epsilon.eol.types.NumberUtil; public class NumberOperationContributor extends OperationContributor { @@ -19,6 +24,11 @@ public boolean contributesTo(Object target) { return target instanceof Number; } + @Override + public List contributesToType() { + return Arrays.asList(EolPrimitiveType.Real, EolPrimitiveType.Integer); + } + @Override protected Number getTarget() { return (Number) super.getTarget(); diff --git a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/OperationContributor.java b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/OperationContributor.java index 7a9c943892..0866f235ad 100644 --- a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/OperationContributor.java +++ b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/OperationContributor.java @@ -11,12 +11,15 @@ package org.eclipse.epsilon.eol.execute.operations.contributors; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.List; import java.util.Set; import org.eclipse.epsilon.common.parse.AST; import org.eclipse.epsilon.eol.dom.Expression; import org.eclipse.epsilon.eol.execute.context.IEolContext; import org.eclipse.epsilon.eol.execute.introspection.java.ObjectMethod; +import org.eclipse.epsilon.eol.types.EolAnyType; +import org.eclipse.epsilon.eol.types.EolType; import org.eclipse.epsilon.eol.util.ReflectionUtil; /** @@ -33,6 +36,10 @@ public abstract class OperationContributor implements AutoCloseable { public abstract boolean contributesTo(Object target); + public List contributesToType() { + return Arrays.asList(EolAnyType.Instance); + } + public ObjectMethod findContributedMethodForUnevaluatedParameters(Object target, String name, List parameterExpressions, IEolContext context) { // Note that the last parameter is false: we only want to retrieve methods that take an AST as an argument // and not methods that take a supertype of AST (such as Object) diff --git a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/StringOperationContributor.java b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/StringOperationContributor.java index 514a74b776..5eb4fcfaae 100644 --- a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/StringOperationContributor.java +++ b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/operations/contributors/StringOperationContributor.java @@ -11,6 +11,7 @@ import java.io.FileOutputStream; import java.io.StringWriter; +import java.util.Arrays; import java.util.List; import javax.xml.parsers.DocumentBuilderFactory; @@ -35,8 +36,8 @@ public boolean contributesTo(Object target) { } @Override - public EolType contributesToType() { - return EolPrimitiveType.String; + public List contributesToType() { + return Arrays.asList(EolPrimitiveType.String); } public Object toEnum() throws Exception { diff --git a/plugins/org.eclipse.epsilon.eol.staticanalyser/src/org/eclipse/epsilon/eol/staticanalyser/EolStaticAnalyser.java b/plugins/org.eclipse.epsilon.eol.staticanalyser/src/org/eclipse/epsilon/eol/staticanalyser/EolStaticAnalyser.java index 0d1e96be90..5f451a20dd 100644 --- a/plugins/org.eclipse.epsilon.eol.staticanalyser/src/org/eclipse/epsilon/eol/staticanalyser/EolStaticAnalyser.java +++ b/plugins/org.eclipse.epsilon.eol.staticanalyser/src/org/eclipse/epsilon/eol/staticanalyser/EolStaticAnalyser.java @@ -1199,7 +1199,14 @@ public void preValidate(IEolModule imodule) { //Parse builtin operations List operationContributors = context.operationContributorRegistry.stream().collect(Collectors.toList()); for(OperationContributor oc: operationContributors) { - EolType contextType = toStaticAnalyserType(oc.contributesToType()); + List contextTypes = oc.contributesToType().stream().map(t -> toStaticAnalyserType(t)).collect(Collectors.toList()); + EolType contextType; + if (contextTypes.size() == 1) { + contextType = contextTypes.get(0); + } + else { + contextType = new EolUnionType(contextTypes); + } for(Method m: oc.getClass().getDeclaredMethods()) { List operationParameterTypes = new ArrayList(); @@ -1251,6 +1258,8 @@ public EolType javaClassToEolType(Class javaClass) { } else if (javaClass == Double.class || javaClass == double.class || javaClass == Float.class || javaClass == float.class) { return EolPrimitiveType.Real; + } else if (javaClass == Number.class) { + return new EolUnionType(EolPrimitiveType.Real, EolPrimitiveType.Integer); } else if (javaClass == boolean.class || javaClass == Boolean.class) { return EolPrimitiveType.Boolean; } else if (javaClass == java.util.Collection.class) { @@ -1508,6 +1517,15 @@ public boolean canBeCompatible(EolType targetType, EolType valueType) { return false; } + if (targetType instanceof EolUnionType) { + for (EolType t : ((EolUnionType)targetType).containedTypes) { + if (canBeCompatible(t, valueType)) { + return true; + } + } + return false; + } + while (true) { if (!(targetType.equals(valueType)) && !(valueType instanceof EolAnyType)) {