docs: private static Object[] adaptParams(Method method, JavaValue[] tofuValues) {
      Class<?>[] paramTypes = method.getParameterTypes();
      if (tofuValues.length != paramTypes.length) {
        throw RenderException.create(
            "Parameters ["
                + Arrays.asList(paramTypes)
                + " don't match values ["
                + Arrays.asList(tofuValues)
                + "], calling method: "
                + method);
      }
      Object[] params = new Object[tofuValues.length];
      for (int i = 0; i < tofuValues.length; i++) {
        TofuJavaValue tofuVal = (TofuJavaValue) tofuValues[i];
        Class<?> type = Primitives.unwrap(paramTypes[i]);
        if (type == BidiGlobalDir.class) {
          params[i] = tofuVal.bidiGlobalDir();
        } else if (type == ULocale.class) {
          params[i] = tofuVal.locale();
        } else {
          if (!tofuVal.hasSoyValue()) {
            throw RenderException.create("Invalid parameter: " + tofuVal);
          }
          SoyValue value = tofuVal.soyValue();
          if (value instanceof NullData || value instanceof UndefinedData) {
            if (Primitives.allPrimitiveTypes().contains(type)) {
              throw RenderException.create(
                  "cannot call method "
                      + method.getDeclaringClass().getName()
                      + "."
                      + method.getName()
                      + " because parameter["
                      + i
                      + "] expects a primitive type ["
                      + type
                      + "], but actual value is null [ "
                      + tofuVal
                      + "]");
            }
            params[i] = null;
          } else if (type.isInstance(value)) {
            params[i] = value;
          } else if (type == boolean.class) {
            params[i] = value.booleanValue();
          } else if (type == int.class) {
            params[i] = value.integerValue();
          } else if (type == long.class) {
            params[i] = value.longValue();
          } else if (type == double.class) {
            params[i] = value.numberValue();
          } else if (type == String.class) {
            params[i] = value.stringValue();
          } else if (type == List.class) {
            params[i] = ((SoyList) value).asJavaList();
          } else if (Message.class.isAssignableFrom(type)) {
            params[i] = type.cast(((SoyProtoValue) value).getProto());
          } else if (type.isEnum() && ProtocolMessageEnum.class.isAssignableFrom(type)) {
            try {
              params[i] =
                  type.getDeclaredMethod("forNumber", int.class).invoke(null, value.integerValue());
            } catch (ReflectiveOperationException roe) {
              throw RenderException.create("Invalid parameter: " + tofuVal, roe);
            }
          } else {
            throw new UnsupportedOperationException(
                "cannot call method "
                    + method.getDeclaringClass().getName()
                    + "."
                    + method.getName()
                    + " because parameter["
                    + i
                    + "] expects a "
                    + type
                    + ", but actual value is a `"
                    + value
                    + "`");
          }
        }
      }
      return params;
    }