| 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 /// This library defined `uses`. A `use` is a single impact of the world, for | 5 /// This library defined `uses`. A `use` is a single impact of the world, for |
| 6 /// instance an invocation of a top level function or a call to the `foo()` | 6 /// instance an invocation of a top level function or a call to the `foo()` |
| 7 /// method on an unknown class. | 7 /// method on an unknown class. |
| 8 library dart2js.universe.use; | 8 library dart2js.universe.use; |
| 9 | 9 |
| 10 import '../closure.dart' show | 10 import '../closure.dart' show |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 } | 77 } |
| 78 | 78 |
| 79 /// Statically known use of an [Element]. | 79 /// Statically known use of an [Element]. |
| 80 // TODO(johnniwinther): Create backend-specific implementations with better | 80 // TODO(johnniwinther): Create backend-specific implementations with better |
| 81 // invariants. | 81 // invariants. |
| 82 class StaticUse { | 82 class StaticUse { |
| 83 final Element element; | 83 final Element element; |
| 84 final StaticUseKind kind; | 84 final StaticUseKind kind; |
| 85 final int hashCode; | 85 final int hashCode; |
| 86 | 86 |
| 87 StaticUse._(Element element, StaticUseKind kind) | 87 StaticUse.internal(Element element, StaticUseKind kind) |
| 88 : this.element = element, | 88 : this.element = element, |
| 89 this.kind = kind, | 89 this.kind = kind, |
| 90 this.hashCode = Hashing.objectHash(element, Hashing.objectHash(kind)) { | 90 this.hashCode = Hashing.objectHash(element, Hashing.objectHash(kind)) { |
| 91 assert(invariant(element, element.isDeclaration, | 91 assert(invariant(element, element.isDeclaration, |
| 92 message: "Static use element $element must be " | 92 message: "Static use element $element must be " |
| 93 "the declaration element.")); | 93 "the declaration element.")); |
| 94 } | 94 } |
| 95 | 95 |
| 96 /// Invocation of a static or top-level [element] with the given | 96 /// Invocation of a static or top-level [element] with the given |
| 97 /// [callStructure]. | 97 /// [callStructure]. |
| 98 factory StaticUse.staticInvoke(MethodElement element, | 98 factory StaticUse.staticInvoke(MethodElement element, |
| 99 CallStructure callStructure) { | 99 CallStructure callStructure) { |
| 100 // TODO(johnniwinther): Use the [callStructure]. | 100 // TODO(johnniwinther): Use the [callStructure]. |
| 101 assert(invariant(element, element.isStatic || element.isTopLevel, | 101 assert(invariant(element, element.isStatic || element.isTopLevel, |
| 102 message: "Static invoke element $element must be a top-level " | 102 message: "Static invoke element $element must be a top-level " |
| 103 "or static method.")); | 103 "or static method.")); |
| 104 return new StaticUse._(element, StaticUseKind.GENERAL); | 104 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 105 } | 105 } |
| 106 | 106 |
| 107 /// Closurization of a static or top-level function [element]. | 107 /// Closurization of a static or top-level function [element]. |
| 108 factory StaticUse.staticTearOff(MethodElement element) { | 108 factory StaticUse.staticTearOff(MethodElement element) { |
| 109 assert(invariant(element, element.isStatic || element.isTopLevel, | 109 assert(invariant(element, element.isStatic || element.isTopLevel, |
| 110 message: "Static tear-off element $element must be a top-level " | 110 message: "Static tear-off element $element must be a top-level " |
| 111 "or static method.")); | 111 "or static method.")); |
| 112 return new StaticUse._(element, StaticUseKind.STATIC_TEAR_OFF); | 112 return new StaticUse.internal(element, StaticUseKind.STATIC_TEAR_OFF); |
| 113 } | 113 } |
| 114 | 114 |
| 115 /// Read access of a static or top-level field or getter [element]. | 115 /// Read access of a static or top-level field or getter [element]. |
| 116 factory StaticUse.staticGet(MemberElement element) { | 116 factory StaticUse.staticGet(MemberElement element) { |
| 117 assert(invariant(element, element.isStatic || element.isTopLevel, | 117 assert(invariant(element, element.isStatic || element.isTopLevel, |
| 118 message: "Static get element $element must be a top-level " | 118 message: "Static get element $element must be a top-level " |
| 119 "or static method.")); | 119 "or static method.")); |
| 120 assert(invariant(element, element.isField || element.isGetter, | 120 assert(invariant(element, element.isField || element.isGetter, |
| 121 message: "Static get element $element must be a field or a getter.")); | 121 message: "Static get element $element must be a field or a getter.")); |
| 122 return new StaticUse._(element, StaticUseKind.GENERAL); | 122 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 123 } | 123 } |
| 124 | 124 |
| 125 /// Write access of a static or top-level field or setter [element]. | 125 /// Write access of a static or top-level field or setter [element]. |
| 126 factory StaticUse.staticSet(MemberElement element) { | 126 factory StaticUse.staticSet(MemberElement element) { |
| 127 assert(invariant(element, element.isStatic || element.isTopLevel, | 127 assert(invariant(element, element.isStatic || element.isTopLevel, |
| 128 message: "Static set element $element must be a top-level " | 128 message: "Static set element $element must be a top-level " |
| 129 "or static method.")); | 129 "or static method.")); |
| 130 assert(invariant(element, element.isField || element.isSetter, | 130 assert(invariant(element, element.isField || element.isSetter, |
| 131 message: "Static set element $element must be a field or a setter.")); | 131 message: "Static set element $element must be a field or a setter.")); |
| 132 return new StaticUse._(element, StaticUseKind.GENERAL); | 132 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 133 } | 133 } |
| 134 | 134 |
| 135 /// Invocation of the lazy initializer for a static or top-level field | 135 /// Invocation of the lazy initializer for a static or top-level field |
| 136 /// [element]. | 136 /// [element]. |
| 137 factory StaticUse.staticInit(FieldElement element) { | 137 factory StaticUse.staticInit(FieldElement element) { |
| 138 assert(invariant(element, element.isStatic || element.isTopLevel, | 138 assert(invariant(element, element.isStatic || element.isTopLevel, |
| 139 message: "Static init element $element must be a top-level " | 139 message: "Static init element $element must be a top-level " |
| 140 "or static method.")); | 140 "or static method.")); |
| 141 assert(invariant(element, element.isField, | 141 assert(invariant(element, element.isField, |
| 142 message: "Static init element $element must be a field.")); | 142 message: "Static init element $element must be a field.")); |
| 143 return new StaticUse._(element, StaticUseKind.GENERAL); | 143 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 144 } | 144 } |
| 145 | 145 |
| 146 /// Invocation of a super method [element] with the given [callStructure]. | 146 /// Invocation of a super method [element] with the given [callStructure]. |
| 147 factory StaticUse.superInvoke(MethodElement element, | 147 factory StaticUse.superInvoke(MethodElement element, |
| 148 CallStructure callStructure) { | 148 CallStructure callStructure) { |
| 149 // TODO(johnniwinther): Use the [callStructure]. | 149 // TODO(johnniwinther): Use the [callStructure]. |
| 150 assert(invariant(element, element.isInstanceMember, | 150 assert(invariant(element, element.isInstanceMember, |
| 151 message: "Super invoke element $element must be an instance method.")); | 151 message: "Super invoke element $element must be an instance method.")); |
| 152 return new StaticUse._(element, StaticUseKind.GENERAL); | 152 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 153 } | 153 } |
| 154 | 154 |
| 155 /// Read access of a super field or getter [element]. | 155 /// Read access of a super field or getter [element]. |
| 156 factory StaticUse.superGet(MemberElement element) { | 156 factory StaticUse.superGet(MemberElement element) { |
| 157 assert(invariant(element, element.isInstanceMember, | 157 assert(invariant(element, element.isInstanceMember, |
| 158 message: "Super get element $element must be an instance method.")); | 158 message: "Super get element $element must be an instance method.")); |
| 159 assert(invariant(element, element.isField || element.isGetter, | 159 assert(invariant(element, element.isField || element.isGetter, |
| 160 message: "Super get element $element must be a field or a getter.")); | 160 message: "Super get element $element must be a field or a getter.")); |
| 161 return new StaticUse._(element, StaticUseKind.GENERAL); | 161 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 162 } | 162 } |
| 163 | 163 |
| 164 /// Write access of a super field [element]. | 164 /// Write access of a super field [element]. |
| 165 factory StaticUse.superFieldSet(FieldElement element) { | 165 factory StaticUse.superFieldSet(FieldElement element) { |
| 166 assert(invariant(element, element.isInstanceMember, | 166 assert(invariant(element, element.isInstanceMember, |
| 167 message: "Super set element $element must be an instance method.")); | 167 message: "Super set element $element must be an instance method.")); |
| 168 assert(invariant(element, element.isField, | 168 assert(invariant(element, element.isField, |
| 169 message: "Super set element $element must be a field.")); | 169 message: "Super set element $element must be a field.")); |
| 170 return new StaticUse._(element, StaticUseKind.SUPER_FIELD_SET); | 170 return new StaticUse.internal(element, StaticUseKind.SUPER_FIELD_SET); |
| 171 } | 171 } |
| 172 | 172 |
| 173 /// Write access of a super setter [element]. | 173 /// Write access of a super setter [element]. |
| 174 factory StaticUse.superSetterSet(SetterElement element) { | 174 factory StaticUse.superSetterSet(SetterElement element) { |
| 175 assert(invariant(element, element.isInstanceMember, | 175 assert(invariant(element, element.isInstanceMember, |
| 176 message: "Super set element $element must be an instance method.")); | 176 message: "Super set element $element must be an instance method.")); |
| 177 assert(invariant(element, element.isSetter, | 177 assert(invariant(element, element.isSetter, |
| 178 message: "Super set element $element must be a setter.")); | 178 message: "Super set element $element must be a setter.")); |
| 179 return new StaticUse._(element, StaticUseKind.GENERAL); | 179 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 180 } | 180 } |
| 181 | 181 |
| 182 /// Closurization of a super method [element]. | 182 /// Closurization of a super method [element]. |
| 183 factory StaticUse.superTearOff(MethodElement element) { | 183 factory StaticUse.superTearOff(MethodElement element) { |
| 184 assert(invariant(element, element.isInstanceMember && element.isFunction, | 184 assert(invariant(element, element.isInstanceMember && element.isFunction, |
| 185 message: "Super invoke element $element must be an instance method.")); | 185 message: "Super invoke element $element must be an instance method.")); |
| 186 return new StaticUse._(element, StaticUseKind.SUPER_TEAR_OFF); | 186 return new StaticUse.internal(element, StaticUseKind.SUPER_TEAR_OFF); |
| 187 } | 187 } |
| 188 | 188 |
| 189 /// Invocation of a constructor [element] through a this or super | 189 /// Invocation of a constructor [element] through a this or super |
| 190 /// constructor call with the given [callStructure]. | 190 /// constructor call with the given [callStructure]. |
| 191 factory StaticUse.superConstructorInvoke(Element element, | 191 factory StaticUse.superConstructorInvoke(Element element, |
| 192 CallStructure callStructure) { | 192 CallStructure callStructure) { |
| 193 // TODO(johnniwinther): Use the [callStructure]. | 193 // TODO(johnniwinther): Use the [callStructure]. |
| 194 assert(invariant(element, | 194 assert(invariant(element, |
| 195 element.isGenerativeConstructor, | 195 element.isGenerativeConstructor, |
| 196 message: "Constructor invoke element $element must be a " | 196 message: "Constructor invoke element $element must be a " |
| 197 "generative constructor.")); | 197 "generative constructor.")); |
| 198 return new StaticUse._(element, StaticUseKind.GENERAL); | 198 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 199 } | 199 } |
| 200 | 200 |
| 201 /// Invocation of a constructor (body) [element] through a this or super | 201 /// Invocation of a constructor (body) [element] through a this or super |
| 202 /// constructor call with the given [callStructure]. | 202 /// constructor call with the given [callStructure]. |
| 203 factory StaticUse.constructorBodyInvoke(ConstructorBodyElement element, | 203 factory StaticUse.constructorBodyInvoke(ConstructorBodyElement element, |
| 204 CallStructure callStructure) { | 204 CallStructure callStructure) { |
| 205 // TODO(johnniwinther): Use the [callStructure]. | 205 // TODO(johnniwinther): Use the [callStructure]. |
| 206 return new StaticUse._(element, StaticUseKind.GENERAL); | 206 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 207 } | 207 } |
| 208 | 208 |
| 209 /// Constructor invocation of [element] with the given [callStructure]. | 209 /// Constructor invocation of [element] with the given [callStructure]. |
| 210 factory StaticUse.constructorInvoke(ConstructorElement element, | 210 factory StaticUse.constructorInvoke(ConstructorElement element, |
| 211 CallStructure callStructure) { | 211 CallStructure callStructure) { |
| 212 // TODO(johnniwinther): Use the [callStructure]. | 212 // TODO(johnniwinther): Use the [callStructure]. |
| 213 return new StaticUse._(element, StaticUseKind.GENERAL); | 213 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 214 } | 214 } |
| 215 | 215 |
| 216 /// Constructor redirection to [element]. | 216 /// Constructor redirection to [element]. |
| 217 factory StaticUse.constructorRedirect(ConstructorElement element) { | 217 factory StaticUse.constructorRedirect(ConstructorElement element) { |
| 218 return new StaticUse._(element, StaticUseKind.GENERAL); | 218 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 219 } | 219 } |
| 220 | 220 |
| 221 /// Initialization of an instance field [element]. | 221 /// Initialization of an instance field [element]. |
| 222 factory StaticUse.fieldInit(FieldElement element) { | 222 factory StaticUse.fieldInit(FieldElement element) { |
| 223 assert(invariant(element, element.isInstanceMember, | 223 assert(invariant(element, element.isInstanceMember, |
| 224 message: "Field init element $element must be an instance field.")); | 224 message: "Field init element $element must be an instance field.")); |
| 225 return new StaticUse._(element, StaticUseKind.GENERAL); | 225 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 226 } | 226 } |
| 227 | 227 |
| 228 /// Read access of an instance field or boxed field [element]. | 228 /// Read access of an instance field or boxed field [element]. |
| 229 factory StaticUse.fieldGet(Element element) { | 229 factory StaticUse.fieldGet(Element element) { |
| 230 assert(invariant(element, | 230 assert(invariant(element, |
| 231 element.isInstanceMember || element is BoxFieldElement, | 231 element.isInstanceMember || element is BoxFieldElement, |
| 232 message: "Field init element $element must be an instance " | 232 message: "Field init element $element must be an instance " |
| 233 "or boxed field.")); | 233 "or boxed field.")); |
| 234 return new StaticUse._(element, StaticUseKind.FIELD_GET); | 234 return new StaticUse.internal(element, StaticUseKind.FIELD_GET); |
| 235 } | 235 } |
| 236 | 236 |
| 237 /// Write access of an instance field or boxed field [element]. | 237 /// Write access of an instance field or boxed field [element]. |
| 238 factory StaticUse.fieldSet(Element element) { | 238 factory StaticUse.fieldSet(Element element) { |
| 239 assert(invariant(element, | 239 assert(invariant(element, |
| 240 element.isInstanceMember || element is BoxFieldElement, | 240 element.isInstanceMember || element is BoxFieldElement, |
| 241 message: "Field init element $element must be an instance " | 241 message: "Field init element $element must be an instance " |
| 242 "or boxed field.")); | 242 "or boxed field.")); |
| 243 return new StaticUse._(element, StaticUseKind.FIELD_SET); | 243 return new StaticUse.internal(element, StaticUseKind.FIELD_SET); |
| 244 } | 244 } |
| 245 | 245 |
| 246 /// Read of a local function [element]. | 246 /// Read of a local function [element]. |
| 247 factory StaticUse.closure(LocalFunctionElement element) { | 247 factory StaticUse.closure(LocalFunctionElement element) { |
| 248 return new StaticUse._(element, StaticUseKind.CLOSURE); | 248 return new StaticUse.internal(element, StaticUseKind.CLOSURE); |
| 249 } | 249 } |
| 250 | 250 |
| 251 /// Unknown use of [element]. | 251 /// Unknown use of [element]. |
| 252 @deprecated | 252 @deprecated |
| 253 factory StaticUse.foreignUse(Element element) { | 253 factory StaticUse.foreignUse(Element element) { |
| 254 return new StaticUse._(element, StaticUseKind.GENERAL); | 254 return new StaticUse.internal(element, StaticUseKind.GENERAL); |
| 255 } | 255 } |
| 256 | 256 |
| 257 bool operator ==(other) { | 257 bool operator ==(other) { |
| 258 if (identical(this, other)) return true; | 258 if (identical(this, other)) return true; |
| 259 if (other is! StaticUse) return false; | 259 if (other is! StaticUse) return false; |
| 260 return element == other.element && | 260 return element == other.element && |
| 261 kind == other.kind; | 261 kind == other.kind; |
| 262 } | 262 } |
| 263 | 263 |
| 264 String toString() => 'StaticUse($element,$kind)'; | 264 String toString() => 'StaticUse($element,$kind)'; |
| 265 } | 265 } |
| 266 | 266 |
| 267 enum TypeUseKind { | 267 enum TypeUseKind { |
| 268 IS_CHECK, | 268 IS_CHECK, |
| 269 AS_CAST, | 269 AS_CAST, |
| 270 CHECKED_MODE_CHECK, | 270 CHECKED_MODE_CHECK, |
| 271 CATCH_TYPE, | 271 CATCH_TYPE, |
| 272 TYPE_LITERAL, | 272 TYPE_LITERAL, |
| 273 INSTANTIATION, | 273 INSTANTIATION, |
| 274 } | 274 } |
| 275 | 275 |
| 276 /// Use of a [DartType]. | 276 /// Use of a [DartType]. |
| 277 class TypeUse { | 277 class TypeUse { |
| 278 final DartType type; | 278 final DartType type; |
| 279 final TypeUseKind kind; | 279 final TypeUseKind kind; |
| 280 final int hashCode; | 280 final int hashCode; |
| 281 | 281 |
| 282 TypeUse._(DartType type, TypeUseKind kind) | 282 TypeUse.internal(DartType type, TypeUseKind kind) |
| 283 : this.type = type, | 283 : this.type = type, |
| 284 this.kind = kind, | 284 this.kind = kind, |
| 285 this.hashCode = Hashing.objectHash(type, Hashing.objectHash(kind)); | 285 this.hashCode = Hashing.objectHash(type, Hashing.objectHash(kind)); |
| 286 | 286 |
| 287 /// [type] used in an is check, like `e is T` or `e is! T`. | 287 /// [type] used in an is check, like `e is T` or `e is! T`. |
| 288 factory TypeUse.isCheck(DartType type) { | 288 factory TypeUse.isCheck(DartType type) { |
| 289 return new TypeUse._(type, TypeUseKind.IS_CHECK); | 289 return new TypeUse.internal(type, TypeUseKind.IS_CHECK); |
| 290 } | 290 } |
| 291 | 291 |
| 292 /// [type] used in an as cast, like `e as T`. | 292 /// [type] used in an as cast, like `e as T`. |
| 293 factory TypeUse.asCast(DartType type) { | 293 factory TypeUse.asCast(DartType type) { |
| 294 return new TypeUse._(type, TypeUseKind.AS_CAST); | 294 return new TypeUse.internal(type, TypeUseKind.AS_CAST); |
| 295 } | 295 } |
| 296 | 296 |
| 297 /// [type] used as a type annotation, like `T foo;`. | 297 /// [type] used as a type annotation, like `T foo;`. |
| 298 factory TypeUse.checkedModeCheck(DartType type) { | 298 factory TypeUse.checkedModeCheck(DartType type) { |
| 299 return new TypeUse._(type, TypeUseKind.CHECKED_MODE_CHECK); | 299 return new TypeUse.internal(type, TypeUseKind.CHECKED_MODE_CHECK); |
| 300 } | 300 } |
| 301 | 301 |
| 302 /// [type] used in a on type catch clause, like `try {} on T catch (e) {}`. | 302 /// [type] used in a on type catch clause, like `try {} on T catch (e) {}`. |
| 303 factory TypeUse.catchType(DartType type) { | 303 factory TypeUse.catchType(DartType type) { |
| 304 return new TypeUse._(type, TypeUseKind.CATCH_TYPE); | 304 return new TypeUse.internal(type, TypeUseKind.CATCH_TYPE); |
| 305 } | 305 } |
| 306 | 306 |
| 307 /// [type] used as a type literal, like `foo() => T;`. | 307 /// [type] used as a type literal, like `foo() => T;`. |
| 308 factory TypeUse.typeLiteral(DartType type) { | 308 factory TypeUse.typeLiteral(DartType type) { |
| 309 return new TypeUse._(type, TypeUseKind.TYPE_LITERAL); | 309 return new TypeUse.internal(type, TypeUseKind.TYPE_LITERAL); |
| 310 } | 310 } |
| 311 | 311 |
| 312 /// [type] used in an instantiation, like `new T();`. | 312 /// [type] used in an instantiation, like `new T();`. |
| 313 factory TypeUse.instantiation(InterfaceType type) { | 313 factory TypeUse.instantiation(InterfaceType type) { |
| 314 return new TypeUse._(type, TypeUseKind.INSTANTIATION); | 314 return new TypeUse.internal(type, TypeUseKind.INSTANTIATION); |
| 315 } | 315 } |
| 316 | 316 |
| 317 bool operator ==(other) { | 317 bool operator ==(other) { |
| 318 if (identical(this, other)) return true; | 318 if (identical(this, other)) return true; |
| 319 if (other is! TypeUse) return false; | 319 if (other is! TypeUse) return false; |
| 320 return type == other.type && | 320 return type == other.type && |
| 321 kind == other.kind; | 321 kind == other.kind; |
| 322 } | 322 } |
| 323 | 323 |
| 324 String toString() => 'TypeUse($type,$kind)'; | 324 String toString() => 'TypeUse($type,$kind)'; |
| 325 } | 325 } |
| OLD | NEW |