001/*
002 * Copyright (c) 2012-2018 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others
003 *
004 * This program and the accompanying materials are made available under the
005 * terms of the Eclipse Public License 2.0 which is available at
006 * http://www.eclipse.org/legal/epl-2.0.
007 *
008 * SPDX-License-Identifier: EPL-2.0
009 */
010
011package org.eclipse.golo.runtime;
012
013import java.lang.reflect.Method;
014import java.lang.reflect.Parameter;
015import java.lang.invoke.MethodHandle;
016import java.util.Arrays;
017import java.util.List;
018import java.util.Collections;
019
020import static java.util.stream.Collectors.toList;
021import static gololang.Messages.message;
022import static java.lang.invoke.MethodHandles.permuteArguments;
023
024public final class NamedArgumentsHelper {
025
026  private NamedArgumentsHelper() {
027    // utility class
028  }
029
030  public static Boolean hasNamedParameters(Method method) {
031    return Arrays.stream(method.getParameters()).allMatch(Parameter::isNamePresent);
032  }
033
034  public static List<String> getParameterNames(Method method) {
035    if (hasNamedParameters(method)) {
036      return Arrays.stream(method.getParameters())
037          .map(Parameter::getName)
038          .collect(toList());
039    }
040    return Collections.emptyList();
041  }
042
043  public static void checkArgumentPosition(int position, String argument, String declaration) {
044    if (position == -1) {
045      throw new IllegalArgumentException(message("invalid_argument_name", argument, declaration));
046    }
047  }
048
049  public static int[] getArgumentsOrder(String methodName, List<String> parameterNames, String[] argumentNames, int nameOffset, int orderOffset) {
050    int[] argumentsOrder = new int[parameterNames.size() + orderOffset];
051    for (int i = 0; i <= orderOffset; i++) {
052      argumentsOrder[i] = i;
053    }
054    for (int i = 0; i < argumentNames.length; i++) {
055      int actualPosition = parameterNames.indexOf(argumentNames[i]);
056      checkArgumentPosition(actualPosition, argumentNames[i], methodName + parameterNames);
057      argumentsOrder[actualPosition + orderOffset] = i + nameOffset;
058    }
059    return argumentsOrder;
060  }
061
062  public static MethodHandle reorderArguments(String methodName, List<String> parameterNames, MethodHandle handle, String[] argumentNames, int nameOffset, int orderOffset) {
063    if (argumentNames.length == 0) { return handle; }
064    if (parameterNames.isEmpty()) {
065      Warnings.noParameterNames(methodName, argumentNames);
066      return handle;
067    }
068    return permuteArguments(handle, handle.type(), getArgumentsOrder(methodName, parameterNames, argumentNames, nameOffset, orderOffset));
069  }
070
071}