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).
  var normalValuesHasUnresolved = _hasUnresolvedParameterValue(normalValues);
  var optionalValuesHasUnresolved =
      _hasUnresolvedParameterValue(optionalValues);
  var namedValuesHasUnresolved =
      _hasUnresolvedParameterValue(namedValues.entries);

  if (normalValuesHasUnresolved ||
      optionalValuesHasUnresolved ||
      namedValuesHasUnresolved) {
    if (normalValuesHasUnresolved) {
      normalValues = parameterResolver.resolveNormal(normalParameters);
    }

    if (optionalValuesHasUnresolved) {
      optionalValues = parameterResolver.resolveOptional(optionalParameters);
    }

    if (namedValuesHasUnresolved) {
      namedValues = parameterResolver.resolveNamed(namedParameters);
    }

    if (_hasUnresolvedParameterValueRequired(normalValues) ||
        _hasUnresolvedParameterValueRequired(optionalValues) ||
        _hasUnresolvedParameterValueRequired(namedValues.entries)) {
      throw UnresolvedParameterError(
          this, normalValues, optionalValues, namedValues);
    }
  }

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

    var entry = optionalValues[lastIndex];
    var value = entry.value;
    var isAbsent =
        value.isAbsentParameterValue || value.isUnresolvedParameterValue;
    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}");
      }
    }
  }

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

      var isAbsent =
          value.isAbsentParameterValue || value.isUnresolvedParameterValue;

      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();

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