| 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 |