| 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 library mirrors_util; | 5 library mirrors_util; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue, IterableBase; | 7 import 'dart:collection' show Queue, IterableBase; |
| 8 | 8 |
| 9 // TODO(rnystrom): Use "package:" URL (#4968). | 9 // TODO(rnystrom): Use "package:" URL (#4968). |
| 10 import 'mirrors.dart'; | 10 import 'mirrors.dart'; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 _current = object; | 165 _current = object; |
| 166 object = null; | 166 object = null; |
| 167 return true; | 167 return true; |
| 168 } else { | 168 } else { |
| 169 _current = push(queue.removeFirst()); | 169 _current = push(queue.removeFirst()); |
| 170 return true; | 170 return true; |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 } | 173 } |
| 174 | 174 |
| 175 bool isMixinApplication(Mirror mirror) { |
| 176 return mirror is ClassMirror && mirror.mixin != mirror; |
| 177 } |
| 178 |
| 179 /** |
| 180 * Returns the superclass of [cls] skipping unnamed mixin applications. |
| 181 * |
| 182 * For instance, for all of the following definitions this method returns [:B:]. |
| 183 * |
| 184 * class A extends B {} |
| 185 * class A extends B with C1, C2 {} |
| 186 * class A extends B implements D1, D2 {} |
| 187 * class A extends B with C1, C2 implements D1, D2 {} |
| 188 * class A = B with C1, C2; |
| 189 * abstract class A = B with C1, C2 implements D1, D2; |
| 190 */ |
| 191 ClassMirror getSuperclass(ClassMirror cls) { |
| 192 ClassMirror superclass = cls.superclass; |
| 193 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { |
| 194 superclass = superclass.superclass; |
| 195 } |
| 196 return superclass; |
| 197 } |
| 198 |
| 199 /** |
| 200 * Returns the mixins directly applied to [cls]. |
| 201 * |
| 202 * For instance, for all of the following definitions this method returns |
| 203 * [:C1, C2:]. |
| 204 * |
| 205 * class A extends B with C1, C2 {} |
| 206 * class A extends B with C1, C2 implements D1, D2 {} |
| 207 * class A = B with C1, C2; |
| 208 * abstract class A = B with C1, C2 implements D1, D2; |
| 209 */ |
| 210 Iterable<ClassMirror> getAppliedMixins(ClassMirror cls) { |
| 211 List<ClassMirror> mixins = <ClassMirror>[]; |
| 212 ClassMirror superclass = cls.superclass; |
| 213 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { |
| 214 mixins.add(superclass.mixin); |
| 215 superclass = superclass.superclass; |
| 216 } |
| 217 if (mixins.length > 1) { |
| 218 mixins = new List<ClassMirror>.from(mixins.reversed); |
| 219 } |
| 220 if (isMixinApplication(cls)) { |
| 221 mixins.add(cls.mixin); |
| 222 } |
| 223 return mixins; |
| 224 } |
| 225 |
| 226 /** |
| 227 * Returns the superinterfaces directly and explicitly implemented by [cls]. |
| 228 * |
| 229 * For instance, for all of the following definitions this method returns |
| 230 * [:D1, D2:]. |
| 231 * |
| 232 * class A extends B implements D1, D2 {} |
| 233 * class A extends B with C1, C2 implements D1, D2 {} |
| 234 * abstract class A = B with C1, C2 implements D1, D2; |
| 235 */ |
| 236 Iterable<ClassMirror> getExplicitInterfaces(ClassMirror cls) { |
| 237 if (isMixinApplication(cls)) { |
| 238 bool first = true; |
| 239 ClassMirror mixin = cls.mixin; |
| 240 bool filter(ClassMirror superinterface) { |
| 241 if (first && superinterface == mixin) { |
| 242 first = false; |
| 243 return false; |
| 244 } |
| 245 return true; |
| 246 } |
| 247 return cls.superinterfaces.where(filter); |
| 248 } |
| 249 return cls.superinterfaces; |
| 250 } |
| 251 |
| 175 final RegExp _singleLineCommentStart = new RegExp(r'^///? ?(.*)'); | 252 final RegExp _singleLineCommentStart = new RegExp(r'^///? ?(.*)'); |
| 176 final RegExp _multiLineCommentStartEnd = | 253 final RegExp _multiLineCommentStartEnd = |
| 177 new RegExp(r'^/\*\*? ?([\s\S]*)\*/$', multiLine: true); | 254 new RegExp(r'^/\*\*? ?([\s\S]*)\*/$', multiLine: true); |
| 178 final RegExp _multiLineCommentLineStart = new RegExp(r'^[ \t]*\* ?(.*)'); | 255 final RegExp _multiLineCommentLineStart = new RegExp(r'^[ \t]*\* ?(.*)'); |
| 179 | 256 |
| 180 /** | 257 /** |
| 181 * Pulls the raw text out of a comment (i.e. removes the comment | 258 * Pulls the raw text out of a comment (i.e. removes the comment |
| 182 * characters). | 259 * characters). |
| 183 */ | 260 */ |
| 184 String stripComment(String comment) { | 261 String stripComment(String comment) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 213 } | 290 } |
| 214 return sb.toString(); | 291 return sb.toString(); |
| 215 } | 292 } |
| 216 throw new ArgumentError('Invalid comment $comment'); | 293 throw new ArgumentError('Invalid comment $comment'); |
| 217 } | 294 } |
| 218 | 295 |
| 219 /** | 296 /** |
| 220 * Looks up [name] in the scope [declaration]. | 297 * Looks up [name] in the scope [declaration]. |
| 221 * | 298 * |
| 222 * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of | 299 * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of |
| 223 * [declaration] and if unresolved 'a.b' is looked in the scope of | 300 * [declaration] and if unresolved 'a.b' is looked in the scope of |
| 224 * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is | 301 * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is |
| 225 * then looked up in the local scope of the previous result. | 302 * then looked up in the local scope of the previous result. |
| 226 * | 303 * |
| 227 * For instance, assumming that [:Iterable:] is imported into the scope of | 304 * For instance, assumming that [:Iterable:] is imported into the scope of |
| 228 * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type | 305 * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type |
| 229 * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the | 306 * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the |
| 230 * [:element:] parameter of the [:contains:] method on [:Iterable:]. | 307 * [:element:] parameter of the [:contains:] method on [:Iterable:]. |
| 231 */ | 308 */ |
| 232 DeclarationMirror lookupQualifiedInScope(DeclarationMirror declaration, | 309 DeclarationMirror lookupQualifiedInScope(DeclarationMirror declaration, |
| 233 String name) { | 310 String name) { |
| 234 // TODO(11653): Support lookup of constructors using the [:new Foo:] | 311 // TODO(11653): Support lookup of constructors using the [:new Foo:] |
| 235 // syntax. | 312 // syntax. |
| 236 int offset = 1; | 313 int offset = 1; |
| 237 List<String> parts = name.split('.'); | 314 List<String> parts = name.split('.'); |
| 238 DeclarationMirror result = declaration.lookupInScope(parts[0]); | 315 DeclarationMirror result = declaration.lookupInScope(parts[0]); |
| 239 if (result == null && parts.length > 1) { | 316 if (result == null && parts.length > 1) { |
| 240 // Try lookup of `prefix.id`. | 317 // Try lookup of `prefix.id`. |
| 241 result = declaration.lookupInScope('${parts[0]}.${parts[1]}'); | 318 result = declaration.lookupInScope('${parts[0]}.${parts[1]}'); |
| 242 offset = 2; | 319 offset = 2; |
| 243 } | 320 } |
| 244 if (result == null) return null; | 321 if (result == null) return null; |
| 245 while (result != null && offset < parts.length) { | 322 while (result != null && offset < parts.length) { |
| 246 result = _lookupLocal(result, parts[offset++]); | 323 result = _lookupLocal(result, parts[offset++]); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 262 result = classMirror.typeVariables.firstWhere( | 339 result = classMirror.typeVariables.firstWhere( |
| 263 (TypeVariableMirror v) => v.simpleName == id, orElse: () => null); | 340 (TypeVariableMirror v) => v.simpleName == id, orElse: () => null); |
| 264 } else if (mirror is MethodMirror) { | 341 } else if (mirror is MethodMirror) { |
| 265 MethodMirror methodMirror = mirror; | 342 MethodMirror methodMirror = mirror; |
| 266 result = methodMirror.parameters.firstWhere( | 343 result = methodMirror.parameters.firstWhere( |
| 267 (ParameterMirror p) => p.simpleName == id, orElse: () => null); | 344 (ParameterMirror p) => p.simpleName == id, orElse: () => null); |
| 268 } | 345 } |
| 269 return result; | 346 return result; |
| 270 | 347 |
| 271 } | 348 } |
| OLD | NEW |