public final class CheckEventfulObjectDisposal extends java.lang.Object implements CompilerPass
An eventful class is any class that derives from goog.events.EventHandler or (in aggressive mode) is disposable and disposes of an eventful class when it is disposed (see http://research.google.com/pubs/pub40738.html).
This pass is heuristic based and should not be used for any check of pass/fail testing. The pass traverses the AST and marks as errors cases where an eventful object is allocated but a dispose call is not found. It only tracks eventful objects that has a easily identifiable static name, i.e., objects assigned to arrays, returned from functions or captured in closures are not considered. It simply tries to see if there exists a call to a dispose method in the AST for every object seen as eventful.
This compiler pass uses the inferred types and hence either type checking or type inference needs to be enabled.
Modifier and Type | Class and Description |
---|---|
private class |
CheckEventfulObjectDisposal.ComputeEventizeTraversal |
static class |
CheckEventfulObjectDisposal.DisposalCheckingPolicy
Policies to determine the disposal checking level.
|
private static class |
CheckEventfulObjectDisposal.EventfulObjectState |
private static class |
CheckEventfulObjectDisposal.SeenType |
private class |
CheckEventfulObjectDisposal.Traversal |
Modifier and Type | Field and Description |
---|---|
private CheckEventfulObjectDisposal.DisposalCheckingPolicy |
checkingPolicy |
private AbstractCompiler |
compiler |
private static java.lang.String |
DISPOSABLE_INTERFACE_TYPE_NAME |
static int |
DISPOSE_ALL
Constant used to signify all arguments of method/function
should be marked as disposed.
|
static int |
DISPOSE_SELF
Constant used to signify that object on which this method is called,
will itself get disposed of.
|
private java.util.Map<JSType,java.util.Map<java.lang.String,java.util.List<java.lang.Integer>>> |
disposeCalls |
private static java.lang.String |
EVENT_HANDLER_TYPE_NAME |
(package private) static DiagnosticType |
EVENTFUL_OBJECT_NOT_DISPOSED |
(package private) static DiagnosticType |
EVENTFUL_OBJECT_PURELY_LOCAL |
private static java.util.Map<java.lang.String,CheckEventfulObjectDisposal.EventfulObjectState> |
eventfulObjectMap |
private java.util.Set<JSType> |
eventfulTypes |
private java.util.Map<java.lang.String,java.util.Set<java.lang.String>> |
eventizes |
private JSType |
googDisposableInterfaceType |
private JSType |
googEventsEventHandlerType |
(package private) static DiagnosticType |
OVERWRITE_PRIVATE_EVENTFUL_OBJECT |
private TypeIRegistry |
typeRegistry |
(package private) static DiagnosticType |
UNLISTEN_WITH_ANONBOUND |
Constructor and Description |
---|
CheckEventfulObjectDisposal(AbstractCompiler compiler,
CheckEventfulObjectDisposal.DisposalCheckingPolicy checkingPolicy) |
Modifier and Type | Method and Description |
---|---|
private void |
addDisposeCall(java.lang.String functionOrMethodName,
java.util.List<java.lang.Integer> argumentsThatAreDisposed)
Add a new call that is used to dispose an JS object.
|
private void |
computeEventful() |
private static JSType |
dereference(JSType type) |
private static java.lang.String |
generateKey(NodeTraversal t,
Node n,
boolean noLocalVariables) |
private static Node |
getBase(Node n) |
private static JSType |
getTypeOfThisForScope(NodeTraversal t) |
private void |
initializeDisposeMethodsMap() |
private static boolean |
isPossiblySubtype(JSType thisType,
JSType thatType)
Determines if thisType is possibly a subtype of thatType.
|
private JSType |
maybeReturnDisposedType(Node n,
boolean checkDispose) |
void |
process(Node externs,
Node root)
Process the JS with root node root.
|
static final DiagnosticType EVENTFUL_OBJECT_NOT_DISPOSED
static final DiagnosticType EVENTFUL_OBJECT_PURELY_LOCAL
static final DiagnosticType OVERWRITE_PRIVATE_EVENTFUL_OBJECT
static final DiagnosticType UNLISTEN_WITH_ANONBOUND
private static final java.lang.String DISPOSABLE_INTERFACE_TYPE_NAME
private static final java.lang.String EVENT_HANDLER_TYPE_NAME
private JSType googDisposableInterfaceType
private JSType googEventsEventHandlerType
private java.util.Set<JSType> eventfulTypes
private java.util.Map<JSType,java.util.Map<java.lang.String,java.util.List<java.lang.Integer>>> disposeCalls
public static final int DISPOSE_ALL
public static final int DISPOSE_SELF
private final AbstractCompiler compiler
private final TypeIRegistry typeRegistry
private final CheckEventfulObjectDisposal.DisposalCheckingPolicy checkingPolicy
private java.util.Map<java.lang.String,java.util.Set<java.lang.String>> eventizes
private static java.util.Map<java.lang.String,CheckEventfulObjectDisposal.EventfulObjectState> eventfulObjectMap
public CheckEventfulObjectDisposal(AbstractCompiler compiler, CheckEventfulObjectDisposal.DisposalCheckingPolicy checkingPolicy)
private void addDisposeCall(java.lang.String functionOrMethodName, java.util.List<java.lang.Integer> argumentsThatAreDisposed)
functionOrMethodName
- The name or suffix of a function or method
that disposes of/registers an object as disposableargumentsThatAreDisposed
- An array of integers (ideally sorted) that
specifies the arguments of the function being disposedprivate void initializeDisposeMethodsMap()
private static JSType getTypeOfThisForScope(NodeTraversal t)
private static boolean isPossiblySubtype(JSType thisType, JSType thatType)
It differs from isSubtype only in that thisType gets expanded if it is a union.
Common case targeted is a function returning an eventful object that may also return a null.
thisType
- the JSType being testedthatType
- the JSType that is possibly a base of thisTypeprivate static java.lang.String generateKey(NodeTraversal t, Node n, boolean noLocalVariables)
public void process(Node externs, Node root)
CompilerPass
process
in interface CompilerPass
externs
- Top of external JS treeroot
- Top of JS treeprivate void computeEventful()