| // Copyright (c) 2019, 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. |
| |
| library fasta.type_builder_computer; |
| |
| import 'package:_fe_analyzer_shared/src/parser/parser.dart' |
| show FormalParameterKind; |
| |
| import 'package:kernel/ast.dart'; |
| |
| import '../builder/class_builder.dart'; |
| import '../builder/dynamic_type_declaration_builder.dart'; |
| import '../builder/fixed_type_builder.dart'; |
| import '../builder/formal_parameter_builder.dart'; |
| import '../builder/function_type_builder.dart'; |
| import '../builder/future_or_type_declaration_builder.dart'; |
| import '../builder/library_builder.dart'; |
| import '../builder/named_type_builder.dart'; |
| import '../builder/never_type_declaration_builder.dart'; |
| import '../builder/null_type_declaration_builder.dart'; |
| import '../builder/nullability_builder.dart'; |
| import '../builder/type_builder.dart'; |
| import '../builder/type_variable_builder.dart'; |
| import '../builder/void_type_declaration_builder.dart'; |
| |
| import '../kernel/utils.dart'; |
| |
| import '../loader.dart' show Loader; |
| |
| class TypeBuilderComputer implements DartTypeVisitor<TypeBuilder> { |
| final Loader loader; |
| |
| const TypeBuilderComputer(this.loader); |
| |
| @override |
| TypeBuilder defaultDartType(DartType node) { |
| throw "Unsupported"; |
| } |
| |
| @override |
| TypeBuilder visitInvalidType(InvalidType node) { |
| return new FixedTypeBuilder( |
| node, /* fileUri = */ null, /* charOffset = */ null); |
| } |
| |
| @override |
| TypeBuilder visitDynamicType(DynamicType node) { |
| // 'dynamic' is always nullable. |
| return new NamedTypeBuilder("dynamic", const NullabilityBuilder.nullable(), |
| /* arguments = */ null, /* fileUri = */ null, /* charOffset = */ null, |
| instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected) |
| ..bind(new DynamicTypeDeclarationBuilder( |
| const DynamicType(), loader.coreLibrary, -1)); |
| } |
| |
| @override |
| TypeBuilder visitVoidType(VoidType node) { |
| // 'void' is always nullable. |
| return new NamedTypeBuilder("void", const NullabilityBuilder.nullable(), |
| /* arguments = */ null, /* fileUri = */ null, /* charOffset = */ null, |
| instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected) |
| ..bind(new VoidTypeDeclarationBuilder( |
| const VoidType(), loader.coreLibrary, -1)); |
| } |
| |
| @override |
| TypeBuilder visitNeverType(NeverType node) { |
| return new NamedTypeBuilder( |
| "Never", |
| new NullabilityBuilder.fromNullability(node.nullability), |
| /* arguments = */ null, |
| /* fileUri = */ null, |
| /* charOffset = */ null, |
| instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected) |
| ..bind(new NeverTypeDeclarationBuilder(node, loader.coreLibrary, -1)); |
| } |
| |
| @override |
| TypeBuilder visitNullType(NullType node) { |
| return new NamedTypeBuilder("Null", new NullabilityBuilder.nullable(), |
| /* arguments = */ null, /* fileUri = */ null, /* charOffset = */ null, |
| instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected) |
| ..bind(new NullTypeDeclarationBuilder(node, loader.coreLibrary, -1)); |
| } |
| |
| @override |
| TypeBuilder visitInterfaceType(InterfaceType node) { |
| ClassBuilder cls = |
| loader.computeClassBuilderFromTargetClass(node.classNode); |
| List<TypeBuilder>? arguments; |
| List<DartType> kernelArguments = node.typeArguments; |
| if (kernelArguments.isNotEmpty) { |
| arguments = new List<TypeBuilder>.generate( |
| kernelArguments.length, (int i) => kernelArguments[i].accept(this), |
| growable: false); |
| } |
| return new NamedTypeBuilder( |
| cls.name, |
| new NullabilityBuilder.fromNullability(node.nullability), |
| arguments, |
| /* fileUri = */ null, |
| /* charOffset = */ null, |
| instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected) |
| ..bind(cls); |
| } |
| |
| @override |
| TypeBuilder visitExtensionType(ExtensionType node) { |
| throw "Not implemented"; |
| } |
| |
| @override |
| TypeBuilder visitFutureOrType(FutureOrType node) { |
| TypeBuilder argument = node.typeArgument.accept(this); |
| return new NamedTypeBuilder( |
| "FutureOr", |
| new NullabilityBuilder.fromNullability(node.nullability), |
| [argument], |
| /* fileUri = */ null, |
| /* charOffset = */ null, |
| instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected) |
| ..bind(new FutureOrTypeDeclarationBuilder(node, loader.coreLibrary, -1)); |
| } |
| |
| @override |
| TypeBuilder visitFunctionType(FunctionType node) { |
| TypeBuilder returnType = node.returnType.accept(this); |
| // We could compute the type variables here. However, the current |
| // implementation of [visitTypeParameterType] is sufficient. |
| List<TypeVariableBuilder>? typeVariables = null; |
| List<DartType> positionalParameters = node.positionalParameters; |
| List<NamedType> namedParameters = node.namedParameters; |
| List<FormalParameterBuilder> formals = |
| new List<FormalParameterBuilder>.filled( |
| positionalParameters.length + namedParameters.length, |
| dummyFormalParameterBuilder); |
| for (int i = 0; i < positionalParameters.length; i++) { |
| TypeBuilder type = positionalParameters[i].accept(this); |
| FormalParameterKind kind = FormalParameterKind.mandatory; |
| if (i >= node.requiredParameterCount) { |
| kind = FormalParameterKind.optionalPositional; |
| } |
| formals[i] = new FormalParameterBuilder( |
| /* metadata = */ null, |
| /* modifiers = */ 0, |
| type, |
| /* name = */ '', |
| /* compilationUnit = */ null, |
| /* charOffset = */ TreeNode.noOffset) |
| ..kind = kind; |
| } |
| for (int i = 0; i < namedParameters.length; i++) { |
| NamedType parameter = namedParameters[i]; |
| TypeBuilder type = parameter.type.accept(this); |
| formals[i + positionalParameters.length] = new FormalParameterBuilder( |
| /* metadata = */ null, |
| /* modifiers = */ 0, |
| type, |
| parameter.name, |
| /* compilationUnit = */ null, |
| /* charOffset = */ TreeNode.noOffset) |
| ..kind = FormalParameterKind.optionalNamed; |
| } |
| return new FunctionTypeBuilder( |
| returnType, |
| typeVariables, |
| formals, |
| new NullabilityBuilder.fromNullability(node.nullability), |
| /* fileUri = */ null, |
| /* charOffset = */ TreeNode.noOffset); |
| } |
| |
| @override |
| TypeBuilder visitTypeParameterType(TypeParameterType node) { |
| TypeParameter parameter = node.parameter; |
| TreeNode? kernelClassOrTypeDef = parameter.parent; |
| Library? kernelLibrary; |
| if (kernelClassOrTypeDef is Class) { |
| kernelLibrary = kernelClassOrTypeDef.enclosingLibrary; |
| } else if (kernelClassOrTypeDef is Typedef) { |
| kernelLibrary = kernelClassOrTypeDef.enclosingLibrary; |
| } |
| LibraryBuilder library = |
| loader.lookupLibraryBuilder(kernelLibrary!.importUri)!; |
| return new NamedTypeBuilder( |
| parameter.name!, |
| new NullabilityBuilder.fromNullability(node.nullability), |
| /* arguments = */ null, |
| /* fileUri = */ null, |
| /* charOffset = */ null, |
| instanceTypeVariableAccess: InstanceTypeVariableAccessState.Allowed) |
| ..bind(new TypeVariableBuilder.fromKernel(parameter, library)); |
| } |
| |
| @override |
| TypeBuilder visitTypedefType(TypedefType node) { |
| throw "Not implemented"; |
| } |
| } |