blob: 4387d1a5ce85864b1f3eab4c1ade82978d9fc22b [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.
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/type_environment.dart';
import '../base/messages.dart';
import '../base/problems.dart';
import '../base/scope.dart';
import '../builder/builder.dart';
import '../builder/builder_mixins.dart';
import '../builder/constructor_builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/factory_builder.dart';
import '../builder/library_builder.dart';
import '../builder/type_builder.dart';
import '../kernel/type_algorithms.dart';
import 'source_library_builder.dart';
import 'source_loader.dart';
import 'source_member_builder.dart';
import 'source_type_parameter_builder.dart';
abstract class SourceDeclarationBuilder implements IDeclarationBuilder {
void buildScopes(LibraryBuilder coreLibrary);
int computeDefaultTypes(ComputeDefaultTypeContext context);
}
mixin SourceDeclarationBuilderMixin
implements DeclarationBuilderMixin, SourceDeclarationBuilder {
@override
SourceLibraryBuilder get libraryBuilder;
@override
List<SourceNominalParameterBuilder>? get typeParameters;
@override
Uri get fileUri;
/// Builds the [Extension] for this extension build and inserts the members
/// into the [Library] of [libraryBuilder].
///
/// [addMembersToLibrary] is `true` if the extension members should be added
/// to the library. This is `false` if the extension is in conflict with
/// another library member. In this case, the extension member should not be
/// added to the library to avoid name clashes with other members in the
/// library.
void buildInternal(LibraryBuilder coreLibrary,
{required bool addMembersToLibrary}) {
ClassBuilder objectClassBuilder =
coreLibrary.lookupLocalMember('Object', required: true) as ClassBuilder;
void buildBuilders(NamedBuilder declaration) {
String name = declaration.name;
if (!name.startsWith('_') &&
!(declaration is ConstructorBuilder ||
declaration is FactoryBuilder)) {
Builder? objectGetter = objectClassBuilder.lookupLocalMember(name);
Builder? objectSetter =
objectClassBuilder.lookupLocalMember(name, setter: true);
if (objectGetter != null && !objectGetter.isStatic ||
// Coverage-ignore(suite): Not run.
objectSetter != null && !objectSetter.isStatic) {
libraryBuilder.addProblem(
// TODO(johnniwinther): Use a different error message for
// extension type declarations.
templateExtensionMemberConflictsWithObjectMember
.withArguments(name),
declaration.fileOffset,
name.length,
declaration.fileUri);
}
}
if (declaration.parent != this) {
// Coverage-ignore-block(suite): Not run.
if (fileUri != declaration.parent!.fileUri) {
unexpected("$fileUri", "${declaration.parent!.fileUri}", fileOffset,
fileUri);
} else {
unexpected(fullNameForErrors, declaration.parent!.fullNameForErrors,
fileOffset, fileUri);
}
} else if (declaration is SourceMemberBuilder) {
SourceMemberBuilder memberBuilder = declaration;
memberBuilder.buildOutlineNodes((
{required Member member,
Member? tearOff,
required BuiltMemberKind kind}) {
_buildMember(memberBuilder, member, tearOff, kind,
addMembersToLibrary: addMembersToLibrary);
});
} else {
unhandled("${declaration.runtimeType}", "buildBuilders",
declaration.fileOffset, declaration.fileUri);
}
}
unfilteredMembersIterator.forEach(buildBuilders);
unfilteredConstructorsIterator.forEach(buildBuilders);
}
int buildBodyNodes({required bool addMembersToLibrary}) {
int count = 0;
Iterator<SourceMemberBuilder> iterator =
filteredMembersIterator<SourceMemberBuilder>(includeDuplicates: false)
.join(filteredConstructorsIterator<SourceMemberBuilder>(
includeDuplicates: false));
while (iterator.moveNext()) {
SourceMemberBuilder declaration = iterator.current;
count += declaration.buildBodyNodes(
// Coverage-ignore(suite): Not run.
(
{required Member member,
Member? tearOff,
required BuiltMemberKind kind}) {
_buildMember(declaration, member, tearOff, kind,
addMembersToLibrary: addMembersToLibrary);
});
}
return count;
}
@override
int computeDefaultTypes(ComputeDefaultTypeContext context) {
bool hasErrors = context.reportNonSimplicityIssues(this, typeParameters);
int count = context.computeDefaultTypesForVariables(typeParameters,
inErrorRecovery: hasErrors);
Iterator<SourceMemberBuilder> constructorIterator =
filteredConstructorsIterator<SourceMemberBuilder>(
includeDuplicates: false);
while (constructorIterator.moveNext()) {
count += constructorIterator.current
.computeDefaultTypes(context, inErrorRecovery: hasErrors);
}
Iterator<SourceMemberBuilder> memberIterator =
filteredMembersIterator(includeDuplicates: false);
while (memberIterator.moveNext()) {
count += memberIterator.current
.computeDefaultTypes(context, inErrorRecovery: hasErrors);
}
return count;
}
void checkTypesInOutline(TypeEnvironment typeEnvironment) {
Iterator<SourceMemberBuilder> memberIterator =
filteredMembersIterator(includeDuplicates: false);
while (memberIterator.moveNext()) {
memberIterator.current
.checkTypes(libraryBuilder, nameSpace, typeEnvironment);
}
Iterator<SourceMemberBuilder> constructorIterator =
filteredConstructorsIterator(includeDuplicates: false);
while (constructorIterator.moveNext()) {
constructorIterator.current
.checkTypes(libraryBuilder, nameSpace, typeEnvironment);
}
}
void _buildMember(SourceMemberBuilder memberBuilder, Member member,
Member? tearOff, BuiltMemberKind memberKind,
{required bool addMembersToLibrary}) {
if (!memberBuilder.isDuplicate) {
if (memberKind == BuiltMemberKind.ExtensionTypeRepresentationField) {
addMemberInternal(memberBuilder, memberKind, member, tearOff);
} else {
if (addMembersToLibrary) {
Reference addMember(Member member) {
if (member is Field) {
libraryBuilder.library.addField(member);
return member.fieldReference;
} else if (member is Procedure) {
libraryBuilder.library.addProcedure(member);
return member.reference;
} else {
unhandled("${member.runtimeType}", "buildBuilders",
member.fileOffset, member.fileUri);
}
}
Reference memberReference = addMember(member);
Reference? tearOffReference;
if (tearOff != null) {
tearOffReference = addMember(tearOff);
}
addMemberDescriptorInternal(
memberBuilder, memberKind, memberReference, tearOffReference);
} else {
// Still set parent to avoid crashes.
member.parent = libraryBuilder.library;
}
}
}
}
/// Adds [member] and [tearOff] to this declaration.
void addMemberInternal(SourceMemberBuilder memberBuilder,
BuiltMemberKind memberKind, Member member, Member? tearOff);
/// Adds a descriptor for [member] to this declaration.
void addMemberDescriptorInternal(
SourceMemberBuilder memberBuilder,
BuiltMemberKind memberKind,
Reference memberReference,
Reference? tearOffReference);
@override
List<DartType> buildAliasedTypeArguments(LibraryBuilder library,
List<TypeBuilder>? arguments, ClassHierarchyBase? hierarchy) {
if (arguments == null && typeParameters == null) {
return <DartType>[];
}
if (arguments == null && typeParameters != null) {
List<DartType> result =
new List<DartType>.generate(typeParameters!.length, (int i) {
if (typeParameters![i].defaultType == null) {
throw 'here';
}
return typeParameters![i].defaultType!.buildAliased(
library, TypeUse.defaultTypeAsTypeArgument, hierarchy);
}, growable: true);
return result;
}
if (arguments != null && arguments.length != typeParametersCount) {
// Coverage-ignore-block(suite): Not run.
assert(libraryBuilder.loader.assertProblemReportedElsewhere(
"SourceDeclarationBuilderMixin.buildAliasedTypeArguments: "
"the numbers of type parameters and type arguments don't match.",
expectedPhase: CompilationPhaseForProblemReporting.outline));
return unhandled(
templateTypeArgumentMismatch
.withArguments(typeParametersCount)
.problemMessage,
"buildTypeArguments",
-1,
null);
}
assert(arguments!.length == typeParametersCount);
List<DartType> result =
new List<DartType>.generate(arguments!.length, (int i) {
return arguments[i]
.buildAliased(library, TypeUse.typeArgument, hierarchy);
}, growable: true);
return result;
}
@override
int get typeParametersCount => typeParameters?.length ?? 0;
}