| 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 /** | |
| 6 * Code for classifying the semantics of identifiers appearing in a Dart file. | |
| 7 */ | |
| 8 library sharedfrontend.access_semantics; | |
| 9 | |
| 10 import '../elements.dart'; | |
| 11 | |
| 12 /** | |
| 13 * Enum representing the different kinds of destinations which a property | |
| 14 * access or method or function invocation might refer to. | |
| 15 */ | |
| 16 class AccessKind { | |
| 17 /** | |
| 18 * The destination of the access is an instance method, property, or field | |
| 19 * of a class, and thus must be determined dynamically. | |
| 20 */ | |
| 21 static const AccessKind DYNAMIC = const AccessKind._('DYNAMIC'); | |
| 22 | |
| 23 /** | |
| 24 * The destination of the access is a function that is defined locally within | |
| 25 * an enclosing function or method. | |
| 26 */ | |
| 27 static const AccessKind LOCAL_FUNCTION = const AccessKind._('LOCAL_FUNCTION'); | |
| 28 | |
| 29 /** | |
| 30 * The destination of the access is a variable that is defined locally within | |
| 31 * an enclosing function or method. | |
| 32 */ | |
| 33 static const AccessKind LOCAL_VARIABLE = const AccessKind._('LOCAL_VARIABLE'); | |
| 34 | |
| 35 /** | |
| 36 * The destination of the access is a variable that is defined as a parameter | |
| 37 * to an enclosing function or method. | |
| 38 */ | |
| 39 static const AccessKind PARAMETER = const AccessKind._('PARAMETER'); | |
| 40 | |
| 41 /** | |
| 42 * The destination of the access is a field that is defined statically within | |
| 43 * a class, or a top level variable within a library. | |
| 44 */ | |
| 45 static const AccessKind STATIC_FIELD = const AccessKind._('STATIC_FIELD'); | |
| 46 | |
| 47 /** | |
| 48 * The destination of the access is a method that is defined statically | |
| 49 * within a class, or at top level within a library. | |
| 50 */ | |
| 51 static const AccessKind STATIC_METHOD = const AccessKind._('STATIC_METHOD'); | |
| 52 | |
| 53 /** | |
| 54 * The destination of the access is a property getter/setter that is defined | |
| 55 * statically within a class, or at top level within a library. | |
| 56 */ | |
| 57 static const AccessKind STATIC_PROPERTY = | |
| 58 const AccessKind._('STATIC_PROPERTY'); | |
| 59 | |
| 60 /** | |
| 61 * The destination of the access is a toplevel class, function typedef, mixin | |
| 62 * application, or the built-in type "dynamic". | |
| 63 */ | |
| 64 static const AccessKind TOPLEVEL_TYPE = const AccessKind._('TOPLEVEL_TYPE'); | |
| 65 | |
| 66 /** | |
| 67 * The destination of the access is a type parameter of the enclosing class. | |
| 68 */ | |
| 69 static const AccessKind TYPE_PARAMETER = const AccessKind._('TYPE_PARAMETER'); | |
| 70 | |
| 71 final String name; | |
| 72 | |
| 73 const AccessKind._(this.name); | |
| 74 | |
| 75 String toString() => name; | |
| 76 } | |
| 77 | |
| 78 /** | |
| 79 * Data structure used to classify the semantics of a property access or method | |
| 80 * or function invocation. | |
| 81 */ | |
| 82 // TODO(paulberry,johnniwinther): Support index operations in AccessSemantics. | |
| 83 class AccessSemantics { | |
| 84 /** | |
| 85 * The kind of access. | |
| 86 */ | |
| 87 final AccessKind kind; | |
| 88 | |
| 89 /** | |
| 90 * The name being used to access the property, method, or function. | |
| 91 */ | |
| 92 final String name; | |
| 93 | |
| 94 /** | |
| 95 * The element being accessed, if statically known. This will be null if | |
| 96 * [kind] is DYNAMIC or if the element is undefined (e.g. an attempt to | |
| 97 * access a non-existent static method in a class). | |
| 98 */ | |
| 99 final Element element; | |
| 100 | |
| 101 /** | |
| 102 * The class containing the element being accessed, if this is a static | |
| 103 * reference to an element in a class. This will be null if [kind] is | |
| 104 * DYNAMIC, LOCAL_FUNCTION, LOCAL_VARIABLE, PARAMETER, TOPLEVEL_CLASS, or | |
| 105 * TYPE_PARAMETER, or if the element being accessed is defined at toplevel | |
| 106 * within a library. | |
| 107 * | |
| 108 * Note: it is possible for [classElement] to be non-null and for [element] | |
| 109 * to be null; for example this occurs if the element being accessed is a | |
| 110 * non-existent static method or field inside an existing class. | |
| 111 */ | |
| 112 final ClassElement classElement; | |
| 113 | |
| 114 // TODO(paulberry): would it also be useful to store the libraryElement? | |
| 115 | |
| 116 /** | |
| 117 * When [kind] is DYNAMIC, the expression whose runtime type determines the | |
| 118 * class in which [identifier] should be looked up. Null if the expression | |
| 119 * is implicit "this". | |
| 120 * | |
| 121 * When [kind] is not DYNAMIC, this field is always null. | |
| 122 */ | |
| 123 final /*Expression*/ target; | |
| 124 | |
| 125 /** | |
| 126 * True if this is an invocation of a method, or a call on a property. | |
| 127 */ | |
| 128 final bool isInvoke; | |
| 129 | |
| 130 /** | |
| 131 * True if this is a read access to a property, or a method tear-off. Note | |
| 132 * that both [isRead] and [isWrite] will be true in the case of a | |
| 133 * read-modify-write operation (e.g. "+="). | |
| 134 */ | |
| 135 final bool isRead;// => !isInvoke && identifier.inGetterContext(); | |
| 136 | |
| 137 /** | |
| 138 * True if this is a write access to a property, or an (erroneous) attempt to | |
| 139 * write to a method. Note that both [isRead] and [isWrite] will be true in | |
| 140 * the case of a read-modify-write operation (e.g. "+="). | |
| 141 */ | |
| 142 final bool isWrite; // => identifier.inSetterContext(); | |
| 143 | |
| 144 AccessSemantics.dynamic( | |
| 145 this.name, | |
| 146 this.target, | |
| 147 {this.isInvoke: false, | |
| 148 this.isRead: false, | |
| 149 this.isWrite: false}) | |
| 150 : kind = AccessKind.DYNAMIC, | |
| 151 element = null, | |
| 152 classElement = null; | |
| 153 | |
| 154 AccessSemantics.localFunction( | |
| 155 this.name, | |
| 156 this.element, | |
| 157 {this.isInvoke: false, | |
| 158 this.isRead: false, | |
| 159 this.isWrite: false}) | |
| 160 : kind = AccessKind.LOCAL_FUNCTION, | |
| 161 classElement = null, | |
| 162 target = null; | |
| 163 | |
| 164 AccessSemantics.localVariable( | |
| 165 this.name, | |
| 166 this.element, | |
| 167 {this.isInvoke: false, | |
| 168 this.isRead: false, | |
| 169 this.isWrite: false}) | |
| 170 : kind = AccessKind.LOCAL_VARIABLE, | |
| 171 classElement = null, | |
| 172 target = null; | |
| 173 | |
| 174 AccessSemantics.parameter( | |
| 175 this.name, | |
| 176 this.element, | |
| 177 {this.isInvoke: false, | |
| 178 this.isRead: false, | |
| 179 this.isWrite: false}) | |
| 180 : kind = AccessKind.PARAMETER, | |
| 181 classElement = null, | |
| 182 target = null; | |
| 183 | |
| 184 AccessSemantics.staticField( | |
| 185 this.name, | |
| 186 this.element, | |
| 187 this.classElement, | |
| 188 {this.isInvoke: false, | |
| 189 this.isRead: false, | |
| 190 this.isWrite: false}) | |
| 191 : kind = AccessKind.STATIC_FIELD, | |
| 192 target = null; | |
| 193 | |
| 194 AccessSemantics.staticMethod( | |
| 195 this.name, | |
| 196 this.element, | |
| 197 this.classElement, | |
| 198 {this.isInvoke: false, | |
| 199 this.isRead: false, | |
| 200 this.isWrite: false}) | |
| 201 : kind = AccessKind.STATIC_METHOD, | |
| 202 target = null; | |
| 203 | |
| 204 AccessSemantics.staticProperty( | |
| 205 this.name, | |
| 206 this.element, | |
| 207 this.classElement, | |
| 208 {this.isInvoke: false, | |
| 209 this.isRead: false, | |
| 210 this.isWrite: false}) | |
| 211 : kind = AccessKind.STATIC_PROPERTY, | |
| 212 target = null; | |
| 213 | |
| 214 AccessSemantics.toplevelType( | |
| 215 this.name, | |
| 216 this.element, | |
| 217 {this.isInvoke: false, | |
| 218 this.isRead: false, | |
| 219 this.isWrite: false}) | |
| 220 : kind = AccessKind.TOPLEVEL_TYPE, | |
| 221 classElement = null, | |
| 222 target = null; | |
| 223 | |
| 224 AccessSemantics.typeParameter( | |
| 225 this.name, | |
| 226 this.element, | |
| 227 {this.isInvoke: false, | |
| 228 this.isRead: false, | |
| 229 this.isWrite: false}) | |
| 230 : kind = AccessKind.TYPE_PARAMETER, | |
| 231 classElement = null, | |
| 232 target = null; | |
| 233 | |
| 234 String toString() { | |
| 235 StringBuffer sb = new StringBuffer(); | |
| 236 sb.write('AccessSemantics['); | |
| 237 sb.write('kind=$kind,'); | |
| 238 if (isRead && isWrite) { | |
| 239 assert(!isInvoke); | |
| 240 sb.write('read/write,'); | |
| 241 } else if (isRead) { | |
| 242 sb.write('read,'); | |
| 243 } else if (isWrite) { | |
| 244 sb.write('write,'); | |
| 245 } else if (isInvoke) { | |
| 246 sb.write('call,'); | |
| 247 } | |
| 248 if (element != null) { | |
| 249 sb.write('element='); | |
| 250 if (classElement != null) { | |
| 251 sb.write('${classElement.name}.'); | |
| 252 } | |
| 253 sb.write('${element}'); | |
| 254 } else { | |
| 255 if (target == null) { | |
| 256 sb.write('target=this.$name'); | |
| 257 } else { | |
| 258 sb.write('target=$target.$name'); | |
| 259 } | |
| 260 } | |
| 261 sb.write(']'); | |
| 262 return sb.toString(); | |
| 263 } | |
| 264 } | |
| OLD | NEW |