| // 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); |
| } |