blob: 6563dd0c208e7eef6df8102f47da7af23e202670 [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 '../builder/builder.dart';
import '../builder/builder_mixins.dart';
import '../builder/class_builder.dart';
import '../builder/declaration_builder.dart';
import '../builder/library_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/procedure_builder.dart';
import '../fasta_codes.dart'
show templateExtensionMemberConflictsWithObjectMember;
import '../kernel/kernel_helper.dart';
import '../problems.dart';
import '../scope.dart';
import '../util/helpers.dart';
import 'source_field_builder.dart';
import 'source_library_builder.dart';
import 'source_member_builder.dart';
import 'source_procedure_builder.dart';
mixin SourceDeclarationBuilderMixin
implements DeclarationBuilder, DeclarationBuilderMixin {
@override
SourceLibraryBuilder get libraryBuilder;
@override
Uri get fileUri;
/// Returns the [Annotatable] node that holds the annotations declared on
/// this declaration or its augmentations.
Annotatable get annotatable;
/// 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}) {
SourceLibraryBuilder.checkMemberConflicts(libraryBuilder, scope,
checkForInstanceVsStaticConflict: true,
checkForMethodVsSetterConflict: true);
ClassBuilder objectClassBuilder =
coreLibrary.lookupLocalMember('Object', required: true) as ClassBuilder;
void buildBuilders(String name, Builder declaration) {
Builder? objectGetter = objectClassBuilder.lookupLocalMember(name);
Builder? objectSetter =
objectClassBuilder.lookupLocalMember(name, setter: true);
if (objectGetter != null && !objectGetter.isStatic ||
objectSetter != null && !objectSetter.isStatic) {
addProblem(
// TODO(johnniwinther): Use a different error message for views.
templateExtensionMemberConflictsWithObjectMember
.withArguments(name),
declaration.charOffset,
name.length);
}
if (declaration.parent != this) {
if (fileUri != declaration.parent!.fileUri) {
unexpected("$fileUri", "${declaration.parent!.fileUri}", charOffset,
fileUri);
} else {
unexpected(fullNameForErrors, declaration.parent!.fullNameForErrors,
charOffset, fileUri);
}
} else if (declaration is SourceMemberBuilder) {
SourceMemberBuilder memberBuilder = declaration;
memberBuilder
.buildOutlineNodes((Member member, BuiltMemberKind memberKind) {
_buildMember(memberBuilder, member, memberKind,
addMembersToLibrary: addMembersToLibrary);
});
} else {
unhandled("${declaration.runtimeType}", "buildBuilders",
declaration.charOffset, declaration.fileUri);
}
}
scope.unfilteredNameIterator.forEach(buildBuilders);
}
int buildBodyNodes({required bool addMembersToLibrary}) {
int count = 0;
Iterator<SourceMemberBuilder> iterator =
scope.filteredIterator<SourceMemberBuilder>(
parent: this, includeDuplicates: false, includeAugmentations: true);
while (iterator.moveNext()) {
SourceMemberBuilder declaration = iterator.current;
count +=
declaration.buildBodyNodes((Member member, BuiltMemberKind kind) {
_buildMember(declaration, member, kind,
addMembersToLibrary: addMembersToLibrary);
});
}
return count;
}
void checkTypesInOutline(TypeEnvironment typeEnvironment) {
forEach((String name, Builder builder) {
if (builder is SourceFieldBuilder) {
// Check fields.
libraryBuilder.checkTypesInField(builder, typeEnvironment);
} else if (builder is SourceProcedureBuilder) {
// Check procedures
libraryBuilder.checkTypesInFunctionBuilder(builder, typeEnvironment);
if (builder.isGetter) {
Builder? setterDeclaration =
scope.lookupLocalMember(builder.name, setter: true);
if (setterDeclaration != null) {
libraryBuilder.checkGetterSetterTypes(builder,
setterDeclaration as ProcedureBuilder, typeEnvironment);
}
}
} else {
assert(false, "Unexpected member: $builder.");
}
});
}
void buildOutlineExpressions(
ClassHierarchy classHierarchy,
List<DelayedActionPerformer> delayedActionPerformers,
List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
MetadataBuilder.buildAnnotations(annotatable, metadata, libraryBuilder,
this, null, fileUri, libraryBuilder.scope);
if (typeParameters != null) {
for (int i = 0; i < typeParameters!.length; i++) {
typeParameters![i].buildOutlineExpressions(libraryBuilder, this, null,
classHierarchy, delayedActionPerformers, scope.parent!);
}
}
Iterator<SourceMemberBuilder> iterator =
scope.filteredIterator<SourceMemberBuilder>(
parent: this, includeDuplicates: false, includeAugmentations: true);
while (iterator.moveNext()) {
iterator.current.buildOutlineExpressions(
classHierarchy, delayedActionPerformers, delayedDefaultValueCloners);
}
}
void _buildMember(SourceMemberBuilder memberBuilder, Member member,
BuiltMemberKind memberKind,
{required bool addMembersToLibrary}) {
if (addMembersToLibrary &&
!memberBuilder.isPatch &&
!memberBuilder.isDuplicate &&
!memberBuilder.isConflictingSetter) {
Reference memberReference;
if (member is Field) {
libraryBuilder.library.addField(member);
memberReference = member.fieldReference;
} else if (member is Procedure) {
libraryBuilder.library.addProcedure(member);
memberReference = member.reference;
} else {
unhandled("${member.runtimeType}", "buildBuilders", member.fileOffset,
member.fileUri);
}
addMemberDescriptorInternal(
memberBuilder, member, memberKind, memberReference);
}
}
/// Adds a descriptor for [member] to this declaration.
void addMemberDescriptorInternal(SourceMemberBuilder memberBuilder,
Member member, BuiltMemberKind memberKind, Reference memberReference);
}