getBestConstructorsFor method
Returns a List of the best ConstructorReflection for requiredParameters
, optionalParameters
,
nullableParameters
and presentParameters
.
Implementation
List<ConstructorReflection<O>> getBestConstructorsFor(
{Iterable<String> requiredParameters = const <String>[],
Iterable<String> optionalParameters = const <String>[],
Iterable<String> nullableParameters = const <String>[],
Iterable<String> presentParameters = const <String>[],
bool allowEmptyConstructors = true,
bool jsonName = false}) {
if (nullableParameters is! List && nullableParameters is! Set) {
nullableParameters = nullableParameters.toList(growable: false);
}
var constructors = allConstructors().toList();
if (constructors.isEmpty) return <ConstructorReflection<O>>[];
if (!allowEmptyConstructors) {
var emptyConstructors = constructors
.where((c) =>
c.parametersLength == 0 ||
(c.normalParameters.isEmpty &&
c.optionalParameters.where((c) => c.required).isEmpty &&
c.namedParameters.values.where((c) => c.required).isEmpty))
.toList();
constructors =
constructors.where((c) => !emptyConstructors.contains(c)).toList();
if (constructors.isEmpty) return <ConstructorReflection<O>>[];
}
var presentParametersResolved = presentParameters.toSet();
String paramNameResolver(ParameterReflection p, String name) {
var f = field(p.name);
var alias = f?.jsonFieldAliasAnnotations.alias;
return alias ?? name;
}
var paramNameResolverJson = jsonName ? paramNameResolver : null;
var invalidConstructors = constructors.where((c) {
var paramsRequired = c
.parametersNamesWhere((p) => p.required && !p.nullable,
jsonName: jsonName, nameResolver: paramNameResolverJson)
.toList();
return _elementsInCount(
presentParameters, paramsRequired, _nameNormalizer) <
paramsRequired.length;
}).toList();
if (invalidConstructors.isNotEmpty) {
constructors.removeWhere((c) => invalidConstructors.contains(c));
if (constructors.isEmpty) return <ConstructorReflection<O>>[];
}
if (requiredParameters.isNotEmpty) {
var constructorsWithRequired = constructors.where((c) {
var paramsAll = c
.parametersNamesWhere((p) => true,
jsonName: jsonName, nameResolver: paramNameResolverJson)
.toList();
return _elementsInCount<String>(
requiredParameters, paramsAll, _nameNormalizer) ==
requiredParameters.length;
}).toList();
constructors = constructorsWithRequired;
if (constructors.isEmpty) return <ConstructorReflection<O>>[];
presentParametersResolved.addAll(requiredParameters);
}
if (nullableParameters.isNotEmpty) {
var constructorsWithNullables = constructors.where((c) {
var paramsNullable = c
.parametersNamesWhere((p) => p.nullable || !p.required,
jsonName: jsonName, nameResolver: paramNameResolverJson)
.toList();
return _elementsInCount(
nullableParameters, paramsNullable, _nameNormalizer) ==
nullableParameters.length;
}).toList();
constructors = constructorsWithNullables;
if (constructors.isEmpty) return <ConstructorReflection<O>>[];
presentParametersResolved.addAll(nullableParameters);
}
presentParametersResolved.addAll(optionalParameters);
constructors = constructors.where((c) {
var paramsRequired = c
.parametersNamesWhere((p) => p.required,
jsonName: jsonName, nameResolver: paramNameResolverJson)
.toList();
return _elementsInCount<String>(
presentParametersResolved, paramsRequired, _nameNormalizer) ==
paramsRequired.length;
}).toList();
if (constructors.length <= 1) {
return constructors;
}
var constructorsInfo = Map.fromEntries(constructors.map((c) {
var requiredCount =
c.getParametersByNames(requiredParameters, jsonName: jsonName).length;
var optionalCount =
c.getParametersByNames(optionalParameters, jsonName: jsonName).length;
return MapEntry(c, [requiredCount, optionalCount]);
}));
constructors.sort((c1, c2) {
var i1 = constructorsInfo[c1]!;
var i2 = constructorsInfo[c2]!;
var req1 = i1[0];
var req2 = i2[0];
var cmp = req2.compareTo(req1);
if (cmp == 0) {
var opt1 = i1[1];
var opt2 = i2[1];
cmp = opt2.compareTo(opt1);
}
return cmp;
});
return constructors;
}