| Index: packages/analyzer/lib/dart/element/visitor.dart
|
| diff --git a/packages/analyzer/lib/dart/element/visitor.dart b/packages/analyzer/lib/dart/element/visitor.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c34c7719ae59161ae247d1f9c06a17e87e036737
|
| --- /dev/null
|
| +++ b/packages/analyzer/lib/dart/element/visitor.dart
|
| @@ -0,0 +1,455 @@
|
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +/**
|
| + * Defines element visitors that support useful patterns for visiting the
|
| + * elements in an [element model](element.dart).
|
| + *
|
| + * Dart is an evolving language, and the element model must evolved with it.
|
| + * When the element model changes, the visitor interface will sometimes change
|
| + * as well. If it is desirable to get a compilation error when the structure of
|
| + * the element model has been modified, then you should consider implementing
|
| + * the interface [ElementVisitor] directly. Doing so will ensure that changes
|
| + * that introduce new classes of elements will be flagged. (Of course, not all
|
| + * changes to the element model require the addition of a new class of element,
|
| + * and hence cannot be caught this way.)
|
| + *
|
| + * But if automatic detection of these kinds of changes is not necessary then
|
| + * you will probably want to extend one of the classes in this library because
|
| + * doing so will simplify the task of writing your visitor and guard against
|
| + * future changes to the element model. For example, the
|
| + * [RecursiveElementVisitor] automates the process of visiting all of the
|
| + * descendants of an element.
|
| + */
|
| +library analyzer.dart.element.visitor;
|
| +
|
| +import 'package:analyzer/dart/element/element.dart';
|
| +
|
| +/**
|
| + * An element visitor that will recursively visit all of the elements in an
|
| + * element model (like instances of the class [RecursiveElementVisitor]). In
|
| + * addition, when an element of a specific type is visited not only will the
|
| + * visit method for that specific type of element be invoked, but additional
|
| + * methods for the supertypes of that element will also be invoked. For example,
|
| + * using an instance of this class to visit a [MethodElement] will cause the
|
| + * method [visitMethodElement] to be invoked but will also cause the methods
|
| + * [visitExecutableElement] and [visitElement] to be subsequently invoked. This
|
| + * allows visitors to be written that visit all executable elements without
|
| + * needing to override the visit method for each of the specific subclasses of
|
| + * [ExecutableElement].
|
| + *
|
| + * Note, however, that unlike many visitors, element visitors visit objects
|
| + * based on the interfaces implemented by those elements. Because interfaces
|
| + * form a graph structure rather than a tree structure the way classes do, and
|
| + * because it is generally undesirable for an object to be visited more than
|
| + * once, this class flattens the interface graph into a pseudo-tree. In
|
| + * particular, this class treats elements as if the element types were
|
| + * structured in the following way:
|
| + *
|
| + * <pre>
|
| + * Element
|
| + * ClassElement
|
| + * CompilationUnitElement
|
| + * ExecutableElement
|
| + * ConstructorElement
|
| + * LocalElement
|
| + * FunctionElement
|
| + * MethodElement
|
| + * PropertyAccessorElement
|
| + * ExportElement
|
| + * HtmlElement
|
| + * ImportElement
|
| + * LabelElement
|
| + * LibraryElement
|
| + * MultiplyDefinedElement
|
| + * PrefixElement
|
| + * TypeAliasElement
|
| + * TypeParameterElement
|
| + * UndefinedElement
|
| + * VariableElement
|
| + * PropertyInducingElement
|
| + * FieldElement
|
| + * TopLevelVariableElement
|
| + * LocalElement
|
| + * LocalVariableElement
|
| + * ParameterElement
|
| + * FieldFormalParameterElement
|
| + * </pre>
|
| + *
|
| + * Subclasses that override a visit method must either invoke the overridden
|
| + * visit method or explicitly invoke the more general visit method. Failure to
|
| + * do so will cause the visit methods for superclasses of the element to not be
|
| + * invoked and will cause the children of the visited node to not be visited.
|
| + *
|
| + * Clients may extend this class.
|
| + */
|
| +class GeneralizingElementVisitor<R> implements ElementVisitor<R> {
|
| + @override
|
| + R visitClassElement(ClassElement element) => visitElement(element);
|
| +
|
| + @override
|
| + R visitCompilationUnitElement(CompilationUnitElement element) =>
|
| + visitElement(element);
|
| +
|
| + @override
|
| + R visitConstructorElement(ConstructorElement element) =>
|
| + visitExecutableElement(element);
|
| +
|
| + R visitElement(Element element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + R visitExecutableElement(ExecutableElement element) => visitElement(element);
|
| +
|
| + @override
|
| + R visitExportElement(ExportElement element) => visitElement(element);
|
| +
|
| + @override
|
| + R visitFieldElement(FieldElement element) =>
|
| + visitPropertyInducingElement(element);
|
| +
|
| + @override
|
| + R visitFieldFormalParameterElement(FieldFormalParameterElement element) =>
|
| + visitParameterElement(element);
|
| +
|
| + @override
|
| + R visitFunctionElement(FunctionElement element) => visitLocalElement(element);
|
| +
|
| + @override
|
| + R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) =>
|
| + visitElement(element);
|
| +
|
| + @override
|
| + R visitImportElement(ImportElement element) => visitElement(element);
|
| +
|
| + @override
|
| + R visitLabelElement(LabelElement element) => visitElement(element);
|
| +
|
| + @override
|
| + R visitLibraryElement(LibraryElement element) => visitElement(element);
|
| +
|
| + R visitLocalElement(LocalElement element) {
|
| + if (element is LocalVariableElement) {
|
| + return visitVariableElement(element);
|
| + } else if (element is ParameterElement) {
|
| + return visitVariableElement(element);
|
| + } else if (element is FunctionElement) {
|
| + return visitExecutableElement(element);
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitLocalVariableElement(LocalVariableElement element) =>
|
| + visitLocalElement(element);
|
| +
|
| + @override
|
| + R visitMethodElement(MethodElement element) =>
|
| + visitExecutableElement(element);
|
| +
|
| + @override
|
| + R visitMultiplyDefinedElement(MultiplyDefinedElement element) =>
|
| + visitElement(element);
|
| +
|
| + @override
|
| + R visitParameterElement(ParameterElement element) =>
|
| + visitLocalElement(element);
|
| +
|
| + @override
|
| + R visitPrefixElement(PrefixElement element) => visitElement(element);
|
| +
|
| + @override
|
| + R visitPropertyAccessorElement(PropertyAccessorElement element) =>
|
| + visitExecutableElement(element);
|
| +
|
| + R visitPropertyInducingElement(PropertyInducingElement element) =>
|
| + visitVariableElement(element);
|
| +
|
| + @override
|
| + R visitTopLevelVariableElement(TopLevelVariableElement element) =>
|
| + visitPropertyInducingElement(element);
|
| +
|
| + @override
|
| + R visitTypeParameterElement(TypeParameterElement element) =>
|
| + visitElement(element);
|
| +
|
| + R visitVariableElement(VariableElement element) => visitElement(element);
|
| +}
|
| +
|
| +/**
|
| + * A visitor that will recursively visit all of the element in an element model.
|
| + * For example, using an instance of this class to visit a
|
| + * [CompilationUnitElement] will also cause all of the types in the compilation
|
| + * unit to be visited.
|
| + *
|
| + * Subclasses that override a visit method must either invoke the overridden
|
| + * visit method or must explicitly ask the visited element to visit its
|
| + * children. Failure to do so will cause the children of the visited element to
|
| + * not be visited.
|
| + *
|
| + * Clients may extend this class.
|
| + */
|
| +class RecursiveElementVisitor<R> implements ElementVisitor<R> {
|
| + @override
|
| + R visitClassElement(ClassElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitCompilationUnitElement(CompilationUnitElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitConstructorElement(ConstructorElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitExportElement(ExportElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitFieldElement(FieldElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitFieldFormalParameterElement(FieldFormalParameterElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitFunctionElement(FunctionElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitImportElement(ImportElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitLabelElement(LabelElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitLibraryElement(LibraryElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitLocalVariableElement(LocalVariableElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitMethodElement(MethodElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitMultiplyDefinedElement(MultiplyDefinedElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitParameterElement(ParameterElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitPrefixElement(PrefixElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitPropertyAccessorElement(PropertyAccessorElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitTopLevelVariableElement(TopLevelVariableElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +
|
| + @override
|
| + R visitTypeParameterElement(TypeParameterElement element) {
|
| + element.visitChildren(this);
|
| + return null;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A visitor that will do nothing when visiting an element. It is intended to be
|
| + * a superclass for classes that use the visitor pattern primarily as a dispatch
|
| + * mechanism (and hence don't need to recursively visit a whole structure) and
|
| + * that only need to visit a small number of element types.
|
| + *
|
| + * Clients may extend this class.
|
| + */
|
| +class SimpleElementVisitor<R> implements ElementVisitor<R> {
|
| + @override
|
| + R visitClassElement(ClassElement element) => null;
|
| +
|
| + @override
|
| + R visitCompilationUnitElement(CompilationUnitElement element) => null;
|
| +
|
| + @override
|
| + R visitConstructorElement(ConstructorElement element) => null;
|
| +
|
| + @override
|
| + R visitExportElement(ExportElement element) => null;
|
| +
|
| + @override
|
| + R visitFieldElement(FieldElement element) => null;
|
| +
|
| + @override
|
| + R visitFieldFormalParameterElement(FieldFormalParameterElement element) =>
|
| + null;
|
| +
|
| + @override
|
| + R visitFunctionElement(FunctionElement element) => null;
|
| +
|
| + @override
|
| + R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) => null;
|
| +
|
| + @override
|
| + R visitImportElement(ImportElement element) => null;
|
| +
|
| + @override
|
| + R visitLabelElement(LabelElement element) => null;
|
| +
|
| + @override
|
| + R visitLibraryElement(LibraryElement element) => null;
|
| +
|
| + @override
|
| + R visitLocalVariableElement(LocalVariableElement element) => null;
|
| +
|
| + @override
|
| + R visitMethodElement(MethodElement element) => null;
|
| +
|
| + @override
|
| + R visitMultiplyDefinedElement(MultiplyDefinedElement element) => null;
|
| +
|
| + @override
|
| + R visitParameterElement(ParameterElement element) => null;
|
| +
|
| + @override
|
| + R visitPrefixElement(PrefixElement element) => null;
|
| +
|
| + @override
|
| + R visitPropertyAccessorElement(PropertyAccessorElement element) => null;
|
| +
|
| + @override
|
| + R visitTopLevelVariableElement(TopLevelVariableElement element) => null;
|
| +
|
| + @override
|
| + R visitTypeParameterElement(TypeParameterElement element) => null;
|
| +}
|
| +
|
| +/**
|
| + * An AST visitor that will throw an exception if any of the visit methods that
|
| + * are invoked have not been overridden. It is intended to be a superclass for
|
| + * classes that implement the visitor pattern and need to (a) override all of
|
| + * the visit methods or (b) need to override a subset of the visit method and
|
| + * want to catch when any other visit methods have been invoked.
|
| + *
|
| + * Clients may extend this class.
|
| + */
|
| +class ThrowingElementVisitor<R> implements ElementVisitor<R> {
|
| + @override
|
| + R visitClassElement(ClassElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitCompilationUnitElement(CompilationUnitElement element) =>
|
| + _throw(element);
|
| +
|
| + @override
|
| + R visitConstructorElement(ConstructorElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitExportElement(ExportElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitFieldElement(FieldElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitFieldFormalParameterElement(FieldFormalParameterElement element) =>
|
| + _throw(element);
|
| +
|
| + @override
|
| + R visitFunctionElement(FunctionElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitFunctionTypeAliasElement(FunctionTypeAliasElement element) =>
|
| + _throw(element);
|
| +
|
| + @override
|
| + R visitImportElement(ImportElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitLabelElement(LabelElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitLibraryElement(LibraryElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitLocalVariableElement(LocalVariableElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitMethodElement(MethodElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitMultiplyDefinedElement(MultiplyDefinedElement element) =>
|
| + _throw(element);
|
| +
|
| + @override
|
| + R visitParameterElement(ParameterElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitPrefixElement(PrefixElement element) => _throw(element);
|
| +
|
| + @override
|
| + R visitPropertyAccessorElement(PropertyAccessorElement element) =>
|
| + _throw(element);
|
| +
|
| + @override
|
| + R visitTopLevelVariableElement(TopLevelVariableElement element) =>
|
| + _throw(element);
|
| +
|
| + @override
|
| + R visitTypeParameterElement(TypeParameterElement element) => _throw(element);
|
| +
|
| + R _throw(Element element) {
|
| + throw new Exception(
|
| + 'Missing implementation of visit${element.runtimeType}');
|
| + }
|
| +}
|
|
|