51b50f7710
Revert "Remove visitLabelElement() and visitLocalVariableElement()."
This reverts commit 2c064df145.
R=brianwilkerson@google.com, paulberry@google.com
BUG=
Review-Url: https://codereview.chromium.org/2977623002 .
473 lines
14 KiB
Dart
473 lines
14 KiB
Dart
// 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 visitGenericFunctionTypeElement(GenericFunctionTypeElement 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 visitGenericFunctionTypeElement(GenericFunctionTypeElement 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 visitGenericFunctionTypeElement(GenericFunctionTypeElement 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 visitGenericFunctionTypeElement(GenericFunctionTypeElement 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}');
|
|
}
|
|
}
|