OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'dart:collection' show HashMap, HashSet; | |
6 import 'package:analyzer/dart/ast/ast.dart' show Identifier; | |
7 import 'package:analyzer/dart/element/element.dart'; | |
8 | |
9 import 'js_codegen.dart' show ExtensionTypeSet; | |
10 | |
11 /// We use a storage slot for fields that override or can be overridden by | |
12 /// getter/setter pairs. | |
13 HashSet<FieldElement> findFieldsNeedingStorage( | |
14 Iterable<CompilationUnitElement> units, ExtensionTypeSet extensionTypes) { | |
15 var overrides = new HashSet<FieldElement>(); | |
16 for (var unit in units) { | |
17 for (var cls in unit.types) { | |
18 var superclasses = getSuperclasses(cls); | |
19 for (var field in cls.fields) { | |
20 if (!field.isSynthetic && !overrides.contains(field)) { | |
21 checkForPropertyOverride( | |
22 field, superclasses, overrides, extensionTypes); | |
23 } | |
24 } | |
25 } | |
26 } | |
27 | |
28 return overrides; | |
29 } | |
30 | |
31 void checkForPropertyOverride( | |
32 FieldElement field, | |
33 List<ClassElement> superclasses, | |
34 HashSet<FieldElement> overrides, | |
35 ExtensionTypeSet extensionTypes) { | |
36 assert(!field.isSynthetic); | |
37 | |
38 var library = field.library; | |
39 | |
40 bool found = false; | |
41 for (var superclass in superclasses) { | |
42 var superprop = getProperty(superclass, library, field.name); | |
43 if (superprop != null) { | |
44 // If we find an abstract getter/setter pair, stop the search. | |
45 var getter = superprop.getter; | |
46 var setter = superprop.setter; | |
47 if (!extensionTypes.contains(superclass) && | |
48 (getter == null || getter.isAbstract) && | |
49 (setter == null || setter.isAbstract)) { | |
50 break; | |
51 } | |
52 | |
53 found = true; | |
54 // Record that the super property is overridden. | |
55 if (superprop.library == library) overrides.add(superprop); | |
56 } | |
57 } | |
58 | |
59 // If this we found a super property, then this property overrides it. | |
60 if (found) overrides.add(field); | |
61 } | |
62 | |
63 FieldElement getProperty( | |
64 ClassElement cls, LibraryElement fromLibrary, String name) { | |
65 // Properties from a different library are not accessible. | |
66 if (Identifier.isPrivateName(name) && cls.library != fromLibrary) { | |
67 return null; | |
68 } | |
69 for (var accessor in cls.accessors) { | |
70 var prop = accessor.variable; | |
71 if (prop.name == name) return prop; | |
72 } | |
73 return null; | |
74 } | |
75 | |
76 List<ClassElement> getSuperclasses(ClassElement cls) { | |
77 var result = <ClassElement>[]; | |
78 var visited = new HashSet<ClassElement>(); | |
79 while (cls != null && visited.add(cls)) { | |
80 for (var mixinType in cls.mixins.reversed) { | |
81 var mixin = mixinType.element; | |
82 if (mixin != null) result.add(mixin); | |
83 } | |
84 var supertype = cls.supertype; | |
85 if (supertype == null) break; | |
86 | |
87 cls = supertype.element; | |
88 result.add(cls); | |
89 } | |
90 return result; | |
91 } | |
OLD | NEW |