| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:front_end/src/codes/diagnostic.dart' as diag; | |
| import 'package:kernel/ast.dart'; | |
| import 'package:kernel/class_hierarchy.dart'; | |
| import '../builder/formal_parameter_builder.dart'; | |
| import '../builder/omitted_type_builder.dart'; | |
| import '../builder/type_builder.dart'; | |
| import '../type_inference/type_inference_engine.dart' | |
| show IncludesTypeParametersNonCovariantly; | |
| import 'source_library_builder.dart'; | |
| import 'source_type_parameter_builder.dart'; | |
| /// Builds the [TypeParameter]s for [declaredTypeParameters] and the parameter | |
| /// [Variable]s for [declaredFormals] and adds them to [function]. | |
| /// | |
| /// If [classTypeParameters] the bounds on type parameters and formal parameter | |
| /// types will be marked as `isCovariantByClass` depending on their use of the | |
| /// [classTypeParameters]. | |
| /// | |
| /// If [supportsTypeParameters] is false, declared type parameters are not added | |
| /// to the function. This is done to avoid adding type parameters to | |
| /// [Constructor]s which don't support them. | |
| void buildTypeParametersAndFormals( | |
| SourceLibraryBuilder libraryBuilder, | |
| FunctionNode function, | |
| List<SourceNominalParameterBuilder>? declaredTypeParameters, | |
| List<FormalParameterBuilder>? declaredFormals, { | |
| required List<TypeParameter>? classTypeParameters, | |
| required bool supportsTypeParameters, | |
| }) { | |
| IncludesTypeParametersNonCovariantly? needsCheckVisitor; | |
| if (classTypeParameters != null && classTypeParameters.isNotEmpty) { | |
| needsCheckVisitor = new IncludesTypeParametersNonCovariantly( | |
| classTypeParameters, | |
| // We are checking the parameter types which are in a | |
| // contravariant position. | |
| initialVariance: Variance.contravariant, | |
| ); | |
| } | |
| if (declaredTypeParameters != null) { | |
| for (int i = 0; i < declaredTypeParameters.length; i++) { | |
| SourceNominalParameterBuilder t = declaredTypeParameters[i]; | |
| TypeParameter parameter = t.parameter; | |
| if (needsCheckVisitor != null) { | |
| if (parameter.bound.accept(needsCheckVisitor)) { | |
| parameter.isCovariantByClass = true; | |
| } | |
| } | |
| } | |
| if (supportsTypeParameters) { | |
| final TypeParameterList existing = function.typeParameters; | |
| final int existingLength = existing.length; | |
| function.typeParameters = new TypeParameterList.generate( | |
| existingLength + declaredTypeParameters.length, | |
| (int i) => i < existingLength | |
| ? existing[i] | |
| : declaredTypeParameters[i - existingLength].parameter, | |
| ); | |
| } | |
| setParents(function.typeParameters, function); | |
| } | |
| if (declaredFormals != null) { | |
| List<PositionalParameter> positionalParameters = [ | |
| ...function.positionalParameters, | |
| ]; | |
| List<NamedParameter> namedParameters = [...function.namedParameters]; | |
| for (int i = 0; i < declaredFormals.length; i++) { | |
| FormalParameterBuilder formal = declaredFormals[i]; | |
| FunctionParameter parameter = formal | |
| .build(libraryBuilder) | |
| .functionParameter; | |
| if (needsCheckVisitor != null) { | |
| if (parameter.type.accept(needsCheckVisitor)) { | |
| parameter.isCovariantByClass = true; | |
| } | |
| } | |
| switch (parameter) { | |
| case PositionalParameter(): | |
| positionalParameters.add(parameter); | |
| case NamedParameter(): | |
| namedParameters.add(parameter); | |
| } | |
| parameter.parent = function; | |
| if (formal.isRequiredPositional) { | |
| function.requiredParameterCount++; | |
| } | |
| // Required named parameters can't have default values. | |
| if (formal.isRequiredNamed && formal.hasDeclaredDefaultValue) { | |
| libraryBuilder.addProblem( | |
| diag.requiredNamedParameterHasDefaultValueError.withArguments( | |
| parameterName: formal.name, | |
| ), | |
| formal.fileOffset, | |
| formal.name.length, | |
| formal.fileUri, | |
| ); | |
| } | |
| } | |
| function.positionalParameters = new PositionalParameterList.from( | |
| positionalParameters, | |
| ); | |
| function.namedParameters = new NamedParameterList.from(namedParameters); | |
| } | |
| } | |
| extension FormalsMethods on List<FormalParameterBuilder> { | |
| /// Ensures the type of each of the formals is inferred. | |
| void infer(ClassHierarchy classHierarchy) { | |
| for (FormalParameterBuilder formal in this) { | |
| TypeBuilder formalType = formal.type; | |
| if (formalType is InferableTypeBuilder) { | |
| formalType.inferType(classHierarchy); | |
| } | |
| } | |
| } | |
| } |