package me.tomassetti.turin.compiler; import com.google.common.collect.ImmutableList; import me.tomassetti.turin.definitions.TypeDefinition; import me.tomassetti.turin.parser.analysis.Property; import me.tomassetti.turin.resolvers.SymbolResolver; import me.tomassetti.turin.parser.ast.Node; import me.tomassetti.turin.parser.ast.expressions.ActualParam; import me.tomassetti.turin.parser.ast.expressions.Creation; import me.tomassetti.turin.parser.ast.expressions.Expression; import me.tomassetti.turin.parser.ast.expressions.InstanceMethodInvokation; import me.tomassetti.turin.parser.ast.expressions.literals.StringLiteral; import me.tomassetti.turin.symbols.FormalParameter; import me.tomassetti.turin.typesystem.TypeUsage; import me.tomassetti.turin.util.Either; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; public final class ParamUtils { private ParamUtils() { // prevent instantiation } public static boolean verifyOrder(List<ActualParam> actualParams) { boolean findNamed = false; for (ActualParam actualParam : actualParams) { if (findNamed && (!actualParam.isNamed() && !actualParam.isAsterisk())) { return false; } findNamed = findNamed || actualParam.isNamed(); } return true; } public static List<ActualParam> unnamedParams(List<ActualParam> actualParams) { return actualParams.stream().filter((p)->!p.isNamed() && !p.isAsterisk()).collect(Collectors.toList()); } public static List<ActualParam> namedParams(List<ActualParam> actualParams) { return actualParams.stream().filter((p) -> p.isNamed()).collect(Collectors.toList()); } public static boolean hasDefaultParams(List<? extends FormalParameter> formalParameters) { return formalParameters.stream().filter((p)->p.hasDefaultValue()).findFirst().isPresent(); } public static Either<String, List<ActualParam>> desugarizeAsteriskParam(List<? extends FormalParameter> formalParameters, Expression value, SymbolResolver resolver, Node parent) { TypeUsage type = value.calcType(); if (!type.isReference()) { return Either.left("An asterisk param should be an object"); } List<ActualParam> actualParams = new ArrayList<>(); TypeDefinition typeDefinition = type.asReferenceTypeUsage().getTypeDefinition(); // map with the default params Expression mapCreation = new Creation("turin.collections.MapBuilder", Collections.emptyList()); mapCreation.setParent(parent); for (FormalParameter formalParameter : formalParameters) { String getterName = getterName(formalParameter, resolver); InstanceMethodInvokation instanceMethodInvokation = new InstanceMethodInvokation(value, getterName, Collections.emptyList()); if (typeDefinition.hasMethodFor(getterName, Collections.emptyList(), false)) { if (formalParameter.hasDefaultValue()) { List<ActualParam> params = new ArrayList<>(); params.add(new ActualParam(new StringLiteral(formalParameter.getName()))); params.add(new ActualParam(instanceMethodInvokation)); mapCreation = new InstanceMethodInvokation(mapCreation, "put", params); } else { ActualParam actualParam = new ActualParam(instanceMethodInvokation); actualParam.setParent(parent); actualParams.add(actualParam); } } else { if (!formalParameter.hasDefaultValue()) { return Either.left("the given value has not a getter '" + getterName + "'"); } } } if (hasDefaultParams(formalParameters)) { mapCreation = new InstanceMethodInvokation(mapCreation, "build", ImmutableList.of()); mapCreation.setParent(parent); ActualParam mapForDefaultParams = new ActualParam(mapCreation); mapForDefaultParams.setParent(parent); actualParams.add(mapForDefaultParams); } return Either.right(actualParams); } /** * Corresponding getter method name */ public static String getterName(FormalParameter formalParameter, SymbolResolver resolver) { return Property.getterName(formalParameter.getType(), formalParameter.getName(), resolver); } }