OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 | 5 |
6 /** | 6 /** |
7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
8 * compiled. | 8 * compiled. |
9 */ | 9 */ |
10 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 fields[field] = propagatedType; | 118 fields[field] = propagatedType; |
119 } else { | 119 } else { |
120 fields[field] = fields[field].union(propagatedType); | 120 fields[field] = fields[field].union(propagatedType); |
121 } | 121 } |
122 } | 122 } |
123 | 123 |
124 HType typeFromInitializersSoFar(Element field) { | 124 HType typeFromInitializersSoFar(Element field) { |
125 assert(field.isField()); | 125 assert(field.isField()); |
126 assert(field.enclosingElement.isClass()); | 126 assert(field.enclosingElement.isClass()); |
127 if (!fieldInitializers.containsKey(field.enclosingElement)) { | 127 if (!fieldInitializers.containsKey(field.enclosingElement)) { |
128 return HType.UNKNOWN; | 128 return HType.CONFLICTING; |
129 } | 129 } |
130 Map<Element, HType> fields = fieldInitializers[field.enclosingElement]; | 130 Map<Element, HType> fields = fieldInitializers[field.enclosingElement]; |
131 return fields[field]; | 131 return fields[field]; |
132 } | 132 } |
133 | 133 |
134 void updateFieldConstructorSetters(Element field, HType type) { | 134 void updateFieldConstructorSetters(Element field, HType type) { |
135 assert(field.isField()); | 135 assert(field.isField()); |
136 assert(field.enclosingElement.isClass()); | 136 assert(field.enclosingElement.isClass()); |
137 Map<Element, HType> fields = | 137 Map<Element, HType> fields = |
138 fieldConstructorSetters.putIfAbsent( | 138 fieldConstructorSetters.putIfAbsent( |
139 field.enclosingElement, () => new Map<Element, HType>()); | 139 field.enclosingElement, () => new Map<Element, HType>()); |
140 if (!fields.containsKey(field)) { | 140 if (!fields.containsKey(field)) { |
141 fields[field] = type; | 141 fields[field] = type; |
142 } else { | 142 } else { |
143 fields[field] = fields[field].union(type); | 143 fields[field] = fields[field].union(type); |
144 } | 144 } |
145 } | 145 } |
146 | 146 |
147 // Check if this field is set in the constructor body. | 147 // Check if this field is set in the constructor body. |
148 bool hasConstructorBodyFieldSetter(Element field) { | 148 bool hasConstructorBodyFieldSetter(Element field) { |
149 if (!fieldConstructorSetters.containsKey(field.enclosingElement)) { | 149 if (!fieldConstructorSetters.containsKey(field.enclosingElement)) { |
150 return false; | 150 return false; |
151 } | 151 } |
152 return fieldConstructorSetters[field.enclosingElement][field] != null; | 152 return fieldConstructorSetters[field.enclosingElement][field] != null; |
153 } | 153 } |
154 | 154 |
155 // Provide an optimistic estimate of the type of a field after construction. | 155 // Provide an optimistic estimate of the type of a field after construction. |
| 156 // If the constructor body has setters for fields returns HType.UNKNOWN. |
156 // This only takes the initializer lists and field assignments in the | 157 // This only takes the initializer lists and field assignments in the |
157 // constructor body into account. The constructor body might have method calls | 158 // constructor body into account. The constructor body might have method calls |
158 // that could alter the field. | 159 // that could alter the field. |
159 HType optimisticFieldTypeAfterConstruction(Element field) { | 160 HType optimisticFieldTypeAfterConstruction(Element field) { |
160 assert(field.isField()); | 161 assert(field.isField()); |
161 assert(field.enclosingElement.isClass()); | 162 assert(field.enclosingElement.isClass()); |
162 | 163 |
163 if (hasConstructorBodyFieldSetter(field)) { | 164 if (hasConstructorBodyFieldSetter(field)) { |
164 // If there are field setters for this field in some constructor only one | 165 // If there are field setters but there is only constructor then the type |
165 // constructor then the type set will be the field type after | 166 // of the field is determined by the assignments in the constructor |
166 // construction. | 167 // body. |
167 if (field.enclosingElement.constructors.length == 1) { | 168 ClassElement classElement = field.enclosingElement; |
| 169 if (classElement.constructors.length == 1) { |
168 return fieldConstructorSetters[field.enclosingElement][field]; | 170 return fieldConstructorSetters[field.enclosingElement][field]; |
169 } else { | 171 } else { |
170 return HType.UNKNOWN; | 172 return HType.UNKNOWN; |
171 } | 173 } |
172 } else if (fieldInitializers.containsKey(field.enclosingElement)) { | 174 } else if (fieldInitializers.containsKey(field.enclosingElement)) { |
173 HType type = fieldInitializers[field.enclosingElement][field]; | 175 HType type = fieldInitializers[field.enclosingElement][field]; |
174 return type == null ? HType.UNKNOWN : type; | 176 return type == null ? HType.CONFLICTING : type; |
175 } else { | 177 } else { |
176 return HType.UNKNOWN; | 178 return HType.CONFLICTING; |
177 } | 179 } |
178 } | 180 } |
179 | 181 |
180 void updateFieldSetters(Element field, HType type) { | 182 void updateFieldSetters(Element field, HType type) { |
181 assert(field.isField()); | 183 assert(field.isField()); |
182 assert(field.enclosingElement.isClass()); | 184 assert(field.enclosingElement.isClass()); |
183 Map<Element, HType> fields = | 185 Map<Element, HType> fields = |
184 fieldSettersType.putIfAbsent( | 186 fieldSettersType.putIfAbsent( |
185 field.enclosingElement, () => new Map<Element, HType>()); | 187 field.enclosingElement, () => new Map<Element, HType>()); |
186 if (!fields.containsKey(field)) { | 188 if (!fields.containsKey(field)) { |
187 fields[field] = type; | 189 fields[field] = type; |
188 } else { | 190 } else { |
189 fields[field] = fields[field].union(type); | 191 fields[field] = fields[field].union(type); |
190 } | 192 } |
191 } | 193 } |
192 | 194 |
193 // Returns the type that field setters are setting the field to based on what | 195 // Returns the type that field setters are setting the field to based on what |
194 // have been seen during compilation so far. | 196 // have been seen during compilation so far. |
195 HType fieldSettersTypeSoFar(Element field) { | 197 HType fieldSettersTypeSoFar(Element field) { |
196 assert(field.isField()); | 198 assert(field.isField()); |
197 assert(field.enclosingElement.isClass()); | 199 assert(field.enclosingElement.isClass()); |
198 if (!fieldSettersType.containsKey(field.enclosingElement)) { | 200 if (!fieldSettersType.containsKey(field.enclosingElement)) { |
199 return HType.UNKNOWN; | 201 return HType.CONFLICTING; |
200 } | 202 } |
201 Map<Element, HType> fields = fieldSettersType[field.enclosingElement]; | 203 Map<Element, HType> fields = fieldSettersType[field.enclosingElement]; |
202 if (!fields.containsKey(field)) return HType.UNKNOWN; | 204 if (!fields.containsKey(field)) return HType.CONFLICTING; |
203 return fields[field]; | 205 return fields[field]; |
204 } | 206 } |
205 } | 207 } |
206 | 208 |
207 class Compiler implements DiagnosticListener { | 209 class Compiler implements DiagnosticListener { |
208 final Map<String, LibraryElement> libraries; | 210 final Map<String, LibraryElement> libraries; |
209 int nextFreeClassId = 0; | 211 int nextFreeClassId = 0; |
210 World world; | 212 World world; |
211 String assembledCode; | 213 String assembledCode; |
212 Namer namer; | 214 Namer namer; |
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 f(int beginOffset, int endOffset)) { | 1045 f(int beginOffset, int endOffset)) { |
1044 final beginOffset = begin.charOffset; | 1046 final beginOffset = begin.charOffset; |
1045 final endOffset = end.charOffset + end.slowCharCount; | 1047 final endOffset = end.charOffset + end.slowCharCount; |
1046 | 1048 |
1047 // [begin] and [end] might be the same for the same empty token. This | 1049 // [begin] and [end] might be the same for the same empty token. This |
1048 // happens for instance when scanning '$$'. | 1050 // happens for instance when scanning '$$'. |
1049 assert(endOffset >= beginOffset); | 1051 assert(endOffset >= beginOffset); |
1050 return f(beginOffset, endOffset); | 1052 return f(beginOffset, endOffset); |
1051 } | 1053 } |
1052 } | 1054 } |
OLD | NEW |