package me.tomassetti.turin.resolvers.jdk; import me.tomassetti.jvm.JvmMethodDefinition; import me.tomassetti.jvm.JvmType; import me.tomassetti.turin.parser.ast.expressions.ActualParam; import me.tomassetti.turin.resolvers.SymbolResolver; import me.tomassetti.turin.parser.ast.Node; import me.tomassetti.turin.parser.ast.expressions.Expression; import me.tomassetti.turin.parser.ast.expressions.FunctionCall; import me.tomassetti.turin.parser.ast.expressions.InvokableExpr; import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; import me.tomassetti.turin.symbols.FormalParameter; import me.tomassetti.turin.symbols.Symbol; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; // TODO it should not be a Node public class ReflectionBasedSetOfOverloadedMethods extends Expression { private List<Method> methods; private boolean isStatic; private Symbol instance; private String name; @Override public JvmMethodDefinition findMethodFor(List<ActualParam> actualParams, SymbolResolver resolver, boolean staticContext) { List<JvmType> argsTypes = actualParams.stream().map((ap)->ap.getValue().calcType().jvmType()).collect(Collectors.toList()); return ReflectionTypeDefinitionFactory.toMethodDefinition(ReflectionBasedMethodResolution.findMethodAmong(name, argsTypes, resolver, staticContext, methods)); } private SymbolResolver symbolResolver; public ReflectionBasedSetOfOverloadedMethods(List<Method> methods, Symbol instance, SymbolResolver symbolResolver) { this.symbolResolver = symbolResolver; if (methods.isEmpty()) { throw new IllegalArgumentException(); } this.isStatic = Modifier.isStatic(methods.get(0).getModifiers()); this.name = methods.get(0).getName(); for (Method method : methods) { if (isStatic != Modifier.isStatic(method.getModifiers())) { throw new IllegalArgumentException("All methods should be static or non static"); } if (!name.equals(method.getName())) { throw new IllegalArgumentException("All methods should be named " + name); } } this.methods = methods; this.instance = instance; } public Symbol getInstance() { return instance; } @Override public Iterable<Node> getChildren() { return Collections.emptyList(); } public boolean isStatic() { return isStatic; } @Override public TypeUsageNode calcType() { throw new UnsupportedOperationException(); } @Override public Optional<List<? extends FormalParameter>> findFormalParametersFor(InvokableExpr invokable) { if (invokable instanceof FunctionCall) { FunctionCall functionCall = (FunctionCall)invokable; Optional<Method> method = ReflectionBasedMethodResolution.findMethodAmongActualParams(name, invokable.getActualParams(), symbolResolver, functionCall.isStatic(), methods); return Optional.of(ReflectionBasedMethodResolution.formalParameters(method.get(), Collections.emptyMap(), symbolResolver)); } throw new UnsupportedOperationException(invokable.getClass().getCanonicalName()); // return ReflectionTypeDefinitionFactory.toMethodDefinition(ReflectionBasedMethodResolution.findMethodAmong(name, argsTypes, resolver, staticContext, methods, this)); } }