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 |