blob: 185357dd1e83c44157637fcaa36b48c1376fc467 [file] [log] [blame]
// 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 or implement 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 or implement 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 or implement 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;
}