in nullaway/src/main/java/com/uber/nullaway/handlers/Handler.java [75:445]
void onMatchTopLevelClass(
NullAway analysis, ClassTree tree, VisitorState state, Symbol.ClassSymbol classSymbol);
/**
* Called when NullAway first matches a particular method node.
*
* @param tree The AST node for the method being matched.
* @param methodAnalysisContext The MethodAnalysisContext object
*/
void onMatchMethod(MethodTree tree, MethodAnalysisContext methodAnalysisContext);
/**
* Called when NullAway first matches a particular method call-site.
*
* @param tree The AST node for the method invocation (call-site) being matched.
* @param methodAnalysisContext The MethodAnalysisContext object
*/
void onMatchMethodInvocation(
MethodInvocationTree tree, MethodAnalysisContext methodAnalysisContext);
/**
* Called when NullAway first matches a particular lambda expression.
*
* @param tree The AST node for the lambda expression being matched.
* @param methodAnalysisContext The MethodAnalysisContext object
*/
void onMatchLambdaExpression(
LambdaExpressionTree tree, MethodAnalysisContext methodAnalysisContext);
/**
* Called when NullAway first matches a particular method reference expression
*
* @param tree The AST node for the method reference expression being matched.
* @param methodAnalysisContext The MethodAnalysisContext object
*/
void onMatchMethodReference(
MemberReferenceTree tree, MethodAnalysisContext methodAnalysisContext);
/**
* Called when NullAway first matches a return statement.
*
* @param analysis A reference to the running NullAway analysis.
* @param tree The AST node for the return statement being matched.
* @param state The current visitor state.
*/
void onMatchReturn(NullAway analysis, ReturnTree tree, VisitorState state);
/**
* Called after the analysis determines if a expression can be null or not, allowing handlers to
* override.
*
* @param analysis A reference to the running NullAway analysis.
* @param expr The expression in question.
* @param exprSymbol The symbol of the expression, might be null
* @param state The current visitor state.
* @param exprMayBeNull Whether or not the expression may be null according to the base analysis
* or upstream handlers.
* @return Whether or not the expression may be null, as updated by this handler.
*/
boolean onOverrideMayBeNullExpr(
NullAway analysis,
ExpressionTree expr,
@Nullable Symbol exprSymbol,
VisitorState state,
boolean exprMayBeNull);
/**
* Called to potentially override the nullability of an annotated or unannotated method's return,
* when only the method symbol (and not a full invocation tree) is available. This is used
* primarily for checking subtyping / method overrides.
*
* @param methodSymbol The method symbol for the method in question.
* @param state The current visitor state.
* @param isAnnotated A boolean flag indicating whether the called method is considered to be
* within annotated or unannotated code, used to avoid querying for this information multiple
* times within the same handler chain.
* @param returnNullness return nullness computed by upstream handlers or NullAway core.
* @return Updated return nullability computed by this handler.
*/
Nullness onOverrideMethodReturnNullability(
Symbol.MethodSymbol methodSymbol,
VisitorState state,
boolean isAnnotated,
Nullness returnNullness);
/**
* Called to potentially override the nullability of a field which is not annotated as @Nullable.
* If the field is decided to be @Nullable by this handler, the field should be treated
* as @Nullable anyway.
*
* @param field The symbol for the field in question.
* @return true if the field should be treated as @Nullable, false otherwise.
*/
boolean onOverrideFieldNullability(Symbol field);
/**
* Called after the analysis determines the nullability of a method's arguments, allowing handlers
* to override.
*
* <p>The passed Map object maps argument positions to nullness information and is sparse, where
* the nullness of missing indexes is determined by base analysis and depends on if the code is
* considered isAnnotated or not. We use a mutable map for performance, but it should not outlive
* the chain of handler invocations.
*
* @param context The current context.
* @param methodSymbol The method symbol for the method in question.
* @param isAnnotated A boolean flag indicating whether the called method is considered to be
* within isAnnotated or unannotated code, used to avoid querying for this information
* multiple times within the same handler chain.
* @param argumentPositionNullness Nullness info for each argument position as computed by
* upstream handlers and/or the base analysis. Some entries may be {@code null}, indicating
* upstream handlers and the base analysis consider the parameter to be nullness-unknown,
* usually since the parameter is from unannotated code.
* @return The updated nullness info for each argument position, as computed by the current
* handler.
*/
@Nullable Nullness[] onOverrideMethodInvocationParametersNullability(
Context context,
Symbol.MethodSymbol methodSymbol,
boolean isAnnotated,
@Nullable Nullness[] argumentPositionNullness);
/**
* Called when the Dataflow analysis generates the initial NullnessStore for a method or lambda.
*
* @param underlyingAST The AST node for the method's (or lambda's) body, using the checkers
* framework UnderlyingAST class.
* @param parameters The formal parameters of the method.
* @param result The state of the initial NullnessStore for the method (or lambda) at the point
* this hook is called, represented as a builder.
* @return The desired state of the initial NullnessStore for the method (or lambda), after this
* hook is called, represented as a builder. Usually, implementors of this hook will either
* take {@code result} and call {@code setInformation(...)} on it to add additional nullness
* facts, or replace it with a new builder altogether.
*/
NullnessStore.Builder onDataflowInitialStore(
UnderlyingAST underlyingAST,
List<LocalVariableNode> parameters,
NullnessStore.Builder result);
/**
* Called when the Dataflow analysis visits each method invocation.
*
* @param node The AST node for the method callsite.
* @param symbol The symbol of the called method
* @param state The current visitor state.
* @param apContext the current access path context information (see {@link
* AccessPath.AccessPathContext}).
* @param inputs NullnessStore information known before the method invocation.
* @param thenUpdates NullnessStore updates to be added along the then path, handlers can add via
* the set() method.
* @param elseUpdates NullnessStore updates to be added along the else path, handlers can add via
* the set() method.
* @param bothUpdates NullnessStore updates to be added along both paths, handlers can add via the
* set() method.
* @return The Nullness information for this method's return computed by this handler. See
* NullnessHint and CompositeHandler for more information about how this values get merged
* into a final Nullness value.
*/
NullnessHint onDataflowVisitMethodInvocation(
MethodInvocationNode node,
Symbol.MethodSymbol symbol,
VisitorState state,
AccessPath.AccessPathContext apContext,
AccessPathNullnessPropagation.SubNodeValues inputs,
AccessPathNullnessPropagation.Updates thenUpdates,
AccessPathNullnessPropagation.Updates elseUpdates,
AccessPathNullnessPropagation.Updates bothUpdates);
/**
* Called when the Dataflow analysis visits each field access.
*
* @param node The AST node for the field access.
* @param symbol The {@link Symbol} object for the above node, provided for convenience.
* @param types {@link Types} for the current compilation
* @param context the javac Context object (or Error Prone SubContext)
* @param apContext the current access path context information (see {@link
* AccessPath.AccessPathContext}).
* @param inputs NullnessStore information known before the method invocation.
* @param updates NullnessStore updates to be added, handlers can add via the set() method.
* @return The Nullness information for this field computed by this handler. See NullnessHint and
* CompositeHandler for more information about how this values get merged into a final
* Nullness value.
*/
NullnessHint onDataflowVisitFieldAccess(
FieldAccessNode node,
Symbol symbol,
Types types,
Context context,
AccessPath.AccessPathContext apContext,
AccessPathNullnessPropagation.SubNodeValues inputs,
AccessPathNullnessPropagation.Updates updates);
/**
* Called when the Dataflow analysis visits a return statement.
*
* @param tree The AST node for the return statement being matched.
* @param state The current visitor state
* @param thenStore The NullnessStore for the true case of the expression inside the return
* statement.
* @param elseStore The NullnessStore for the false case of the expression inside the return
* statement.
*/
void onDataflowVisitReturn(
ReturnTree tree, VisitorState state, NullnessStore thenStore, NullnessStore elseStore);
/**
* Called when the Dataflow analysis visits the result expression inside the body of lambda.
*
* <p>This is only called for lambda expressions with a single expression as their body. For
* lambdas with a block of code as their body, onDataflowVisitReturn will be called instead, one
* or more times.
*
* <p>It is not expected to be called for anything other than boolean expressions, which are the
* only ones for which providing separate then/else stores makes sense. For simply getting the
* final exit store of the lambda, see Dataflow.finalResult or
* AccessPathNullnessAnalysis.forceRunOnMethod.
*
* @param tree The AST node for the expression being matched.
* @param thenStore The NullnessStore for the true case of the expression inside the return
* statement.
* @param elseStore The NullnessStore for the false case of the expression inside the return
* statement.
*/
void onDataflowVisitLambdaResultExpression(
ExpressionTree tree, NullnessStore thenStore, NullnessStore elseStore);
/**
* It should return an error wrapped in Optional if any of the handlers detect an error in
* dereference.
*
* @param expr The AST node for the expression being matched.
* @param baseExpr The AST node for the base of dereference expression being matched.
* @param state The current visitor state.
* @return {@link ErrorMessage} wrapped in {@link Optional} if dereference causes some error,
* otherwise returns empty Optional
*/
Optional<ErrorMessage> onExpressionDereference(
ExpressionTree expr, ExpressionTree baseExpr, VisitorState state);
/**
* Called when determining which access path nullability information should be preserved when
* analyzing a nested method, i.e., a lambda expression or a method in an anonymous or local
* class.
*
* @param path The tree path to the node for the nested method.
* @param state The current visitor state.
* @return A predicate that determines which access paths should be preserved when analyzing the
* nested method.
*/
Predicate<AccessPath> getAccessPathPredicateForNestedMethod(TreePath path, VisitorState state);
/**
* Called during dataflow analysis initialization to register structurally immutable types.
*
* <p>Handlers declare structurally immutable types, requesting that they be treated as constants
* when they appear as arguments of method inside an AccessPath. Whenever a static final field of
* one of these types appears as an argument to a method in an access path (e.g. get(Foo.f) where
* Foo.f is a static final field of an immutable type T returned by this method), it is treated
* the same as a String or primitive type compile-time constant for the purposes of tracking the
* nullability of that access path.
*
* @return A set of fully qualified immutable type names.
*/
ImmutableSet<String> onRegisterImmutableTypes();
/**
* Called when a method writes a {@code @NonNull} value to a class field.
*
* @param field Symbol of the initialized class field.
* @param analysis nullness dataflow analysis
* @param state VisitorState.
*/
void onNonNullFieldAssignment(
Symbol field, AccessPathNullnessAnalysis analysis, VisitorState state);
/**
* Called during AST to CFG translation (CFGTranslationPhaseOne) immediately after translating a
* MethodInvocationTree.
*
* @param phase a reference to the NullAwayCFGTranslationPhaseOne object and its utility
* functions.
* @param tree the MethodInvocationTree being translated.
* @param originalNode the resulting MethodInvocationNode right before this handler is called.
* @return a MethodInvocationNode which might be originalNode or a modified version, this is
* passed to the next handler in the chain.
*/
MethodInvocationNode onCFGBuildPhase1AfterVisitMethodInvocation(
NullAwayCFGBuilder.NullAwayCFGTranslationPhaseOne phase,
MethodInvocationTree tree,
MethodInvocationNode originalNode);
/**
* Called to determine when a method acts as a cast-to-non-null operation on its parameters.
*
* <p>See {@link LibraryModels#castToNonNullMethods()} for more information about general
* configuration of <code>castToNonNull</code> methods.
*
* @param actualParams The actual parameters from the invocation node
* @param previousArgumentPosition The result computed by the previous handler in the chain, if
* any.
* @return The index of the parameter for which the method should act as a cast (if any). This
* value can be set only once through the full chain of handlers, with each handler deciding
* whether to propagate or override the value previousArgumentPosition passed by the previous
* handler in the chain.
* @param methodAnalysisContext The MethodAnalysisContext object
*/
@Nullable Integer castToNonNullArgumentPositionsForMethod(
List<? extends ExpressionTree> actualParams,
@Nullable Integer previousArgumentPosition,
MethodAnalysisContext methodAnalysisContext);
/**
* Method to override the nullability of the upper bound for a generic type variable on a class.
*
* @param className name of the class
* @param index index of the generic type variable (starting at 0)
* @return boolean true if the variable should be treated as having a {@code @Nullable} upper
* bound
*/
boolean onOverrideTypeParameterUpperBound(String className, int index);
/**
* Method to override the null-markedness of a class.
*
* @param className name of the class
* @return boolean true if the class should be treated as {@code @NullMarked}
*/
boolean onOverrideNullMarkedClasses(String className);
/**
* A three value enum for handlers implementing onDataflowVisitMethodInvocation to communicate
* their knowledge of the method return nullability to the rest of NullAway.
*/
public enum NullnessHint {
/**
* No new information about return nullability, defer to the core algorithm and other handlers.
*/
UNKNOWN(0, Nullness.NONNULL),
/**
* The method is nullable in general (e.g. due to a library model or a return type annotation).
* Override core behavior and mark this method as Nullable, unless a handler returns
* FORCE_NONNULL.
*/
HINT_NULLABLE(1, Nullness.NULLABLE),
/**
* Handler asserts this method is guaranteed to be NonNull for the current invocation (e.g. used
* by ContractHandler when all preconditions for a "-> !null" clause are known to hold).
*/
FORCE_NONNULL(2, Nullness.NONNULL);
private final int priority;
private final Nullness nullness;
NullnessHint(int priority, Nullness nullness) {
this.priority = priority;
this.nullness = nullness;
}
public Nullness toNullness() {
return nullness;
}
public NullnessHint merge(NullnessHint other) {
if (other.priority > this.priority) {
return other;
} else {
return this;
}
}
}