OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// Mixins that implement convenience methods on [Element] subclasses. | 5 /// Mixins that implement convenience methods on [Element] subclasses. |
6 | 6 |
7 library elements.common; | 7 library elements.common; |
8 | 8 |
9 import '../common/names.dart' show | 9 import '../common/names.dart' show Names, Uris; |
10 Names, | 10 import '../core_types.dart' show CoreClasses; |
11 Uris; | 11 import '../dart_types.dart' show DartType, InterfaceType, FunctionType; |
12 import '../core_types.dart' show | 12 import '../util/util.dart' show Link; |
13 CoreClasses; | |
14 import '../dart_types.dart' show | |
15 DartType, | |
16 InterfaceType, | |
17 FunctionType; | |
18 import '../util/util.dart' show | |
19 Link; | |
20 | 13 |
21 import 'elements.dart'; | 14 import 'elements.dart'; |
22 | 15 |
23 abstract class ElementCommon implements Element { | 16 abstract class ElementCommon implements Element { |
24 @override | 17 @override |
25 bool get isLibrary => kind == ElementKind.LIBRARY; | 18 bool get isLibrary => kind == ElementKind.LIBRARY; |
26 | 19 |
27 @override | 20 @override |
28 bool get isCompilationUnit => kind == ElementKind.COMPILATION_UNIT; | 21 bool get isCompilationUnit => kind == ElementKind.COMPILATION_UNIT; |
29 | 22 |
(...skipping 15 matching lines...) Expand all Loading... |
45 @override | 38 @override |
46 bool get isAccessor => isGetter || isSetter; | 39 bool get isAccessor => isGetter || isSetter; |
47 | 40 |
48 @override | 41 @override |
49 bool get isGetter => kind == ElementKind.GETTER; | 42 bool get isGetter => kind == ElementKind.GETTER; |
50 | 43 |
51 @override | 44 @override |
52 bool get isSetter => kind == ElementKind.SETTER; | 45 bool get isSetter => kind == ElementKind.SETTER; |
53 | 46 |
54 @override | 47 @override |
55 bool get isConstructor => isGenerativeConstructor || isFactoryConstructor; | 48 bool get isConstructor => isGenerativeConstructor || isFactoryConstructor; |
56 | 49 |
57 @override | 50 @override |
58 bool get isGenerativeConstructor => | 51 bool get isGenerativeConstructor => |
59 kind == ElementKind.GENERATIVE_CONSTRUCTOR; | 52 kind == ElementKind.GENERATIVE_CONSTRUCTOR; |
60 | 53 |
61 @override | 54 @override |
62 bool get isGenerativeConstructorBody => | 55 bool get isGenerativeConstructorBody => |
63 kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY; | 56 kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY; |
64 | 57 |
65 bool get isFactoryConstructor => | 58 bool get isFactoryConstructor => kind == ElementKind.FACTORY_CONSTRUCTOR; |
66 kind == ElementKind.FACTORY_CONSTRUCTOR; | |
67 | 59 |
68 @override | 60 @override |
69 bool get isVariable => kind == ElementKind.VARIABLE; | 61 bool get isVariable => kind == ElementKind.VARIABLE; |
70 | 62 |
71 @override | 63 @override |
72 bool get isField => kind == ElementKind.FIELD; | 64 bool get isField => kind == ElementKind.FIELD; |
73 | 65 |
74 @override | 66 @override |
75 bool get isAbstractField => kind == ElementKind.ABSTRACT_FIELD; | 67 bool get isAbstractField => kind == ElementKind.ABSTRACT_FIELD; |
76 | 68 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 } | 163 } |
172 | 164 |
173 abstract class CompilationUnitElementCommon implements CompilationUnitElement { | 165 abstract class CompilationUnitElementCommon implements CompilationUnitElement { |
174 int compareTo(CompilationUnitElement other) { | 166 int compareTo(CompilationUnitElement other) { |
175 if (this == other) return 0; | 167 if (this == other) return 0; |
176 return '${script.readableUri}'.compareTo('${other.script.readableUri}'); | 168 return '${script.readableUri}'.compareTo('${other.script.readableUri}'); |
177 } | 169 } |
178 } | 170 } |
179 | 171 |
180 abstract class ClassElementCommon implements ClassElement { | 172 abstract class ClassElementCommon implements ClassElement { |
181 | |
182 @override | 173 @override |
183 Link<DartType> get allSupertypes => allSupertypesAndSelf.supertypes; | 174 Link<DartType> get allSupertypes => allSupertypesAndSelf.supertypes; |
184 | 175 |
185 @override | 176 @override |
186 int get hierarchyDepth => allSupertypesAndSelf.maxDepth; | 177 int get hierarchyDepth => allSupertypesAndSelf.maxDepth; |
187 | 178 |
188 @override | 179 @override |
189 InterfaceType asInstanceOf(ClassElement cls) { | 180 InterfaceType asInstanceOf(ClassElement cls) { |
190 if (cls == this) return thisType; | 181 if (cls == this) return thisType; |
191 return allSupertypesAndSelf.asInstanceOf(cls); | 182 return allSupertypesAndSelf.asInstanceOf(cls); |
192 } | 183 } |
193 | 184 |
194 @override | 185 @override |
195 ConstructorElement lookupConstructor(String name) { | 186 ConstructorElement lookupConstructor(String name) { |
196 Element result = localLookup(name); | 187 Element result = localLookup(name); |
197 return result != null && result.isConstructor ? result : null; | 188 return result != null && result.isConstructor ? result : null; |
198 } | 189 } |
199 | 190 |
200 | |
201 /** | 191 /** |
202 * Find the first member in the class chain with the given [memberName]. | 192 * Find the first member in the class chain with the given [memberName]. |
203 * | 193 * |
204 * This method is NOT to be used for resolving | 194 * This method is NOT to be used for resolving |
205 * unqualified sends because it does not implement the scoping | 195 * unqualified sends because it does not implement the scoping |
206 * rules, where library scope comes before superclass scope. | 196 * rules, where library scope comes before superclass scope. |
207 * | 197 * |
208 * When called on the implementation element both members declared in the | 198 * When called on the implementation element both members declared in the |
209 * origin and the patch class are returned. | 199 * origin and the patch class are returned. |
210 */ | 200 */ |
211 Element lookupByName(Name memberName) { | 201 Element lookupByName(Name memberName) { |
212 return internalLookupByName(memberName, isSuperLookup: false); | 202 return internalLookupByName(memberName, isSuperLookup: false); |
213 } | 203 } |
214 | 204 |
215 Element lookupSuperByName(Name memberName) { | 205 Element lookupSuperByName(Name memberName) { |
216 return internalLookupByName(memberName, isSuperLookup: true); | 206 return internalLookupByName(memberName, isSuperLookup: true); |
217 } | 207 } |
218 | 208 |
219 Element internalLookupByName(Name memberName, {bool isSuperLookup}) { | 209 Element internalLookupByName(Name memberName, {bool isSuperLookup}) { |
220 String name = memberName.text; | 210 String name = memberName.text; |
221 bool isPrivate = memberName.isPrivate; | 211 bool isPrivate = memberName.isPrivate; |
222 LibraryElement library = memberName.library; | 212 LibraryElement library = memberName.library; |
223 for (ClassElement current = isSuperLookup ? superclass : this; | 213 for (ClassElement current = isSuperLookup ? superclass : this; |
224 current != null; | 214 current != null; |
225 current = current.superclass) { | 215 current = current.superclass) { |
226 Element member = current.lookupLocalMember(name); | 216 Element member = current.lookupLocalMember(name); |
227 if (member == null && current.isPatched) { | 217 if (member == null && current.isPatched) { |
228 // Doing lookups on selectors is done after resolution, so it | 218 // Doing lookups on selectors is done after resolution, so it |
229 // is safe to look in the patch class. | 219 // is safe to look in the patch class. |
230 member = current.patch.lookupLocalMember(name); | 220 member = current.patch.lookupLocalMember(name); |
231 } | 221 } |
232 if (member == null) continue; | 222 if (member == null) continue; |
233 // Private members from a different library are not visible. | 223 // Private members from a different library are not visible. |
234 if (isPrivate && !identical(library, member.library)) continue; | 224 if (isPrivate && !identical(library, member.library)) continue; |
235 // Static members are not inherited. | 225 // Static members are not inherited. |
236 if (member.isStatic && !identical(this, current)) continue; | 226 if (member.isStatic && !identical(this, current)) continue; |
237 // If we find an abstract field we have to make sure that it has | 227 // If we find an abstract field we have to make sure that it has |
238 // the getter or setter part we're actually looking | 228 // the getter or setter part we're actually looking |
239 // for. Otherwise, we continue up the superclass chain. | 229 // for. Otherwise, we continue up the superclass chain. |
240 if (member.isAbstractField) { | 230 if (member.isAbstractField) { |
241 AbstractFieldElement field = member; | 231 AbstractFieldElement field = member; |
242 FunctionElement getter = field.getter; | 232 FunctionElement getter = field.getter; |
243 FunctionElement setter = field.setter; | 233 FunctionElement setter = field.setter; |
244 if (memberName.isSetter) { | 234 if (memberName.isSetter) { |
245 // Abstract members can be defined in a super class. | 235 // Abstract members can be defined in a super class. |
246 if (setter != null && !setter.isAbstract) { | 236 if (setter != null && !setter.isAbstract) { |
247 return setter; | 237 return setter; |
248 } | 238 } |
249 } else { | 239 } else { |
250 if (getter != null && !getter.isAbstract) { | 240 if (getter != null && !getter.isAbstract) { |
251 return getter; | 241 return getter; |
252 } | 242 } |
253 } | 243 } |
254 // Abstract members can be defined in a super class. | 244 // Abstract members can be defined in a super class. |
255 } else if (!member.isAbstract) { | 245 } else if (!member.isAbstract) { |
256 return member; | 246 return member; |
257 } | 247 } |
258 } | 248 } |
259 return null; | 249 return null; |
260 } | 250 } |
261 | 251 |
262 /** | 252 /** |
263 * Find the first member in the class chain with the given | 253 * Find the first member in the class chain with the given |
264 * [memberName]. This method is NOT to be used for resolving | 254 * [memberName]. This method is NOT to be used for resolving |
(...skipping 23 matching lines...) Expand all Loading... |
288 @override | 278 @override |
289 Element lookupSuperMember(String memberName) { | 279 Element lookupSuperMember(String memberName) { |
290 return lookupSuperMemberInLibrary(memberName, library); | 280 return lookupSuperMemberInLibrary(memberName, library); |
291 } | 281 } |
292 | 282 |
293 /** | 283 /** |
294 * Lookup super members for the class that is accessible in [library]. | 284 * Lookup super members for the class that is accessible in [library]. |
295 * This will ignore constructors. | 285 * This will ignore constructors. |
296 */ | 286 */ |
297 @override | 287 @override |
298 Element lookupSuperMemberInLibrary(String memberName, | 288 Element lookupSuperMemberInLibrary( |
299 LibraryElement library) { | 289 String memberName, LibraryElement library) { |
300 bool isPrivate = Name.isPrivateName(memberName); | 290 bool isPrivate = Name.isPrivateName(memberName); |
301 for (ClassElement s = superclass; s != null; s = s.superclass) { | 291 for (ClassElement s = superclass; s != null; s = s.superclass) { |
302 // Private members from a different library are not visible. | 292 // Private members from a different library are not visible. |
303 if (isPrivate && !identical(library, s.library)) continue; | 293 if (isPrivate && !identical(library, s.library)) continue; |
304 Element e = s.lookupLocalMember(memberName); | 294 Element e = s.lookupLocalMember(memberName); |
305 if (e == null) continue; | 295 if (e == null) continue; |
306 // Static members are not inherited. | 296 // Static members are not inherited. |
307 if (e.isStatic) continue; | 297 if (e.isStatic) continue; |
308 return e; | 298 return e; |
309 } | 299 } |
(...skipping 15 matching lines...) Expand all Loading... |
325 * | 315 * |
326 * The enclosing class is passed to the callback. This is useful when | 316 * The enclosing class is passed to the callback. This is useful when |
327 * [includeSuperAndInjectedMembers] is [:true:]. | 317 * [includeSuperAndInjectedMembers] is [:true:]. |
328 * | 318 * |
329 * When called on an implementation element both the members in the origin | 319 * When called on an implementation element both the members in the origin |
330 * and patch class are included. | 320 * and patch class are included. |
331 */ | 321 */ |
332 // TODO(johnniwinther): Clean up lookup to get rid of the include predicates. | 322 // TODO(johnniwinther): Clean up lookup to get rid of the include predicates. |
333 @override | 323 @override |
334 void forEachMember(void f(ClassElement enclosingClass, Element member), | 324 void forEachMember(void f(ClassElement enclosingClass, Element member), |
335 {includeBackendMembers: false, | 325 {includeBackendMembers: false, includeSuperAndInjectedMembers: false}) { |
336 includeSuperAndInjectedMembers: false}) { | |
337 bool includeInjectedMembers = includeSuperAndInjectedMembers || isPatch; | 326 bool includeInjectedMembers = includeSuperAndInjectedMembers || isPatch; |
338 ClassElement classElement = declaration; | 327 ClassElement classElement = declaration; |
339 do { | 328 do { |
340 // Iterate through the members in textual order, which requires | 329 // Iterate through the members in textual order, which requires |
341 // to reverse the data structure [localMembers] we created. | 330 // to reverse the data structure [localMembers] we created. |
342 // Textual order may be important for certain operations, for | 331 // Textual order may be important for certain operations, for |
343 // example when emitting the initializers of fields. | 332 // example when emitting the initializers of fields. |
344 classElement.forEachLocalMember((e) => f(classElement, e)); | 333 classElement.forEachLocalMember((e) => f(classElement, e)); |
345 if (includeBackendMembers) { | 334 if (includeBackendMembers) { |
346 classElement.forEachBackendMember((e) => f(classElement, e)); | 335 classElement.forEachBackendMember((e) => f(classElement, e)); |
347 } | 336 } |
348 if (includeInjectedMembers) { | 337 if (includeInjectedMembers) { |
349 if (classElement.isPatched) { | 338 if (classElement.isPatched) { |
350 classElement.patch.forEachLocalMember((e) { | 339 classElement.patch.forEachLocalMember((e) { |
351 if (!e.isPatch) f(classElement, e); | 340 if (!e.isPatch) f(classElement, e); |
352 }); | 341 }); |
353 } | 342 } |
354 } | 343 } |
355 classElement = includeSuperAndInjectedMembers | 344 classElement = |
356 ? classElement.superclass | 345 includeSuperAndInjectedMembers ? classElement.superclass : null; |
357 : null; | |
358 } while (classElement != null); | 346 } while (classElement != null); |
359 } | 347 } |
360 | 348 |
361 /** | 349 /** |
362 * Runs through all instance-field members of this class. | 350 * Runs through all instance-field members of this class. |
363 * | 351 * |
364 * The enclosing class is passed to the callback. This is useful when | 352 * The enclosing class is passed to the callback. This is useful when |
365 * [includeSuperAndInjectedMembers] is [:true:]. | 353 * [includeSuperAndInjectedMembers] is [:true:]. |
366 * | 354 * |
367 * When called on the implementation element both the fields declared in the | 355 * When called on the implementation element both the fields declared in the |
368 * origin and in the patch are included. | 356 * origin and in the patch are included. |
369 */ | 357 */ |
370 @override | 358 @override |
371 void forEachInstanceField(void f(ClassElement enclosingClass, | 359 void forEachInstanceField( |
372 FieldElement field), | 360 void f(ClassElement enclosingClass, FieldElement field), |
373 {bool includeSuperAndInjectedMembers: false}) { | 361 {bool includeSuperAndInjectedMembers: false}) { |
374 // Filters so that [f] is only invoked with instance fields. | 362 // Filters so that [f] is only invoked with instance fields. |
375 void fieldFilter(ClassElement enclosingClass, Element member) { | 363 void fieldFilter(ClassElement enclosingClass, Element member) { |
376 if (member.isInstanceMember && member.kind == ElementKind.FIELD) { | 364 if (member.isInstanceMember && member.kind == ElementKind.FIELD) { |
377 f(enclosingClass, member); | 365 f(enclosingClass, member); |
378 } | 366 } |
379 } | 367 } |
380 | 368 |
381 forEachMember(fieldFilter, | 369 forEachMember(fieldFilter, |
382 includeSuperAndInjectedMembers: includeSuperAndInjectedMembers); | 370 includeSuperAndInjectedMembers: includeSuperAndInjectedMembers); |
383 } | 371 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 } | 414 } |
427 | 415 |
428 @override | 416 @override |
429 bool implementsInterface(ClassElement intrface) { | 417 bool implementsInterface(ClassElement intrface) { |
430 return this != intrface && | 418 return this != intrface && |
431 allSupertypesAndSelf.asInstanceOf(intrface) != null; | 419 allSupertypesAndSelf.asInstanceOf(intrface) != null; |
432 } | 420 } |
433 | 421 |
434 @override | 422 @override |
435 bool implementsFunction(CoreClasses coreClasses) { | 423 bool implementsFunction(CoreClasses coreClasses) { |
436 return asInstanceOf(coreClasses.functionClass) != null || | 424 return asInstanceOf(coreClasses.functionClass) != null || callType != null; |
437 callType != null; | |
438 } | 425 } |
439 | 426 |
440 @override | 427 @override |
441 bool isSubclassOf(ClassElement cls) { | 428 bool isSubclassOf(ClassElement cls) { |
442 // Use [declaration] for both [this] and [cls], because | 429 // Use [declaration] for both [this] and [cls], because |
443 // declaration classes hold the superclass hierarchy. | 430 // declaration classes hold the superclass hierarchy. |
444 cls = cls.declaration; | 431 cls = cls.declaration; |
445 for (ClassElement s = declaration; s != null; s = s.superclass) { | 432 for (ClassElement s = declaration; s != null; s = s.superclass) { |
446 if (identical(s, cls)) return true; | 433 if (identical(s, cls)) return true; |
447 } | 434 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 if (optionalParametersAreNamed) { | 478 if (optionalParametersAreNamed) { |
492 if (!signature.optionalParametersAreNamed) { | 479 if (!signature.optionalParametersAreNamed) { |
493 return requiredParameterCount == signature.parameterCount; | 480 return requiredParameterCount == signature.parameterCount; |
494 } | 481 } |
495 // If both signatures have named parameters, then they must have | 482 // If both signatures have named parameters, then they must have |
496 // the same number of required parameters, and the names in | 483 // the same number of required parameters, and the names in |
497 // [signature] must all be in [:this:]. | 484 // [signature] must all be in [:this:]. |
498 if (requiredParameterCount != signature.requiredParameterCount) { | 485 if (requiredParameterCount != signature.requiredParameterCount) { |
499 return false; | 486 return false; |
500 } | 487 } |
501 Set<String> names = optionalParameters.map( | 488 Set<String> names = |
502 (Element element) => element.name).toSet(); | 489 optionalParameters.map((Element element) => element.name).toSet(); |
503 for (Element namedParameter in signature.optionalParameters) { | 490 for (Element namedParameter in signature.optionalParameters) { |
504 if (!names.contains(namedParameter.name)) { | 491 if (!names.contains(namedParameter.name)) { |
505 return false; | 492 return false; |
506 } | 493 } |
507 } | 494 } |
508 } else { | 495 } else { |
509 if (signature.optionalParametersAreNamed) return false; | 496 if (signature.optionalParametersAreNamed) return false; |
510 // There must be at least as many arguments as in the other signature, but | 497 // There must be at least as many arguments as in the other signature, but |
511 // this signature must not have more required parameters. Having more | 498 // this signature must not have more required parameters. Having more |
512 // optional parameters is not a problem, they simply are never provided | 499 // optional parameters is not a problem, they simply are never provided |
513 // by call sites of a call to a method with the other signature. | 500 // by call sites of a call to a method with the other signature. |
514 int otherTotalCount = signature.parameterCount; | 501 int otherTotalCount = signature.parameterCount; |
515 return requiredParameterCount <= otherTotalCount | 502 return requiredParameterCount <= otherTotalCount && |
516 && parameterCount >= otherTotalCount; | 503 parameterCount >= otherTotalCount; |
517 } | 504 } |
518 return true; | 505 return true; |
519 } | 506 } |
520 } | 507 } |
521 | 508 |
522 abstract class MixinApplicationElementCommon | 509 abstract class MixinApplicationElementCommon |
523 implements MixinApplicationElement { | 510 implements MixinApplicationElement { |
524 Link<ConstructorElement> get constructors { | 511 Link<ConstructorElement> get constructors { |
525 throw new UnsupportedError('Unimplemented $this.constructors'); | 512 throw new UnsupportedError('Unimplemented $this.constructors'); |
526 } | 513 } |
527 | 514 |
528 FunctionElement _lookupLocalConstructor(String name) { | 515 FunctionElement _lookupLocalConstructor(String name) { |
529 for (Link<Element> link = constructors; | 516 for (Link<Element> link = constructors; !link.isEmpty; link = link.tail) { |
530 !link.isEmpty; | |
531 link = link.tail) { | |
532 if (link.head.name == name) return link.head; | 517 if (link.head.name == name) return link.head; |
533 } | 518 } |
534 return null; | 519 return null; |
535 } | 520 } |
536 | 521 |
537 @override | 522 @override |
538 Element localLookup(String name) { | 523 Element localLookup(String name) { |
539 Element constructor = _lookupLocalConstructor(name); | 524 Element constructor = _lookupLocalConstructor(name); |
540 if (constructor != null) return constructor; | 525 if (constructor != null) return constructor; |
541 if (mixin == null) return null; | 526 if (mixin == null) return null; |
542 Element mixedInElement = mixin.localLookup(name); | 527 Element mixedInElement = mixin.localLookup(name); |
543 if (mixedInElement == null) return null; | 528 if (mixedInElement == null) return null; |
544 return mixedInElement.isInstanceMember ? mixedInElement : null; | 529 return mixedInElement.isInstanceMember ? mixedInElement : null; |
545 } | 530 } |
546 | 531 |
547 @override | 532 @override |
548 void forEachLocalMember(void f(Element member)) { | 533 void forEachLocalMember(void f(Element member)) { |
549 constructors.forEach(f); | 534 constructors.forEach(f); |
550 if (mixin != null) mixin.forEachLocalMember((Element mixedInElement) { | 535 if (mixin != null) |
| 536 mixin.forEachLocalMember((Element mixedInElement) { |
551 if (mixedInElement.isInstanceMember) f(mixedInElement); | 537 if (mixedInElement.isInstanceMember) f(mixedInElement); |
552 }); | 538 }); |
553 } | 539 } |
554 } | 540 } |
OLD | NEW |