| // Copyright (c) 2021, 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' show ClassHierarchyMembers; |
| |
| import '../../builder/declaration_builders.dart'; |
| import '../../builder/formal_parameter_builder.dart'; |
| import '../../builder/type_builder.dart'; |
| import '../../source/source_class_builder.dart'; |
| import 'class_member.dart'; |
| import 'delayed.dart'; |
| import 'extension_type_members.dart'; |
| import 'hierarchy_builder.dart'; |
| import 'members_node.dart'; |
| |
| class ClassMembersBuilder implements ClassHierarchyMembers { |
| final ClassHierarchyBuilder hierarchyBuilder; |
| |
| final Map<Class, ClassMembersNode> classNodes = new Map.identity(); |
| |
| final Map<ExtensionTypeDeclaration, ExtensionTypeMembersNode> |
| extensionTypeDeclarationNodes = {}; |
| |
| final List<DelayedTypeComputation> _delayedTypeComputations = |
| <DelayedTypeComputation>[]; |
| |
| final List<DelayedCheck> _delayedChecks = <DelayedCheck>[]; |
| |
| final List<ClassMember> _delayedMemberComputations = <ClassMember>[]; |
| |
| ClassMembersBuilder(this.hierarchyBuilder); |
| |
| void clear() { |
| classNodes.clear(); |
| _delayedChecks.clear(); |
| _delayedTypeComputations.clear(); |
| _delayedMemberComputations.clear(); |
| extensionTypeDeclarationNodes.clear(); |
| } |
| |
| void registerDelayedTypeComputation(DelayedTypeComputation computation) { |
| _delayedTypeComputations.add(computation); |
| } |
| |
| void registerOverrideCheck(SourceClassBuilder classBuilder, |
| ClassMember declaredMember, Set<ClassMember> overriddenMembers, |
| {required ClassMember? localMember}) { |
| _delayedChecks.add(new DelayedOverrideCheck( |
| classBuilder, declaredMember, overriddenMembers, |
| localMember: localMember)); |
| } |
| |
| void registerGetterSetterCheck(DelayedGetterSetterCheck check) { |
| _delayedChecks.add(check); |
| } |
| |
| void registerMemberComputation(ClassMember member) { |
| _delayedMemberComputations.add(member); |
| } |
| |
| List<DelayedTypeComputation> takeDelayedTypeComputations() { |
| List<DelayedTypeComputation> list = _delayedTypeComputations.toList(); |
| _delayedTypeComputations.clear(); |
| return list; |
| } |
| |
| List<DelayedCheck> takeDelayedChecks() { |
| List<DelayedCheck> list = _delayedChecks.toList(); |
| _delayedChecks.clear(); |
| return list; |
| } |
| |
| List<ClassMember> takeDelayedMemberComputations() { |
| List<ClassMember> list = _delayedMemberComputations.toList(); |
| _delayedMemberComputations.clear(); |
| return list; |
| } |
| |
| void inferFieldType(SourceClassBuilder enclosingClassBuilder, |
| TypeBuilder declaredFieldType, Iterable<ClassMember> overriddenMembers, |
| {required String name, |
| required Uri fileUri, |
| required int nameOffset, |
| required int nameLength, |
| required bool isAssignable}) { |
| ClassMembersNodeBuilder.inferFieldType(hierarchyBuilder, this, |
| enclosingClassBuilder, declaredFieldType, overriddenMembers, |
| name: name, |
| fileUri: fileUri, |
| nameOffset: nameOffset, |
| nameLength: nameLength, |
| isAssignable: isAssignable); |
| } |
| |
| void inferGetterType(SourceClassBuilder enclosingClassBuilder, |
| TypeBuilder declaredTypeBuilder, Iterable<ClassMember> overriddenMembers, |
| {required String name, |
| required Uri fileUri, |
| required int nameOffset, |
| required int nameLength}) { |
| ClassMembersNodeBuilder.inferGetterType(hierarchyBuilder, this, |
| enclosingClassBuilder, declaredTypeBuilder, overriddenMembers, |
| name: name, |
| fileUri: fileUri, |
| nameOffset: nameOffset, |
| nameLength: nameLength); |
| } |
| |
| void inferSetterType( |
| SourceClassBuilder enclosingClassBuilder, |
| List<FormalParameterBuilder>? formals, |
| Iterable<ClassMember> overriddenMembers, |
| {required String name, |
| required Uri fileUri, |
| required int nameOffset, |
| required int nameLength}) { |
| ClassMembersNodeBuilder.inferSetterType(hierarchyBuilder, this, |
| enclosingClassBuilder, formals, overriddenMembers, |
| name: name, |
| fileUri: fileUri, |
| nameOffset: nameOffset, |
| nameLength: nameLength); |
| } |
| |
| void inferMethodType( |
| SourceClassBuilder enclosingClassBuilder, |
| FunctionNode declaredFunction, |
| TypeBuilder declaredReturnType, |
| List<FormalParameterBuilder>? formals, |
| Iterable<ClassMember> overriddenMembers, |
| {required String name, |
| required Uri fileUri, |
| required int nameOffset, |
| required int nameLength}) { |
| ClassMembersNodeBuilder.inferMethodType( |
| hierarchyBuilder, |
| this, |
| enclosingClassBuilder, |
| declaredFunction, |
| declaredReturnType, |
| formals, |
| overriddenMembers, |
| name: name, |
| fileUri: fileUri, |
| nameOffset: nameOffset, |
| nameLength: nameLength); |
| } |
| |
| ClassMembersNode getNodeFromClassBuilder(ClassBuilder classBuilder) { |
| return classNodes[classBuilder.cls] ??= new ClassMembersNodeBuilder( |
| this, hierarchyBuilder.getNodeFromClassBuilder(classBuilder)) |
| .build(); |
| } |
| |
| ExtensionTypeMembersNode getNodeFromExtensionTypeDeclarationBuilder( |
| ExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder) { |
| return extensionTypeDeclarationNodes[extensionTypeDeclarationBuilder |
| .extensionTypeDeclaration] ??= new ExtensionTypeMembersNodeBuilder( |
| this, |
| hierarchyBuilder.getNodeFromExtensionTypeDeclarationBuilder( |
| extensionTypeDeclarationBuilder)) |
| .build(); |
| } |
| |
| ClassMembersNode getNodeFromClass(Class cls) { |
| return classNodes[cls] ?? |
| getNodeFromClassBuilder( |
| hierarchyBuilder.loader.computeClassBuilderFromTargetClass(cls)); |
| } |
| |
| ExtensionTypeMembersNode getNodeFromExtensionTypeDeclaration( |
| ExtensionTypeDeclaration extensionTypeDeclaration) { |
| return extensionTypeDeclarationNodes[extensionTypeDeclaration] ?? |
| getNodeFromExtensionTypeDeclarationBuilder(hierarchyBuilder.loader |
| .computeExtensionTypeBuilderFromTargetExtensionType( |
| extensionTypeDeclaration)); |
| } |
| |
| @override |
| Member? getInterfaceMember(Class cls, Name name, {bool setter = false}) { |
| return getNodeFromClass(cls) |
| .getInterfaceMember(name, setter) |
| ?.getMember(this); |
| } |
| |
| ClassMember? getExtensionTypeClassMember( |
| ExtensionTypeDeclaration extensionTypeDeclaration, Name name, |
| {bool setter = false}) { |
| return getNodeFromExtensionTypeDeclaration(extensionTypeDeclaration) |
| .getMember(name, setter); |
| } |
| |
| ClassMember? getExtensionTypeStaticClassMember( |
| ExtensionTypeDeclaration extensionTypeDeclaration, Name name, |
| {bool setter = false}) { |
| return getNodeFromExtensionTypeDeclaration(extensionTypeDeclaration) |
| .getStaticMember(name, setter); |
| } |
| |
| @override |
| Member? getDispatchTarget(Class cls, Name name, {bool setter = false}) { |
| return getNodeFromClass(cls) |
| .getDispatchTarget(name, setter) |
| ?.getMember(this); |
| } |
| |
| ClassMember? getDispatchClassMember(Class cls, Name name, |
| {bool setter = false}) { |
| return getNodeFromClass(cls).getDispatchTarget(name, setter); |
| } |
| |
| Member? getStaticMember(Class cls, Name name, {bool setter = false}) { |
| return getNodeFromClass(cls).getStaticMember(name, setter)?.getMember(this); |
| } |
| |
| static ClassMembersBuilder build( |
| ClassHierarchyBuilder hierarchyBuilder, |
| List<ClassBuilder> classes, |
| List<ExtensionTypeDeclarationBuilder> extensionTypeDeclarations) { |
| ClassMembersBuilder membersBuilder = |
| new ClassMembersBuilder(hierarchyBuilder); |
| for (ClassBuilder classBuilder in classes) { |
| membersBuilder.getNodeFromClassBuilder(classBuilder); |
| } |
| for (ExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder |
| in extensionTypeDeclarations) { |
| membersBuilder.getNodeFromExtensionTypeDeclarationBuilder( |
| extensionTypeDeclarationBuilder); |
| } |
| return membersBuilder; |
| } |
| |
| void computeTypes() { |
| List<DelayedTypeComputation> typeComputations = |
| takeDelayedTypeComputations(); |
| for (int i = 0; i < typeComputations.length; i++) { |
| typeComputations[i].compute(this); |
| } |
| } |
| } |
| |
| int compareNamedParameters(VariableDeclaration a, VariableDeclaration b) { |
| return a.name!.compareTo(b.name!); |
| } |