blob: d248946610e9efde7e1fec287c9f46496849b4e1 [file] [log] [blame]
// 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;
late final DynamicTypeDeclarationBuilder dynamicDeclaration =
new DynamicTypeDeclarationBuilder(
const DynamicType(), loader.coreLibrary, -1);
late final VoidTypeDeclarationBuilder voidDeclaration =
new VoidTypeDeclarationBuilder(const VoidType(), loader.coreLibrary, -1);
late final NeverTypeDeclarationBuilder neverDeclaration =
new NeverTypeDeclarationBuilder(
const NeverType.nonNullable(), loader.coreLibrary, -1);
late final NullTypeDeclarationBuilder nullDeclaration =
new NullTypeDeclarationBuilder(const NullType(), loader.coreLibrary, -1);
late final FutureOrTypeDeclarationBuilder futureOrDeclaration =
new FutureOrTypeDeclarationBuilder(
new FutureOrType(const DynamicType(), Nullability.nonNullable),
loader.coreLibrary,
-1);
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.forDartType(
node, dynamicDeclaration, const NullabilityBuilder.inherent());
}
@override
TypeBuilder visitVoidType(VoidType node) {
// 'void' is always nullable.
return new NamedTypeBuilder.forDartType(
node, voidDeclaration, const NullabilityBuilder.inherent());
}
@override
TypeBuilder visitNeverType(NeverType node) {
return new NamedTypeBuilder.forDartType(node, neverDeclaration,
new NullabilityBuilder.fromNullability(node.nullability));
}
@override
TypeBuilder visitNullType(NullType node) {
return new NamedTypeBuilder.forDartType(
node, nullDeclaration, const NullabilityBuilder.inherent());
}
@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.forDartType(
node, cls, new NullabilityBuilder.fromNullability(node.nullability),
arguments: arguments);
}
@override
TypeBuilder visitExtensionType(ExtensionType node) {
throw "Not implemented";
}
@override
TypeBuilder visitFutureOrType(FutureOrType node) {
TypeBuilder argument = node.typeArgument.accept(this);
return new NamedTypeBuilder.forDartType(node, futureOrDeclaration,
new NullabilityBuilder.fromNullability(node.nullability),
arguments: [argument]);
}
@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<ParameterBuilder> formals = new List<ParameterBuilder>.filled(
positionalParameters.length + namedParameters.length,
dummyFormalParameterBuilder);
for (int i = 0; i < positionalParameters.length; i++) {
TypeBuilder type = positionalParameters[i].accept(this);
FormalParameterKind kind = FormalParameterKind.requiredPositional;
if (i >= node.requiredParameterCount) {
kind = FormalParameterKind.optionalPositional;
}
formals[i] = new FunctionTypeParameterBuilder(
/* metadata = */ null, kind, type, /* name = */ null);
}
for (int i = 0; i < namedParameters.length; i++) {
NamedType parameter = namedParameters[i];
TypeBuilder type = parameter.type.accept(this);
FormalParameterKind kind = parameter.isRequired
? FormalParameterKind.requiredNamed
: FormalParameterKind.optionalNamed;
formals[i + positionalParameters.length] =
new FunctionTypeParameterBuilder(
/* metadata = */ null, kind, type, parameter.name);
}
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.fromTypeDeclarationBuilder(
new TypeVariableBuilder.fromKernel(parameter, library),
new NullabilityBuilder.fromNullability(node.nullability),
instanceTypeVariableAccess: InstanceTypeVariableAccessState.Allowed,
type: node);
}
@override
TypeBuilder visitIntersectionType(IntersectionType node) {
throw "Not implemented";
}
@override
TypeBuilder visitTypedefType(TypedefType node) {
throw "Not implemented";
}
}