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 |