| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2014, 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 * Defines element visitors that support useful patterns for visiting the |
| 7 * elements in an [element model](element.dart). |
| 8 * |
| 9 * Dart is an evolving language, and the element model must evolved with it. |
| 10 * When the element model changes, the visitor interface will sometimes change |
| 11 * as well. If it is desirable to get a compilation error when the structure of |
| 12 * the element model has been modified, then you should consider implementing |
| 13 * the interface [ElementVisitor] directly. Doing so will ensure that changes |
| 14 * that introduce new classes of elements will be flagged. (Of course, not all |
| 15 * changes to the element model require the addition of a new class of element, |
| 16 * and hence cannot be caught this way.) |
| 17 * |
| 18 * But if automatic detection of these kinds of changes is not necessary then |
| 19 * you will probably want to extend one of the classes in this library because |
| 20 * doing so will simplify the task of writing your visitor and guard against |
| 21 * future changes to the element model. For example, the |
| 22 * [RecursiveElementVisitor] automates the process of visiting all of the |
| 23 * descendants of an element. |
| 24 */ |
| 25 library analyzer.dart.element.visitor; |
| 26 |
| 27 import 'package:analyzer/dart/element/element.dart'; |
| 28 |
| 29 /** |
| 30 * An element visitor that will recursively visit all of the elements in an |
| 31 * element model (like instances of the class [RecursiveElementVisitor]). In |
| 32 * addition, when an element of a specific type is visited not only will the |
| 33 * visit method for that specific type of element be invoked, but additional |
| 34 * methods for the supertypes of that element will also be invoked. For example, |
| 35 * using an instance of this class to visit a [MethodElement] will cause the |
| 36 * method [visitMethodElement] to be invoked but will also cause the methods |
| 37 * [visitExecutableElement] and [visitElement] to be subsequently invoked. This |
| 38 * allows visitors to be written that visit all executable elements without |
| 39 * needing to override the visit method for each of the specific subclasses of |
| 40 * [ExecutableElement]. |
| 41 * |
| 42 * Note, however, that unlike many visitors, element visitors visit objects |
| 43 * based on the interfaces implemented by those elements. Because interfaces |
| 44 * form a graph structure rather than a tree structure the way classes do, and |
| 45 * because it is generally undesirable for an object to be visited more than |
| 46 * once, this class flattens the interface graph into a pseudo-tree. In |
| 47 * particular, this class treats elements as if the element types were |
| 48 * structured in the following way: |
| 49 * |
| 50 * <pre> |
| 51 * Element |
| 52 * ClassElement |
| 53 * CompilationUnitElement |
| 54 * ExecutableElement |
| 55 * ConstructorElement |
| 56 * LocalElement |
| 57 * FunctionElement |
| 58 * MethodElement |
| 59 * PropertyAccessorElement |
| 60 * ExportElement |
| 61 * HtmlElement |
| 62 * ImportElement |
| 63 * LabelElement |
| 64 * LibraryElement |
| 65 * MultiplyDefinedElement |
| 66 * PrefixElement |
| 67 * TypeAliasElement |
| 68 * TypeParameterElement |
| 69 * UndefinedElement |
| 70 * VariableElement |
| 71 * PropertyInducingElement |
| 72 * FieldElement |
| 73 * TopLevelVariableElement |
| 74 * LocalElement |
| 75 * LocalVariableElement |
| 76 * ParameterElement |
| 77 * FieldFormalParameterElement |
| 78 * </pre> |
| 79 * |
| 80 * Subclasses that override a visit method must either invoke the overridden |
| 81 * visit method or explicitly invoke the more general visit method. Failure to |
| 82 * do so will cause the visit methods for superclasses of the element to not be |
| 83 * invoked and will cause the children of the visited node to not be visited. |
| 84 * |
| 85 * Clients may extend this class. |
| 86 */ |
| 87 class GeneralizingElementVisitor<R> implements ElementVisitor<R> { |
| 88 @override |
| 89 R visitClassElement(ClassElement element) => visitElement(element); |
| 90 |
| 91 @override |
| 92 R visitCompilationUnitElement(CompilationUnitElement element) => |
| 93 visitElement(element); |
| 94 |
| 95 @override |
| 96 R visitConstructorElement(ConstructorElement element) => |
| 97 visitExecutableElement(element); |
| 98 |
| 99 R visitElement(Element element) { |
| 100 element.visitChildren(this); |
| 101 return null; |
| 102 } |
| 103 |
| 104 R visitExecutableElement(ExecutableElement element) => visitElement(element); |
| 105 |
| 106 @override |
| 107 R visitExportElement(ExportElement element) => visitElement(element); |
| 108 |
| 109 @override |
| 110 R visitFieldElement(FieldElement element) => |
| 111 visitPropertyInducingElement(element); |
| 112 |
| 113 @override |
| 114 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => |
| 115 visitParameterElement(element); |
| 116 |
| 117 @override |
| 118 R visitFunctionElement(FunctionElement element) => visitLocalElement(element); |
| 119 |
| 120 @override |
| 121 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => |
| 122 visitElement(element); |
| 123 |
| 124 @override |
| 125 R visitImportElement(ImportElement element) => visitElement(element); |
| 126 |
| 127 @override |
| 128 R visitLabelElement(LabelElement element) => visitElement(element); |
| 129 |
| 130 @override |
| 131 R visitLibraryElement(LibraryElement element) => visitElement(element); |
| 132 |
| 133 R visitLocalElement(LocalElement element) { |
| 134 if (element is LocalVariableElement) { |
| 135 return visitVariableElement(element); |
| 136 } else if (element is ParameterElement) { |
| 137 return visitVariableElement(element); |
| 138 } else if (element is FunctionElement) { |
| 139 return visitExecutableElement(element); |
| 140 } |
| 141 return null; |
| 142 } |
| 143 |
| 144 @override |
| 145 R visitLocalVariableElement(LocalVariableElement element) => |
| 146 visitLocalElement(element); |
| 147 |
| 148 @override |
| 149 R visitMethodElement(MethodElement element) => |
| 150 visitExecutableElement(element); |
| 151 |
| 152 @override |
| 153 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => |
| 154 visitElement(element); |
| 155 |
| 156 @override |
| 157 R visitParameterElement(ParameterElement element) => |
| 158 visitLocalElement(element); |
| 159 |
| 160 @override |
| 161 R visitPrefixElement(PrefixElement element) => visitElement(element); |
| 162 |
| 163 @override |
| 164 R visitPropertyAccessorElement(PropertyAccessorElement element) => |
| 165 visitExecutableElement(element); |
| 166 |
| 167 R visitPropertyInducingElement(PropertyInducingElement element) => |
| 168 visitVariableElement(element); |
| 169 |
| 170 @override |
| 171 R visitTopLevelVariableElement(TopLevelVariableElement element) => |
| 172 visitPropertyInducingElement(element); |
| 173 |
| 174 @override |
| 175 R visitTypeParameterElement(TypeParameterElement element) => |
| 176 visitElement(element); |
| 177 |
| 178 R visitVariableElement(VariableElement element) => visitElement(element); |
| 179 } |
| 180 |
| 181 /** |
| 182 * A visitor that will recursively visit all of the element in an element model. |
| 183 * For example, using an instance of this class to visit a |
| 184 * [CompilationUnitElement] will also cause all of the types in the compilation |
| 185 * unit to be visited. |
| 186 * |
| 187 * Subclasses that override a visit method must either invoke the overridden |
| 188 * visit method or must explicitly ask the visited element to visit its |
| 189 * children. Failure to do so will cause the children of the visited element to |
| 190 * not be visited. |
| 191 * |
| 192 * Clients may extend this class. |
| 193 */ |
| 194 class RecursiveElementVisitor<R> implements ElementVisitor<R> { |
| 195 @override |
| 196 R visitClassElement(ClassElement element) { |
| 197 element.visitChildren(this); |
| 198 return null; |
| 199 } |
| 200 |
| 201 @override |
| 202 R visitCompilationUnitElement(CompilationUnitElement element) { |
| 203 element.visitChildren(this); |
| 204 return null; |
| 205 } |
| 206 |
| 207 @override |
| 208 R visitConstructorElement(ConstructorElement element) { |
| 209 element.visitChildren(this); |
| 210 return null; |
| 211 } |
| 212 |
| 213 @override |
| 214 R visitExportElement(ExportElement element) { |
| 215 element.visitChildren(this); |
| 216 return null; |
| 217 } |
| 218 |
| 219 @override |
| 220 R visitFieldElement(FieldElement element) { |
| 221 element.visitChildren(this); |
| 222 return null; |
| 223 } |
| 224 |
| 225 @override |
| 226 R visitFieldFormalParameterElement(FieldFormalParameterElement element) { |
| 227 element.visitChildren(this); |
| 228 return null; |
| 229 } |
| 230 |
| 231 @override |
| 232 R visitFunctionElement(FunctionElement element) { |
| 233 element.visitChildren(this); |
| 234 return null; |
| 235 } |
| 236 |
| 237 @override |
| 238 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) { |
| 239 element.visitChildren(this); |
| 240 return null; |
| 241 } |
| 242 |
| 243 @override |
| 244 R visitImportElement(ImportElement element) { |
| 245 element.visitChildren(this); |
| 246 return null; |
| 247 } |
| 248 |
| 249 @override |
| 250 R visitLabelElement(LabelElement element) { |
| 251 element.visitChildren(this); |
| 252 return null; |
| 253 } |
| 254 |
| 255 @override |
| 256 R visitLibraryElement(LibraryElement element) { |
| 257 element.visitChildren(this); |
| 258 return null; |
| 259 } |
| 260 |
| 261 @override |
| 262 R visitLocalVariableElement(LocalVariableElement element) { |
| 263 element.visitChildren(this); |
| 264 return null; |
| 265 } |
| 266 |
| 267 @override |
| 268 R visitMethodElement(MethodElement element) { |
| 269 element.visitChildren(this); |
| 270 return null; |
| 271 } |
| 272 |
| 273 @override |
| 274 R visitMultiplyDefinedElement(MultiplyDefinedElement element) { |
| 275 element.visitChildren(this); |
| 276 return null; |
| 277 } |
| 278 |
| 279 @override |
| 280 R visitParameterElement(ParameterElement element) { |
| 281 element.visitChildren(this); |
| 282 return null; |
| 283 } |
| 284 |
| 285 @override |
| 286 R visitPrefixElement(PrefixElement element) { |
| 287 element.visitChildren(this); |
| 288 return null; |
| 289 } |
| 290 |
| 291 @override |
| 292 R visitPropertyAccessorElement(PropertyAccessorElement element) { |
| 293 element.visitChildren(this); |
| 294 return null; |
| 295 } |
| 296 |
| 297 @override |
| 298 R visitTopLevelVariableElement(TopLevelVariableElement element) { |
| 299 element.visitChildren(this); |
| 300 return null; |
| 301 } |
| 302 |
| 303 @override |
| 304 R visitTypeParameterElement(TypeParameterElement element) { |
| 305 element.visitChildren(this); |
| 306 return null; |
| 307 } |
| 308 } |
| 309 |
| 310 /** |
| 311 * A visitor that will do nothing when visiting an element. It is intended to be |
| 312 * a superclass for classes that use the visitor pattern primarily as a dispatch |
| 313 * mechanism (and hence don't need to recursively visit a whole structure) and |
| 314 * that only need to visit a small number of element types. |
| 315 * |
| 316 * Clients may extend this class. |
| 317 */ |
| 318 class SimpleElementVisitor<R> implements ElementVisitor<R> { |
| 319 @override |
| 320 R visitClassElement(ClassElement element) => null; |
| 321 |
| 322 @override |
| 323 R visitCompilationUnitElement(CompilationUnitElement element) => null; |
| 324 |
| 325 @override |
| 326 R visitConstructorElement(ConstructorElement element) => null; |
| 327 |
| 328 @override |
| 329 R visitExportElement(ExportElement element) => null; |
| 330 |
| 331 @override |
| 332 R visitFieldElement(FieldElement element) => null; |
| 333 |
| 334 @override |
| 335 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => |
| 336 null; |
| 337 |
| 338 @override |
| 339 R visitFunctionElement(FunctionElement element) => null; |
| 340 |
| 341 @override |
| 342 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null; |
| 343 |
| 344 @override |
| 345 R visitImportElement(ImportElement element) => null; |
| 346 |
| 347 @override |
| 348 R visitLabelElement(LabelElement element) => null; |
| 349 |
| 350 @override |
| 351 R visitLibraryElement(LibraryElement element) => null; |
| 352 |
| 353 @override |
| 354 R visitLocalVariableElement(LocalVariableElement element) => null; |
| 355 |
| 356 @override |
| 357 R visitMethodElement(MethodElement element) => null; |
| 358 |
| 359 @override |
| 360 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => null; |
| 361 |
| 362 @override |
| 363 R visitParameterElement(ParameterElement element) => null; |
| 364 |
| 365 @override |
| 366 R visitPrefixElement(PrefixElement element) => null; |
| 367 |
| 368 @override |
| 369 R visitPropertyAccessorElement(PropertyAccessorElement element) => null; |
| 370 |
| 371 @override |
| 372 R visitTopLevelVariableElement(TopLevelVariableElement element) => null; |
| 373 |
| 374 @override |
| 375 R visitTypeParameterElement(TypeParameterElement element) => null; |
| 376 } |
| 377 |
| 378 /** |
| 379 * An AST visitor that will throw an exception if any of the visit methods that |
| 380 * are invoked have not been overridden. It is intended to be a superclass for |
| 381 * classes that implement the visitor pattern and need to (a) override all of |
| 382 * the visit methods or (b) need to override a subset of the visit method and |
| 383 * want to catch when any other visit methods have been invoked. |
| 384 * |
| 385 * Clients may extend this class. |
| 386 */ |
| 387 class ThrowingElementVisitor<R> implements ElementVisitor<R> { |
| 388 @override |
| 389 R visitClassElement(ClassElement element) => _throw(element); |
| 390 |
| 391 @override |
| 392 R visitCompilationUnitElement(CompilationUnitElement element) => |
| 393 _throw(element); |
| 394 |
| 395 @override |
| 396 R visitConstructorElement(ConstructorElement element) => _throw(element); |
| 397 |
| 398 @override |
| 399 R visitExportElement(ExportElement element) => _throw(element); |
| 400 |
| 401 @override |
| 402 R visitFieldElement(FieldElement element) => _throw(element); |
| 403 |
| 404 @override |
| 405 R visitFieldFormalParameterElement(FieldFormalParameterElement element) => |
| 406 _throw(element); |
| 407 |
| 408 @override |
| 409 R visitFunctionElement(FunctionElement element) => _throw(element); |
| 410 |
| 411 @override |
| 412 R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => |
| 413 _throw(element); |
| 414 |
| 415 @override |
| 416 R visitImportElement(ImportElement element) => _throw(element); |
| 417 |
| 418 @override |
| 419 R visitLabelElement(LabelElement element) => _throw(element); |
| 420 |
| 421 @override |
| 422 R visitLibraryElement(LibraryElement element) => _throw(element); |
| 423 |
| 424 @override |
| 425 R visitLocalVariableElement(LocalVariableElement element) => _throw(element); |
| 426 |
| 427 @override |
| 428 R visitMethodElement(MethodElement element) => _throw(element); |
| 429 |
| 430 @override |
| 431 R visitMultiplyDefinedElement(MultiplyDefinedElement element) => |
| 432 _throw(element); |
| 433 |
| 434 @override |
| 435 R visitParameterElement(ParameterElement element) => _throw(element); |
| 436 |
| 437 @override |
| 438 R visitPrefixElement(PrefixElement element) => _throw(element); |
| 439 |
| 440 @override |
| 441 R visitPropertyAccessorElement(PropertyAccessorElement element) => |
| 442 _throw(element); |
| 443 |
| 444 @override |
| 445 R visitTopLevelVariableElement(TopLevelVariableElement element) => |
| 446 _throw(element); |
| 447 |
| 448 @override |
| 449 R visitTypeParameterElement(TypeParameterElement element) => _throw(element); |
| 450 |
| 451 R _throw(Element element) { |
| 452 throw new Exception( |
| 453 'Missing implementation of visit${element.runtimeType}'); |
| 454 } |
| 455 } |
| OLD | NEW |