| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library fasta.source_class_builder; | 5 library fasta.source_class_builder; |
| 6 | 6 |
| 7 import 'package:kernel/ast.dart' | 7 import 'package:kernel/ast.dart' |
| 8 show Class, Constructor, Supertype, TreeNode, setParents; | 8 show Class, Constructor, Supertype, TreeNode, setParents; |
| 9 | 9 |
| 10 import '../errors.dart' show internalError; | 10 import '../errors.dart' show internalError; |
| 11 | 11 |
| 12 import '../kernel/kernel_builder.dart' | 12 import '../kernel/kernel_builder.dart' |
| 13 show | 13 show |
| 14 Builder, | 14 Builder, |
| 15 ConstructorReferenceBuilder, | 15 ConstructorReferenceBuilder, |
| 16 KernelClassBuilder, | 16 KernelClassBuilder, |
| 17 KernelFieldBuilder, | 17 KernelFieldBuilder, |
| 18 KernelFunctionBuilder, | 18 KernelFunctionBuilder, |
| 19 KernelLibraryBuilder, | 19 KernelLibraryBuilder, |
| 20 KernelTypeBuilder, | 20 KernelTypeBuilder, |
| 21 KernelTypeVariableBuilder, | 21 KernelTypeVariableBuilder, |
| 22 LibraryBuilder, | 22 LibraryBuilder, |
| 23 MetadataBuilder, | 23 MetadataBuilder, |
| 24 ProcedureBuilder, | 24 Scope, |
| 25 TypeVariableBuilder, | 25 TypeVariableBuilder, |
| 26 compareProcedures; | 26 compareProcedures; |
| 27 | 27 |
| 28 import '../dill/dill_member_builder.dart' show DillMemberBuilder; | 28 import '../dill/dill_member_builder.dart' show DillMemberBuilder; |
| 29 | 29 |
| 30 import '../util/relativize.dart' show relativizeUri; | 30 import '../util/relativize.dart' show relativizeUri; |
| 31 | 31 |
| 32 Class initializeClass( | 32 Class initializeClass( |
| 33 Class cls, String name, LibraryBuilder parent, int charOffset) { | 33 Class cls, String name, LibraryBuilder parent, int charOffset) { |
| 34 cls ??= new Class(name: name); | 34 cls ??= new Class(name: name); |
| 35 cls.fileUri ??= relativizeUri(parent.fileUri); | 35 cls.fileUri ??= relativizeUri(parent.fileUri); |
| 36 if (cls.fileOffset == TreeNode.noOffset) { | 36 if (cls.fileOffset == TreeNode.noOffset) { |
| 37 cls.fileOffset = charOffset; | 37 cls.fileOffset = charOffset; |
| 38 } | 38 } |
| 39 return cls; | 39 return cls; |
| 40 } | 40 } |
| 41 | 41 |
| 42 class SourceClassBuilder extends KernelClassBuilder { | 42 class SourceClassBuilder extends KernelClassBuilder { |
| 43 final Class cls; | 43 final Class cls; |
| 44 | 44 |
| 45 @override | |
| 46 final Map<String, Builder> constructors; | |
| 47 | |
| 48 final Map<String, Builder> membersInScope; | |
| 49 | |
| 50 final List<ConstructorReferenceBuilder> constructorReferences; | 45 final List<ConstructorReferenceBuilder> constructorReferences; |
| 51 | 46 |
| 52 final KernelTypeBuilder mixedInType; | 47 final KernelTypeBuilder mixedInType; |
| 53 | 48 |
| 54 SourceClassBuilder( | 49 SourceClassBuilder( |
| 55 List<MetadataBuilder> metadata, | 50 List<MetadataBuilder> metadata, |
| 56 int modifiers, | 51 int modifiers, |
| 57 String name, | 52 String name, |
| 58 List<TypeVariableBuilder> typeVariables, | 53 List<TypeVariableBuilder> typeVariables, |
| 59 KernelTypeBuilder supertype, | 54 KernelTypeBuilder supertype, |
| 60 List<KernelTypeBuilder> interfaces, | 55 List<KernelTypeBuilder> interfaces, |
| 61 Map<String, Builder> members, | 56 Scope scope, |
| 57 Scope constructors, |
| 62 LibraryBuilder parent, | 58 LibraryBuilder parent, |
| 63 this.constructorReferences, | 59 this.constructorReferences, |
| 64 int charOffset, | 60 int charOffset, |
| 65 [Class cls, | 61 [Class cls, |
| 66 this.mixedInType]) | 62 this.mixedInType]) |
| 67 : cls = initializeClass(cls, name, parent, charOffset), | 63 : cls = initializeClass(cls, name, parent, charOffset), |
| 68 membersInScope = computeMembersInScope(members), | |
| 69 constructors = computeConstructors(members), | |
| 70 super(metadata, modifiers, name, typeVariables, supertype, interfaces, | 64 super(metadata, modifiers, name, typeVariables, supertype, interfaces, |
| 71 members, parent, charOffset); | 65 scope, constructors, parent, charOffset); |
| 72 | 66 |
| 73 int resolveTypes(LibraryBuilder library) { | 67 int resolveTypes(LibraryBuilder library) { |
| 74 int count = 0; | 68 int count = 0; |
| 75 if (typeVariables != null) { | 69 if (typeVariables != null) { |
| 76 for (KernelTypeVariableBuilder t in typeVariables) { | 70 for (KernelTypeVariableBuilder t in typeVariables) { |
| 77 cls.typeParameters.add(t.parameter); | 71 cls.typeParameters.add(t.parameter); |
| 78 } | 72 } |
| 79 setParents(cls.typeParameters, cls); | 73 setParents(cls.typeParameters, cls); |
| 80 count += cls.typeParameters.length; | 74 count += cls.typeParameters.length; |
| 81 } | 75 } |
| 82 return count + super.resolveTypes(library); | 76 return count + super.resolveTypes(library); |
| 83 } | 77 } |
| 84 | 78 |
| 85 Class build(KernelLibraryBuilder library) { | 79 Class build(KernelLibraryBuilder library) { |
| 86 void buildBuilder(Builder builder) { | 80 void buildBuilders(String name, Builder builder) { |
| 87 if (builder is KernelFieldBuilder) { | 81 do { |
| 88 // TODO(ahe): It would be nice to have a common interface for the build | 82 if (builder is KernelFieldBuilder) { |
| 89 // method to avoid duplicating these two cases. | 83 // TODO(ahe): It would be nice to have a common interface for the |
| 90 cls.addMember(builder.build(library)); | 84 // build method to avoid duplicating these two cases. |
| 91 } else if (builder is KernelFunctionBuilder) { | 85 cls.addMember(builder.build(library)); |
| 92 cls.addMember(builder.build(library)); | 86 } else if (builder is KernelFunctionBuilder) { |
| 93 } else { | 87 cls.addMember(builder.build(library)); |
| 94 internalError("Unhandled builder: ${builder.runtimeType}"); | 88 } else { |
| 95 } | 89 internalError("Unhandled builder: ${builder.runtimeType}"); |
| 90 } |
| 91 builder = builder.next; |
| 92 } while (builder != null); |
| 96 } | 93 } |
| 97 | 94 |
| 98 members.forEach((String name, Builder builder) { | 95 scope.forEach(buildBuilders); |
| 99 do { | 96 constructors.forEach(buildBuilders); |
| 100 buildBuilder(builder); | |
| 101 builder = builder.next; | |
| 102 } while (builder != null); | |
| 103 }); | |
| 104 cls.supertype = supertype?.buildSupertype(library); | 97 cls.supertype = supertype?.buildSupertype(library); |
| 105 cls.mixedInType = mixedInType?.buildSupertype(library); | 98 cls.mixedInType = mixedInType?.buildSupertype(library); |
| 106 // TODO(ahe): If `cls.supertype` is null, and this isn't Object, report a | 99 // TODO(ahe): If `cls.supertype` is null, and this isn't Object, report a |
| 107 // compile-time error. | 100 // compile-time error. |
| 108 cls.isAbstract = isAbstract; | 101 cls.isAbstract = isAbstract; |
| 109 if (interfaces != null) { | 102 if (interfaces != null) { |
| 110 for (KernelTypeBuilder interface in interfaces) { | 103 for (KernelTypeBuilder interface in interfaces) { |
| 111 Supertype supertype = interface.buildSupertype(library); | 104 Supertype supertype = interface.buildSupertype(library); |
| 112 if (supertype != null) { | 105 if (supertype != null) { |
| 113 // TODO(ahe): Report an error if supertype is null. | 106 // TODO(ahe): Report an error if supertype is null. |
| 114 cls.implementedTypes.add(supertype); | 107 cls.implementedTypes.add(supertype); |
| 115 } | 108 } |
| 116 } | 109 } |
| 117 } | 110 } |
| 118 | 111 |
| 112 constructors.forEach((String name, Builder constructor) { |
| 113 Builder member = scopeBuilder[name]; |
| 114 if (member == null) return; |
| 115 // TODO(ahe): charOffset is missing. |
| 116 addCompileTimeError( |
| 117 constructor.charOffset, "Conflicts with member '${name}'."); |
| 118 if (constructor.isFactory) { |
| 119 addCompileTimeError(member.charOffset, |
| 120 "Conflicts with factory '${this.name}.${name}'."); |
| 121 } else { |
| 122 addCompileTimeError(member.charOffset, |
| 123 "Conflicts with constructor '${this.name}.${name}'."); |
| 124 } |
| 125 }); |
| 126 |
| 127 scope.setters.forEach((String name, Builder setter) { |
| 128 Builder member = scopeBuilder[name]; |
| 129 if (member == null || !member.isField || member.isFinal) return; |
| 130 // TODO(ahe): charOffset is missing. |
| 131 var report = member.isInstanceMember != setter.isInstanceMember |
| 132 ? addWarning |
| 133 : addCompileTimeError; |
| 134 report(setter.charOffset, "Conflicts with member '${name}'."); |
| 135 report(member.charOffset, "Conflicts with setter '${name}'."); |
| 136 }); |
| 137 |
| 119 cls.procedures.sort(compareProcedures); | 138 cls.procedures.sort(compareProcedures); |
| 120 return cls; | 139 return cls; |
| 121 } | 140 } |
| 122 | 141 |
| 123 void addSyntheticConstructor(Constructor constructor) { | 142 void addSyntheticConstructor(Constructor constructor) { |
| 124 String name = constructor.name.name; | 143 String name = constructor.name.name; |
| 125 cls.constructors.add(constructor); | 144 cls.constructors.add(constructor); |
| 126 constructor.parent = cls; | 145 constructor.parent = cls; |
| 127 DillMemberBuilder memberBuilder = new DillMemberBuilder(constructor, this); | 146 DillMemberBuilder memberBuilder = new DillMemberBuilder(constructor, this); |
| 128 memberBuilder.next = constructors[name]; | 147 memberBuilder.next = constructorScopeBuilder[name]; |
| 129 constructors[name] = memberBuilder; | 148 constructorScopeBuilder.addMember(name, memberBuilder); |
| 130 } | 149 } |
| 131 } | 150 } |
| 132 | |
| 133 Map<String, Builder> computeMembersInScope(Map<String, Builder> members) { | |
| 134 Map<String, Builder> membersInScope = <String, Builder>{}; | |
| 135 members.forEach((String name, Builder builder) { | |
| 136 if (builder is ProcedureBuilder) { | |
| 137 if (builder.isConstructor || builder.isFactory) return; | |
| 138 } | |
| 139 membersInScope[name] = builder; | |
| 140 }); | |
| 141 return membersInScope; | |
| 142 } | |
| 143 | |
| 144 Map<String, Builder> computeConstructors(Map<String, Builder> members) { | |
| 145 Map<String, Builder> constructors = <String, Builder>{}; | |
| 146 members.forEach((String name, Builder builder) { | |
| 147 if (builder is ProcedureBuilder && | |
| 148 (builder.isConstructor || builder.isFactory)) { | |
| 149 constructors[name] = builder; | |
| 150 } | |
| 151 }); | |
| 152 return constructors; | |
| 153 } | |
| OLD | NEW |