methodInvocation method

MethodInvocation<O> methodInvocation(
  1. ParameterProvider parameterProvider
)

Creates a MethodInvocation using parameterProvider.

Implementation

MethodInvocation<O> methodInvocation(ParameterProvider parameterProvider) {
  final normalParameters = this.normalParameters;
  final optionalParameters = this.optionalParameters;
  final namedParameters = this.namedParameters;

  var parameterResolver = _ParameterResolver(
      parameterProvider, normalParameters.length, optionalParameters.length);

  var normalValues = parameterResolver.resolveNormal(normalParameters);
  var optionalValues = parameterResolver.resolveOptional(optionalParameters);
  var namedValues = parameterResolver.resolveNamed(namedParameters);

  // If has some unresolved parameter tries to resolve it again.
  // This will allow use of the current cached entities in
  // a `JsonEntityCache` (if in use).
  if (_hasUnresolvedParameterValue(normalValues) ||
      _hasUnresolvedParameterValue(optionalValues) ||
      _hasUnresolvedParameterValue(namedValues.entries)) {
    normalValues = parameterResolver.resolveNormal(normalParameters);
    optionalValues = parameterResolver.resolveOptional(optionalParameters);
    namedValues = parameterResolver.resolveNamed(namedParameters);

    if (_hasUnresolvedParameterValue(normalValues) ||
        _hasUnresolvedParameterValue(optionalValues) ||
        _hasUnresolvedParameterValue(namedValues.entries)) {
      throw StateError(
          "Unresolved parameter value> normal: ${normalValues.asStringSimple} ; "
          "optional: ${optionalValues.asStringSimple} ; "
          "named: ${namedValues.entries.asStringSimple}");
    }
  }

  while (optionalValues.isNotEmpty) {
    var lastIndex = optionalValues.length - 1;

    var entry = optionalValues[lastIndex];
    var value = entry.value;
    var isAbsent = value.isAbsentParameterValue;
    if (value != null && !isAbsent) break;

    var lastParam = this.optionalParameters[lastIndex];

    if (isAbsent) {
      optionalValues.removeAt(lastIndex);
    } else {
      if (lastParam.hasDefaultValue || lastParam.nullable) {
        optionalValues.removeAt(lastIndex);
      } else {
        throw StateError(
            "Invalid optional parameter value: $optionalValues != ${this.optionalParameters}");
      }
    }
  }

  for (var k in namedValues.keys.toList(growable: false)) {
    var p = namedParameters[k]!;
    Object? value = namedValues[k];

    var isAbsent = value.isAbsentParameterValue;

    if ((value == null || isAbsent) &&
        (p.nullable || p.hasDefaultValue) &&
        !p.required) {
      namedValues.remove(k);
    } else if (isAbsent) {
      throw StateError("Required named parameter `${p.name}` "
          "${p.hasJsonNameAlias ? '(jsonName: p.jsonName)' : ''} "
          "for `MethodInvocation[${classReflection.classType}.$name]`: $p");
    }
  }

  _removeAbsentParameterValue(normalValues);
  _removeAbsentParameterValue(optionalValues);

  var normalParametersValues = normalValues.map((e) => e.value).toList();
  var optionalParametersValues = optionalValues.map((e) => e.value).toList();

  var positionalParametersNames = <String>[
    ...normalValues.map((e) => e.key),
    ...optionalValues.map((e) => e.key),
  ];

  return MethodInvocation<O>.withPositionalParametersNames(
    classReflection.classType,
    name,
    positionalParametersNames,
    normalParametersValues,
    optionalParametersValues,
    namedValues,
  );
}