Skip to content
Snippets Groups Projects
Commit 600e0c7f authored by Johannes Mey's avatar Johannes Mey
Browse files

temporarily disable the nullable derereference analysis

parent 81d41c23
No related branches found
No related tags found
No related merge requests found
/** ///**
* Copyright 2015 Google Inc. All Rights Reserved. // * Copyright 2015 Google Inc. All Rights Reserved.
* // *
* Licensed under the Apache License, Version 2.0 (the "License"); // * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. // * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at // * You may obtain a copy of the License at
* // *
* http://www.apache.org/licenses/LICENSE-2.0 // * http://www.apache.org/licenses/LICENSE-2.0
* // *
* Unless required by applicable law or agreed to in writing, software // * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, // * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and // * See the License for the specific language governing permissions and
* limitations under the License. // * limitations under the License.
*/ // */
//
/** ///**
* Adds an analysis that checks for dereferences of a parameter declared nullable. // * Adds an analysis that checks for dereferences of a parameter declared nullable.
* // *
* <p>When a method or constructor parameter is annotated with javax.annotation.Nullable, // * <p>When a method or constructor parameter is annotated with javax.annotation.Nullable,
* we check that all dereferences of that parameter are guarded by a null-check. The // * we check that all dereferences of that parameter are guarded by a null-check. The
* analysis is control-flow sensitive in that it will recognize if all control flow paths // * analysis is control-flow sensitive in that it will recognize if all control flow paths
* to the dereference are effectively guarded by a null check, for example: {@code // * to the dereference are effectively guarded by a null check, for example: {@code
* if (p == null) return; // * if (p == null) return;
* p.x(); // Guarded by null check above. // * p.x(); // Guarded by null check above.
* } // * }
* // *
* <p>The analysis is not intraprocedural, so in order to avoid false positives // * <p>The analysis is not intraprocedural, so in order to avoid false positives
* where a method call guards against nullness the analyzer assumes that // * where a method call guards against nullness the analyzer assumes that
* calling a method with an argument x results in an exception if x is null and // * calling a method with an argument x results in an exception if x is null and
* thus works like an effective null guard for x. // * thus works like an effective null guard for x.
* // *
* <p>To find potential null dereferences on nullable parameters, the analysis does a forward CFG // * <p>To find potential null dereferences on nullable parameters, the analysis does a forward CFG
* traversal from the entry-point of the method. Note that this is only done whenever a // * traversal from the entry-point of the method. Note that this is only done whenever a
* {@code @Nullable} parameter has been encountered in the method. The traversal explores all paths // * {@code @Nullable} parameter has been encountered in the method. The traversal explores all paths
* from the method entry until it finds null guard statements such as {@code if (p != null)}. The // * from the method entry until it finds null guard statements such as {@code if (p != null)}. The
* branches that are protected from nullness get pruned in the search and the search continues on // * branches that are protected from nullness get pruned in the search and the search continues on
* other branches. The search is performed by a {@code NullDereferenceLocator}, which implements the // * other branches. The search is performed by a {@code NullDereferenceLocator}, which implements the
* {@code CfgSearch} interface. This visitor is invoked for each node in the CFG search, and it // * {@code CfgSearch} interface. This visitor is invoked for each node in the CFG search, and it
* decides if the search will continue from that node, or if the current edge should be skipped // * decides if the search will continue from that node, or if the current edge should be skipped
* (i.e., pruned). // * (i.e., pruned).
* // *
* <p>In order to find the position in the CFG where a potential null dereference occurs, CFG marker // * <p>In order to find the position in the CFG where a potential null dereference occurs, CFG marker
* nodes are inserted. This is done by adding a synthesized non-terminal attribute (NTA) for // * nodes are inserted. This is done by adding a synthesized non-terminal attribute (NTA) for
* a CfgMarker on Dot (which represents Java dot expressions). This marker node appears // * a CfgMarker on Dot (which represents Java dot expressions). This marker node appears
* in the CFG as "nullable access" because it is inserted whenever a nullable variable is // * in the CFG as "nullable access" because it is inserted whenever a nullable variable is
* dereferenced. // * dereferenced.
* // *
* <p>Dataflow analysis is not used, so in order to analyze a parameter it is required to be // * <p>Dataflow analysis is not used, so in order to analyze a parameter it is required to be
* effectively final, i.e. it is not assigned anywhere in side the body of the method/constructor. // * effectively final, i.e. it is not assigned anywhere in side the body of the method/constructor.
*/ // */
aspect NullableDereferenceAnalysis { //aspect NullableDereferenceAnalysis {
//
// Give ParameterDeclaration access to the inherited compilationUnit attribute. // // Give ParameterDeclaration access to the inherited compilationUnit attribute.
inh CompilationUnit ParameterDeclaration.compilationUnit(); // inh CompilationUnit ParameterDeclaration.compilationUnit();
//
ParameterDeclaration contributes nullableDereferenceFinding() // ParameterDeclaration contributes nullableDereferenceFinding()
when nullableDereferenceFinding() != null // when nullableDereferenceFinding() != null
to CompilationUnit.findings() // to CompilationUnit.findings()
for compilationUnit(); // for compilationUnit();
//
/** // /**
* Generate a NullableDereference finding for this dot expression, // * Generate a NullableDereference finding for this dot expression,
* if no finding should be reported this attribute returns {@code null}. // * if no finding should be reported this attribute returns {@code null}.
*/ // */
syn lazy ExtendJFinding ParameterDeclaration.nullableDereferenceFinding() { // syn lazy ExtendJFinding ParameterDeclaration.nullableDereferenceFinding() {
if (!getModifiers().hasNullableAnnotation()) { // if (!getModifiers().hasNullableAnnotation()) {
return null; // return null;
} // }
if (!isFinal() && !isEffectivelyFinal()) { // if (!isFinal() && !isEffectivelyFinal()) {
// Do not analyze non-effectively final parameters. // // Do not analyze non-effectively final parameters.
return null; // return null;
} // }
Expr location = findNullableDereference(this); // Expr location = findNullableDereference(this);
if (location == null) { // if (location == null) {
return null; // return null;
} // }
ExtendJFinding finding = location.finding("NullableDereference", String.format( // ExtendJFinding finding = location.finding("NullableDereference", String.format(
"Dereferencing %s, which was declared @Nullable.", name())); // "Dereferencing %s, which was declared @Nullable.", name()));
if (compilationUnit().fromSource()) { // if (compilationUnit().fromSource()) {
ASTNode modifierLocation = nullableModifierLocation(); // ASTNode modifierLocation = nullableModifierLocation();
int line = getLine(modifierLocation.getStart()); // int line = getLine(modifierLocation.getStart());
int startCol = getColumn(modifierLocation.getStart()); // int startCol = getColumn(modifierLocation.getStart());
int endCol = getColumn(modifierLocation.getEnd()); // int endCol = getColumn(modifierLocation.getEnd());
if (startCol < endCol && line == getLine(modifierLocation.getEnd())) { // if (startCol < endCol && line == getLine(modifierLocation.getEnd())) {
try { // try {
InputStream data = compilationUnit().getClassSource().openInputStream(); // InputStream data = compilationUnit().getClassSource().openInputStream();
java.util.Scanner scanner = new java.util.Scanner(data); // java.util.Scanner scanner = new java.util.Scanner(data);
for (int i = 1; i < line && scanner.hasNextLine(); ++i) { // for (int i = 1; i < line && scanner.hasNextLine(); ++i) {
scanner.nextLine(); // scanner.nextLine();
} // }
if (scanner.hasNextLine()) { // if (scanner.hasNextLine()) {
String text = scanner.nextLine(); // String text = scanner.nextLine();
finding.addFix("Remove the @Nullable annotation.", // finding.addFix("Remove the @Nullable annotation.",
line, line, // line, line,
text.substring(0,startCol-1) + text.substring(endCol+1) + "\n"); // text.substring(0,startCol-1) + text.substring(endCol+1) + "\n");
} // }
} catch (IOException e) { // } catch (IOException e) {
// Failed to unparse the current line. // // Failed to unparse the current line.
// This is not a serious problem; we just don't give a fix suggestion. // // This is not a serious problem; we just don't give a fix suggestion.
} // }
} // }
} // }
return finding; // return finding;
} // }
//
// Exclude variable arity parameters from Nullable dereference analysis. // // Exclude variable arity parameters from Nullable dereference analysis.
// When a variable arity parameter is annotated @Nullable, that will most likely be intended as a // // When a variable arity parameter is annotated @Nullable, that will most likely be intended as a
// @Nullable annotation for the individual parameters, not the containing argument array. // // @Nullable annotation for the individual parameters, not the containing argument array.
eq VariableArityParameterDeclaration.nullableDereferenceFinding() = null; // eq VariableArityParameterDeclaration.nullableDereferenceFinding() = null;
//
/** // /**
* Find the location node for the javax.annotation.Nullable annotation in the modifier list. // * Find the location node for the javax.annotation.Nullable annotation in the modifier list.
* Returns {@code null} if the location of the modifier was not found. // * Returns {@code null} if the location of the modifier was not found.
*/ // */
syn ASTNode ParameterDeclaration.nullableModifierLocation() = // syn ASTNode ParameterDeclaration.nullableModifierLocation() =
getModifiers().nullableModifierLocation(); // getModifiers().nullableModifierLocation();
//
syn ASTNode Modifiers.nullableModifierLocation() { // syn ASTNode Modifiers.nullableModifierLocation() {
for (Modifier modifier : getModifierList()) { // for (Modifier modifier : getModifierList()) {
if (modifier.isAnnotation("javax.annotation", "Nullable")) { // if (modifier.isAnnotation("javax.annotation", "Nullable")) {
return modifier.locationNode(); // return modifier.locationNode();
} // }
} // }
return null; // return null;
} // }
//
/** // /**
* Find a location, not necessarily the first location, in the host method/constructor where the // * Find a location, not necessarily the first location, in the host method/constructor where the
* parameter is accessed without a null guard. // * parameter is accessed without a null guard.
*/ // */
inh Expr ParameterDeclaration.findNullableDereference(Variable var); // inh Expr ParameterDeclaration.findNullableDereference(Variable var);
//
eq Program.getChild().findNullableDereference(Variable var) = null; // eq Program.getChild().findNullableDereference(Variable var) = null;
eq BodyDecl.getChild().findNullableDereference(Variable var) = null; // eq BodyDecl.getChild().findNullableDereference(Variable var) = null;
//
eq MethodDecl.getParameter().findNullableDereference(Variable var) { // eq MethodDecl.getParameter().findNullableDereference(Variable var) {
if (!hasBlock()) { // if (!hasBlock()) {
return null; // return null;
} // }
CfgNode cfgNode = entry().bfs(new NullDereferenceLocator(var)); // CfgNode cfgNode = entry().bfs(new NullDereferenceLocator(var));
return cfgNode == null ? null : cfgNode.receiverExpr(); // return cfgNode == null ? null : cfgNode.receiverExpr();
} // }
//
eq ConstructorDecl.getParameter().findNullableDereference(Variable var) { // eq ConstructorDecl.getParameter().findNullableDereference(Variable var) {
CfgNode cfgNode = entry().bfs(new NullDereferenceLocator(var)); // CfgNode cfgNode = entry().bfs(new NullDereferenceLocator(var));
return cfgNode == null ? null : cfgNode.receiverExpr(); // return cfgNode == null ? null : cfgNode.receiverExpr();
} // }
//
/** // /**
* A CFG visitor that searches in the forward CFG for a nullable dereference. // * A CFG visitor that searches in the forward CFG for a nullable dereference.
* // *
* <p>The search stops at parts of the search tree guarded by a null check // * <p>The search stops at parts of the search tree guarded by a null check
* on the receiver variable. // * on the receiver variable.
*/ // */
class NullDereferenceLocator implements CfgVisitor { // class NullDereferenceLocator implements CfgVisitor {
private final Variable var; // private final Variable var;
//
public NullDereferenceLocator(Variable var) { // public NullDereferenceLocator(Variable var) {
this.var = var; // this.var = var;
} // }
//
@Override public SearchAction processEdge(CfgNode pred, CfgNode succ) { // @Override public SearchAction processEdge(CfgNode pred, CfgNode succ) {
if (pred.isNullGuard(var, succ)) { // if (pred.isNullGuard(var, succ)) {
return SearchAction.SKIP; // return SearchAction.SKIP;
} // }
Expr receiver = succ.receiverExpr(); // Expr receiver = succ.receiverExpr();
if (receiver != null && receiver.isVariable(var) && !receiver.hasNullGuard(var)) { // if (receiver != null && receiver.isVariable(var) && !receiver.hasNullGuard(var)) {
return SearchAction.SUCCESSOR_MATCH; // return SearchAction.SUCCESSOR_MATCH;
} // }
return SearchAction.CONTINUE; // return SearchAction.CONTINUE;
} // }
} // }
//
/** // /**
* Returns the receiver expression if the CFG node is the child of a dereference expression. // * Returns the receiver expression if the CFG node is the child of a dereference expression.
* Returns {@code null} otherwise. // * Returns {@code null} otherwise.
*/ // */
inh Expr CfgNode.receiverExpr(); // inh Expr CfgNode.receiverExpr();
eq Program.getChild().receiverExpr() = null; // eq Program.getChild().receiverExpr() = null;
eq BodyDecl.getChild().receiverExpr() = null; // eq BodyDecl.getChild().receiverExpr() = null;
eq BodyDecl.exit().receiverExpr() = null; // eq BodyDecl.exit().receiverExpr() = null;
eq TryStmt.tryEntryMarker().receiverExpr() = null; // eq TryStmt.tryEntryMarker().receiverExpr() = null;
eq BreakStmt.marker().receiverExpr() = null; // eq BreakStmt.marker().receiverExpr() = null;
eq ContinueStmt.marker().receiverExpr() = null; // eq ContinueStmt.marker().receiverExpr() = null;
eq ReturnStmt.marker().receiverExpr() = null; // eq ReturnStmt.marker().receiverExpr() = null;
eq MethodAccess.exceptionNode().receiverExpr() = null; // eq MethodAccess.exceptionNode().receiverExpr() = null;
eq MethodAccess.call().receiverExpr() = // eq MethodAccess.call().receiverExpr() =
hasPrevExpr() // hasPrevExpr()
? prevExpr() // ? prevExpr()
: null; // : null;
eq ThrowStmt.exceptionNode().receiverExpr() = null; // eq ThrowStmt.exceptionNode().receiverExpr() = null;
eq TryStmt.exceptionNode().receiverExpr() = null; // eq TryStmt.exceptionNode().receiverExpr() = null;
eq ConditionalExpr.branch().receiverExpr() = null; // eq ConditionalExpr.branch().receiverExpr() = null;
eq ConditionalExpr.thenEndMarker().receiverExpr() = null; // eq ConditionalExpr.thenEndMarker().receiverExpr() = null;
eq ConditionalExpr.elseEndMarker().receiverExpr() = null; // eq ConditionalExpr.elseEndMarker().receiverExpr() = null;
eq IfStmt.branch().receiverExpr() = null; // eq IfStmt.branch().receiverExpr() = null;
eq IfStmt.thenEndMarker().receiverExpr() = null; // eq IfStmt.thenEndMarker().receiverExpr() = null;
eq IfStmt.elseEndMarker().receiverExpr() = null; // eq IfStmt.elseEndMarker().receiverExpr() = null;
eq ForStmt.branch().receiverExpr() = null; // eq ForStmt.branch().receiverExpr() = null;
eq EnhancedForStmt.branch().receiverExpr() = null; // eq EnhancedForStmt.branch().receiverExpr() = null;
eq WhileStmt.branch().receiverExpr() = null; // eq WhileStmt.branch().receiverExpr() = null;
eq DoStmt.branch().receiverExpr() = null; // eq DoStmt.branch().receiverExpr() = null;
eq SwitchStmt.branch().receiverExpr() = null; // eq SwitchStmt.branch().receiverExpr() = null;
eq LambdaBody.exit().receiverExpr() = null; // eq LambdaBody.exit().receiverExpr() = null;
eq Dot.nullableDereferenceMarker().receiverExpr() = getLeft(); // eq Dot.nullableDereferenceMarker().receiverExpr() = getLeft();
//
/** Marker node used to find location of a nullable dereference in the CFG. */ // /** Marker node used to find location of a nullable dereference in the CFG. */
syn nta CfgMarker Dot.nullableDereferenceMarker() = new CfgMarker(); // syn nta CfgMarker Dot.nullableDereferenceMarker() = new CfgMarker();
//
/** Insert nullable dereference marker in the CFG. */ // /** Insert nullable dereference marker in the CFG. */
refine SimpleCFG // refine SimpleCFG
eq Dot.getLeft().follow() = // eq Dot.getLeft().follow() =
getRight().isMethodAccess() // getRight().isMethodAccess()
? refined() // ? refined()
: nullableDereferenceMarker(); // : nullableDereferenceMarker();
//
eq Dot.nullableDereferenceMarker().succ() = Collections.singleton(getRight().entry()); // eq Dot.nullableDereferenceMarker().succ() = Collections.singleton(getRight().entry());
//
syn boolean CfgNode.isNullGuard(Variable var, CfgNode succ) = false; // syn boolean CfgNode.isNullGuard(Variable var, CfgNode succ) = false;
//
/** // /**
* We assume that calling a method with the variable var as an argument // * We assume that calling a method with the variable var as an argument
* results in an exception thrown by the method call if var is null. This is // * results in an exception thrown by the method call if var is null. This is
* not true for many methods, but it should reduce the false positive rate // * not true for many methods, but it should reduce the false positive rate
* for the NullableDereference analyzer. // * for the NullableDereference analyzer.
*/ // */
eq CfgMethodCall.isNullGuard(Variable var, CfgNode succ) { // eq CfgMethodCall.isNullGuard(Variable var, CfgNode succ) {
if (succ instanceof CfgException) { // if (succ instanceof CfgException) {
return false; // return false;
} // }
MethodAccess access = methodAccess(); // MethodAccess access = methodAccess();
for (Expr arg : access.getArgList()) { // for (Expr arg : access.getArgList()) {
if (arg.isVariable(var)) { // if (arg.isVariable(var)) {
return true; // return true;
} // }
} // }
return false; // return false;
} // }
//
/** Check if this branch has a null-guarding condition. */ // /** Check if this branch has a null-guarding condition. */
eq CfgBranch.isNullGuard(Variable var, CfgNode succ) = inNullGuard(var, succ); // eq CfgBranch.isNullGuard(Variable var, CfgNode succ) = inNullGuard(var, succ);
//
inh boolean CfgBranch.inNullGuard(Variable var, CfgNode succ); // inh boolean CfgBranch.inNullGuard(Variable var, CfgNode succ);
//
eq IfStmt.branch().inNullGuard(Variable var, CfgNode succ) = // eq IfStmt.branch().inNullGuard(Variable var, CfgNode succ) =
succ == getThen().entry() // succ == getThen().entry()
? getCondition().isNonNullWhenTrue(var) // ? getCondition().isNonNullWhenTrue(var)
: getCondition().isNonNullWhenFalse(var); // : getCondition().isNonNullWhenFalse(var);
//
eq ConditionalExpr.branch().inNullGuard(Variable var, CfgNode succ) = // eq ConditionalExpr.branch().inNullGuard(Variable var, CfgNode succ) =
succ == getTrueExpr().entry() // succ == getTrueExpr().entry()
? getCondition().isNonNullWhenTrue(var) // ? getCondition().isNonNullWhenTrue(var)
: getCondition().isNonNullWhenFalse(var); // : getCondition().isNonNullWhenFalse(var);
//
eq ForStmt.branch().inNullGuard(Variable var, CfgNode succ) = // eq ForStmt.branch().inNullGuard(Variable var, CfgNode succ) =
succ == getStmt().entry() // succ == getStmt().entry()
? getCondition().isNonNullWhenTrue(var) // ? getCondition().isNonNullWhenTrue(var)
: getCondition().isNonNullWhenFalse(var); // : getCondition().isNonNullWhenFalse(var);
//
eq WhileStmt.branch().inNullGuard(Variable var, CfgNode succ) = // eq WhileStmt.branch().inNullGuard(Variable var, CfgNode succ) =
succ == getStmt().entry() // succ == getStmt().entry()
? getCondition().isNonNullWhenTrue(var) // ? getCondition().isNonNullWhenTrue(var)
: getCondition().isNonNullWhenFalse(var); // : getCondition().isNonNullWhenFalse(var);
//
eq EnhancedForStmt.branch().inNullGuard(Variable var, CfgNode succ) = false; // eq EnhancedForStmt.branch().inNullGuard(Variable var, CfgNode succ) = false;
eq DoStmt.branch().inNullGuard(Variable var, CfgNode succ) = false; // eq DoStmt.branch().inNullGuard(Variable var, CfgNode succ) = false;
eq SwitchStmt.branch().inNullGuard(Variable var, CfgNode succ) = false; // eq SwitchStmt.branch().inNullGuard(Variable var, CfgNode succ) = false;
//
/** Returns {@code true} if this set of modifiers includes {@code javax.annotation.Nullable}. */ // /** Returns {@code true} if this set of modifiers includes {@code javax.annotation.Nullable}. */
syn boolean Modifiers.hasNullableAnnotation() = hasAnnotation("javax.annotation", "Nullable"); // syn boolean Modifiers.hasNullableAnnotation() = hasAnnotation("javax.annotation", "Nullable");
//
/** Return {@code true} if this expression is guarded by a != null check for var. */ // /** Return {@code true} if this expression is guarded by a != null check for var. */
inh boolean Expr.hasNullGuard(Variable var); // inh boolean Expr.hasNullGuard(Variable var);
eq Program.getChild().hasNullGuard(Variable var) = false; // eq Program.getChild().hasNullGuard(Variable var) = false;
eq IfStmt.getThen().hasNullGuard(Variable var) = getCondition().isNonNullWhenTrue(var); // eq IfStmt.getThen().hasNullGuard(Variable var) = getCondition().isNonNullWhenTrue(var);
eq IfStmt.getElse().hasNullGuard(Variable var) = getCondition().isNonNullWhenFalse(var); // eq IfStmt.getElse().hasNullGuard(Variable var) = getCondition().isNonNullWhenFalse(var);
eq WhileStmt.getStmt().hasNullGuard(Variable var) = getCondition().isNonNullWhenTrue(var); // eq WhileStmt.getStmt().hasNullGuard(Variable var) = getCondition().isNonNullWhenTrue(var);
eq ForStmt.getStmt().hasNullGuard(Variable var) = getCondition().isNonNullWhenTrue(var); // eq ForStmt.getStmt().hasNullGuard(Variable var) = getCondition().isNonNullWhenTrue(var);
eq ConditionalExpr.getTrueExpr().hasNullGuard(Variable var) = // eq ConditionalExpr.getTrueExpr().hasNullGuard(Variable var) =
getCondition().isNonNullWhenTrue(var) || hasNullGuard(var); // getCondition().isNonNullWhenTrue(var) || hasNullGuard(var);
eq ConditionalExpr.getFalseExpr().hasNullGuard(Variable var) = // eq ConditionalExpr.getFalseExpr().hasNullGuard(Variable var) =
getCondition().isNonNullWhenFalse(var) || hasNullGuard(var); // getCondition().isNonNullWhenFalse(var) || hasNullGuard(var);
eq AndLogicalExpr.getRightOperand().hasNullGuard(Variable var) = // eq AndLogicalExpr.getRightOperand().hasNullGuard(Variable var) =
getLeftOperand().isNonNullWhenTrue(var) || hasNullGuard(var); // getLeftOperand().isNonNullWhenTrue(var) || hasNullGuard(var);
eq AndBitwiseExpr.getRightOperand().hasNullGuard(Variable var) = // eq AndBitwiseExpr.getRightOperand().hasNullGuard(Variable var) =
getLeftOperand().isNonNullWhenTrue(var) || hasNullGuard(var); // getLeftOperand().isNonNullWhenTrue(var) || hasNullGuard(var);
eq OrLogicalExpr.getRightOperand().hasNullGuard(Variable var) = // eq OrLogicalExpr.getRightOperand().hasNullGuard(Variable var) =
getLeftOperand().isNonNullWhenFalse(var) || hasNullGuard(var); // getLeftOperand().isNonNullWhenFalse(var) || hasNullGuard(var);
//
/** @return {@code true} if the variable var is null when this expression is true. */ // /** @return {@code true} if the variable var is null when this expression is true. */
syn boolean Expr.isNullWhenTrue(Variable var) = false; // syn boolean Expr.isNullWhenTrue(Variable var) = false;
//
eq NEExpr.isNullWhenTrue(Variable var) = // eq NEExpr.isNullWhenTrue(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var) // getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var) // || getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var)
|| getLeftOperand().isFalse() && getRightOperand().isNullWhenTrue(var) // || getLeftOperand().isFalse() && getRightOperand().isNullWhenTrue(var)
|| getRightOperand().isFalse() && getLeftOperand().isNullWhenTrue(var); // || getRightOperand().isFalse() && getLeftOperand().isNullWhenTrue(var);
//
eq EQExpr.isNullWhenTrue(Variable var) = // eq EQExpr.isNullWhenTrue(Variable var) =
getLeftOperand().isNull() && getRightOperand().varDecl() == var // getLeftOperand().isNull() && getRightOperand().varDecl() == var
|| getRightOperand().isNull() && getLeftOperand().varDecl() == var // || getRightOperand().isNull() && getLeftOperand().varDecl() == var
|| getLeftOperand().isTrue() && getRightOperand().isNullWhenTrue(var) // || getLeftOperand().isTrue() && getRightOperand().isNullWhenTrue(var)
|| getRightOperand().isTrue() && getLeftOperand().isNullWhenTrue(var) // || getRightOperand().isTrue() && getLeftOperand().isNullWhenTrue(var)
|| getLeftOperand().isFalse() && getRightOperand().isNullWhenFalse(var) // || getLeftOperand().isFalse() && getRightOperand().isNullWhenFalse(var)
|| getRightOperand().isFalse() && getLeftOperand().isNullWhenFalse(var); // || getRightOperand().isFalse() && getLeftOperand().isNullWhenFalse(var);
//
eq LogNotExpr.isNullWhenTrue(Variable var) = getOperand().isNullWhenFalse(var); // eq LogNotExpr.isNullWhenTrue(Variable var) = getOperand().isNullWhenFalse(var);
//
eq ParExpr.isNullWhenTrue(Variable var) = getExpr().isNullWhenTrue(var); // eq ParExpr.isNullWhenTrue(Variable var) = getExpr().isNullWhenTrue(var);
//
eq AndLogicalExpr.isNullWhenTrue(Variable var) = // eq AndLogicalExpr.isNullWhenTrue(Variable var) =
getLeftOperand().isNullWhenTrue(var) || getRightOperand().isNullWhenTrue(var); // getLeftOperand().isNullWhenTrue(var) || getRightOperand().isNullWhenTrue(var);
//
eq AndBitwiseExpr.isNullWhenTrue(Variable var) = // eq AndBitwiseExpr.isNullWhenTrue(Variable var) =
getLeftOperand().isNullWhenTrue(var) || getRightOperand().isNullWhenTrue(var); // getLeftOperand().isNullWhenTrue(var) || getRightOperand().isNullWhenTrue(var);
//
eq OrLogicalExpr.isNullWhenTrue(Variable var) = // eq OrLogicalExpr.isNullWhenTrue(Variable var) =
getLeftOperand().isFalse() && getRightOperand().isNullWhenTrue(var) // getLeftOperand().isFalse() && getRightOperand().isNullWhenTrue(var)
|| getRightOperand().isFalse() && getLeftOperand().isNullWhenTrue(var); // || getRightOperand().isFalse() && getLeftOperand().isNullWhenTrue(var);
//
eq Dot.isNullWhenTrue(Variable var) = // eq Dot.isNullWhenTrue(Variable var) =
!getLeft().isVariable(var) && getRight().isNullWhenTrue(var); // !getLeft().isVariable(var) && getRight().isNullWhenTrue(var);
//
// Assume that a method call to X.isNull_(var) is equivalent to a null test on var. // // Assume that a method call to X.isNull_(var) is equivalent to a null test on var.
eq MethodAccess.isNullWhenTrue(Variable var) = // eq MethodAccess.isNullWhenTrue(Variable var) =
name().startsWith("isNull") && getNumArg() == 1 && getArg(0).isVariable(var); // name().startsWith("isNull") && getNumArg() == 1 && getArg(0).isVariable(var);
//
eq VarAccess.isNullWhenTrue(Variable var) = decl().isNullWhenTrue(var); // eq VarAccess.isNullWhenTrue(Variable var) = decl().isNullWhenTrue(var);
//
syn boolean Variable.isNullWhenTrue(Variable var); // syn boolean Variable.isNullWhenTrue(Variable var);
eq EnumConstant.isNullWhenTrue(Variable var) = false; // eq EnumConstant.isNullWhenTrue(Variable var) = false;
eq ParameterDeclaration.isNullWhenTrue(Variable var) = false; // eq ParameterDeclaration.isNullWhenTrue(Variable var) = false;
eq FieldDeclarator.isNullWhenTrue(Variable var) = false; // eq FieldDeclarator.isNullWhenTrue(Variable var) = false;
eq CatchParameterDeclaration.isNullWhenTrue(Variable var) = false; // eq CatchParameterDeclaration.isNullWhenTrue(Variable var) = false;
eq InferredParameterDeclaration.isNullWhenTrue(Variable var) = false; // eq InferredParameterDeclaration.isNullWhenTrue(Variable var) = false;
eq VariableDeclarator.isNullWhenTrue(Variable var) = // eq VariableDeclarator.isNullWhenTrue(Variable var) =
type().isBoolean() && hasInit() && isEffectivelyFinal() // type().isBoolean() && hasInit() && isEffectivelyFinal()
? getInit().isNullWhenTrue(var) // ? getInit().isNullWhenTrue(var)
: false; // : false;
//
/** @return {@code true} if the variable var is null when this expression is false. */ // /** @return {@code true} if the variable var is null when this expression is false. */
syn boolean Expr.isNullWhenFalse(Variable var) = false; // syn boolean Expr.isNullWhenFalse(Variable var) = false;
//
eq NEExpr.isNullWhenFalse(Variable var) = // eq NEExpr.isNullWhenFalse(Variable var) =
getLeftOperand().isNull() && getRightOperand().varDecl() == var // getLeftOperand().isNull() && getRightOperand().varDecl() == var
|| getRightOperand().isNull() && getLeftOperand().varDecl() == var // || getRightOperand().isNull() && getLeftOperand().varDecl() == var
|| getLeftOperand().isTrue() && getRightOperand().isNullWhenTrue(var) // || getLeftOperand().isTrue() && getRightOperand().isNullWhenTrue(var)
|| getRightOperand().isTrue() && getLeftOperand().isNullWhenTrue(var) // || getRightOperand().isTrue() && getLeftOperand().isNullWhenTrue(var)
|| getLeftOperand().isFalse() && getRightOperand().isNullWhenFalse(var) // || getLeftOperand().isFalse() && getRightOperand().isNullWhenFalse(var)
|| getRightOperand().isFalse() && getLeftOperand().isNullWhenFalse(var); // || getRightOperand().isFalse() && getLeftOperand().isNullWhenFalse(var);
//
eq EQExpr.isNullWhenFalse(Variable var) = // eq EQExpr.isNullWhenFalse(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var) // getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var) // || getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var)
|| getLeftOperand().isFalse() && getRightOperand().isNullWhenTrue(var) // || getLeftOperand().isFalse() && getRightOperand().isNullWhenTrue(var)
|| getRightOperand().isFalse() && getLeftOperand().isNullWhenTrue(var); // || getRightOperand().isFalse() && getLeftOperand().isNullWhenTrue(var);
//
eq LogNotExpr.isNullWhenFalse(Variable var) = getOperand().isNullWhenTrue(var); // eq LogNotExpr.isNullWhenFalse(Variable var) = getOperand().isNullWhenTrue(var);
//
eq ParExpr.isNullWhenFalse(Variable var) = getExpr().isNullWhenFalse(var); // eq ParExpr.isNullWhenFalse(Variable var) = getExpr().isNullWhenFalse(var);
//
eq AndLogicalExpr.isNullWhenFalse(Variable var) = // eq AndLogicalExpr.isNullWhenFalse(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var) // getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var); // || getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var);
//
eq AndBitwiseExpr.isNullWhenFalse(Variable var) = // eq AndBitwiseExpr.isNullWhenFalse(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var) // getLeftOperand().isTrue() && getRightOperand().isNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var); // || getRightOperand().isTrue() && getLeftOperand().isNullWhenFalse(var);
//
eq OrLogicalExpr.isNullWhenFalse(Variable var) = // eq OrLogicalExpr.isNullWhenFalse(Variable var) =
getLeftOperand().isNullWhenFalse(var) && getRightOperand().isNullWhenFalse(var); // getLeftOperand().isNullWhenFalse(var) && getRightOperand().isNullWhenFalse(var);
//
eq Dot.isNullWhenFalse(Variable var) = // eq Dot.isNullWhenFalse(Variable var) =
!getLeft().isVariable(var) && getRight().isNullWhenFalse(var); // !getLeft().isVariable(var) && getRight().isNullWhenFalse(var);
//
// Assume that a method call to X.isNo{t,n}Null_(var) is equivalent to a non-null test on var. // // Assume that a method call to X.isNo{t,n}Null_(var) is equivalent to a non-null test on var.
eq MethodAccess.isNullWhenFalse(Variable var) = // eq MethodAccess.isNullWhenFalse(Variable var) =
(name().startsWith("isNotNull") || name().startsWith("isNonNull")) // (name().startsWith("isNotNull") || name().startsWith("isNonNull"))
&& getNumArg() == 1 && getArg(0).isVariable(var); // && getNumArg() == 1 && getArg(0).isVariable(var);
//
eq VarAccess.isNullWhenFalse(Variable var) = decl().isNullWhenFalse(var); // eq VarAccess.isNullWhenFalse(Variable var) = decl().isNullWhenFalse(var);
//
syn boolean Variable.isNullWhenFalse(Variable var); // syn boolean Variable.isNullWhenFalse(Variable var);
eq EnumConstant.isNullWhenFalse(Variable var) = false; // eq EnumConstant.isNullWhenFalse(Variable var) = false;
eq ParameterDeclaration.isNullWhenFalse(Variable var) = false; // eq ParameterDeclaration.isNullWhenFalse(Variable var) = false;
eq FieldDeclarator.isNullWhenFalse(Variable var) = false; // eq FieldDeclarator.isNullWhenFalse(Variable var) = false;
eq CatchParameterDeclaration.isNullWhenFalse(Variable var) = false; // eq CatchParameterDeclaration.isNullWhenFalse(Variable var) = false;
eq InferredParameterDeclaration.isNullWhenFalse(Variable var) = false; // eq InferredParameterDeclaration.isNullWhenFalse(Variable var) = false;
eq VariableDeclarator.isNullWhenFalse(Variable var) = // eq VariableDeclarator.isNullWhenFalse(Variable var) =
type().isBoolean() && hasInit() && isEffectivelyFinal() // type().isBoolean() && hasInit() && isEffectivelyFinal()
? getInit().isNullWhenFalse(var) // ? getInit().isNullWhenFalse(var)
: false; // : false;
//
/** @return {@code true} if the variable var is non-null when this expression is true. */ // /** @return {@code true} if the variable var is non-null when this expression is true. */
syn boolean Expr.isNonNullWhenTrue(Variable var) = false; // syn boolean Expr.isNonNullWhenTrue(Variable var) = false;
//
eq NEExpr.isNonNullWhenTrue(Variable var) = // eq NEExpr.isNonNullWhenTrue(Variable var) =
getLeftOperand().isNull() && getRightOperand().varDecl() == var // getLeftOperand().isNull() && getRightOperand().varDecl() == var
|| getRightOperand().isNull() && getLeftOperand().varDecl() == var // || getRightOperand().isNull() && getLeftOperand().varDecl() == var
|| getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var) // || getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var) // || getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var)
|| getLeftOperand().isFalse() && getRightOperand().isNonNullWhenTrue(var) // || getLeftOperand().isFalse() && getRightOperand().isNonNullWhenTrue(var)
|| getRightOperand().isFalse() && getLeftOperand().isNonNullWhenTrue(var); // || getRightOperand().isFalse() && getLeftOperand().isNonNullWhenTrue(var);
//
eq EQExpr.isNonNullWhenTrue(Variable var) = // eq EQExpr.isNonNullWhenTrue(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNonNullWhenTrue(var) // getLeftOperand().isTrue() && getRightOperand().isNonNullWhenTrue(var)
|| getRightOperand().isTrue() && getLeftOperand().isNonNullWhenTrue(var) // || getRightOperand().isTrue() && getLeftOperand().isNonNullWhenTrue(var)
|| getLeftOperand().isFalse() && getRightOperand().isNonNullWhenFalse(var) // || getLeftOperand().isFalse() && getRightOperand().isNonNullWhenFalse(var)
|| getRightOperand().isFalse() && getLeftOperand().isNonNullWhenFalse(var); // || getRightOperand().isFalse() && getLeftOperand().isNonNullWhenFalse(var);
//
eq LogNotExpr.isNonNullWhenTrue(Variable var) = getOperand().isNullWhenTrue(var); // eq LogNotExpr.isNonNullWhenTrue(Variable var) = getOperand().isNullWhenTrue(var);
//
eq ParExpr.isNonNullWhenTrue(Variable var) = getExpr().isNonNullWhenTrue(var); // eq ParExpr.isNonNullWhenTrue(Variable var) = getExpr().isNonNullWhenTrue(var);
//
eq AndLogicalExpr.isNonNullWhenTrue(Variable var) = // eq AndLogicalExpr.isNonNullWhenTrue(Variable var) =
getLeftOperand().isNonNullWhenTrue(var) || getRightOperand().isNonNullWhenTrue(var); // getLeftOperand().isNonNullWhenTrue(var) || getRightOperand().isNonNullWhenTrue(var);
//
eq AndBitwiseExpr.isNonNullWhenTrue(Variable var) = // eq AndBitwiseExpr.isNonNullWhenTrue(Variable var) =
getLeftOperand().isNonNullWhenTrue(var) || getRightOperand().isNonNullWhenTrue(var); // getLeftOperand().isNonNullWhenTrue(var) || getRightOperand().isNonNullWhenTrue(var);
//
eq OrLogicalExpr.isNonNullWhenTrue(Variable var) = // eq OrLogicalExpr.isNonNullWhenTrue(Variable var) =
getLeftOperand().isFalse() && getRightOperand().isNonNullWhenTrue(var) // getLeftOperand().isFalse() && getRightOperand().isNonNullWhenTrue(var)
|| getRightOperand().isFalse() && getLeftOperand().isNonNullWhenTrue(var); // || getRightOperand().isFalse() && getLeftOperand().isNonNullWhenTrue(var);
//
eq Dot.isNonNullWhenTrue(Variable var) = // eq Dot.isNonNullWhenTrue(Variable var) =
!getLeft().isVariable(var) && getRight().isNonNullWhenTrue(var); // !getLeft().isVariable(var) && getRight().isNonNullWhenTrue(var);
//
// Assume that a method call to X.isNo{t,n}Null_(var) is equivalent to a non-null test on var. // // Assume that a method call to X.isNo{t,n}Null_(var) is equivalent to a non-null test on var.
eq MethodAccess.isNonNullWhenTrue(Variable var) = // eq MethodAccess.isNonNullWhenTrue(Variable var) =
(name().startsWith("isNotNull") || name().startsWith("isNonNull")) // (name().startsWith("isNotNull") || name().startsWith("isNonNull"))
&& getNumArg() == 1 && getArg(0).isVariable(var); // && getNumArg() == 1 && getArg(0).isVariable(var);
//
eq VarAccess.isNonNullWhenTrue(Variable var) = decl().isNonNullWhenTrue(var); // eq VarAccess.isNonNullWhenTrue(Variable var) = decl().isNonNullWhenTrue(var);
//
syn boolean Variable.isNonNullWhenTrue(Variable var); // syn boolean Variable.isNonNullWhenTrue(Variable var);
eq EnumConstant.isNonNullWhenTrue(Variable var) = false; // eq EnumConstant.isNonNullWhenTrue(Variable var) = false;
eq ParameterDeclaration.isNonNullWhenTrue(Variable var) = false; // eq ParameterDeclaration.isNonNullWhenTrue(Variable var) = false;
eq FieldDeclarator.isNonNullWhenTrue(Variable var) = false; // eq FieldDeclarator.isNonNullWhenTrue(Variable var) = false;
eq CatchParameterDeclaration.isNonNullWhenTrue(Variable var) = false; // eq CatchParameterDeclaration.isNonNullWhenTrue(Variable var) = false;
eq InferredParameterDeclaration.isNonNullWhenTrue(Variable var) = false; // eq InferredParameterDeclaration.isNonNullWhenTrue(Variable var) = false;
eq VariableDeclarator.isNonNullWhenTrue(Variable var) = // eq VariableDeclarator.isNonNullWhenTrue(Variable var) =
type().isBoolean() && hasInit() && isEffectivelyFinal() // type().isBoolean() && hasInit() && isEffectivelyFinal()
? getInit().isNonNullWhenTrue(var) // ? getInit().isNonNullWhenTrue(var)
: false; // : false;
//
// An instanceof check guards against the variable being null. // // An instanceof check guards against the variable being null.
eq InstanceOfExpr.isNonNullWhenTrue(Variable var) = getExpr().isVariable(var); // eq InstanceOfExpr.isNonNullWhenTrue(Variable var) = getExpr().isVariable(var);
//
/** @return {@code true} if the variable var is non-null when this expression is false. */ // /** @return {@code true} if the variable var is non-null when this expression is false. */
syn boolean Expr.isNonNullWhenFalse(Variable var) = false; // syn boolean Expr.isNonNullWhenFalse(Variable var) = false;
//
eq NEExpr.isNonNullWhenFalse(Variable var) = // eq NEExpr.isNonNullWhenFalse(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNonNullWhenTrue(var) // getLeftOperand().isTrue() && getRightOperand().isNonNullWhenTrue(var)
|| getRightOperand().isTrue() && getLeftOperand().isNonNullWhenTrue(var) // || getRightOperand().isTrue() && getLeftOperand().isNonNullWhenTrue(var)
|| getLeftOperand().isFalse() && getRightOperand().isNonNullWhenFalse(var) // || getLeftOperand().isFalse() && getRightOperand().isNonNullWhenFalse(var)
|| getRightOperand().isFalse() && getLeftOperand().isNonNullWhenFalse(var); // || getRightOperand().isFalse() && getLeftOperand().isNonNullWhenFalse(var);
//
eq EQExpr.isNonNullWhenFalse(Variable var) = // eq EQExpr.isNonNullWhenFalse(Variable var) =
getLeftOperand().isNull() && getRightOperand().varDecl() == var // getLeftOperand().isNull() && getRightOperand().varDecl() == var
|| getRightOperand().isNull() && getLeftOperand().varDecl() == var // || getRightOperand().isNull() && getLeftOperand().varDecl() == var
|| getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var) // || getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var) // || getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var)
|| getLeftOperand().isFalse() && getRightOperand().isNonNullWhenTrue(var) // || getLeftOperand().isFalse() && getRightOperand().isNonNullWhenTrue(var)
|| getRightOperand().isFalse() && getLeftOperand().isNonNullWhenTrue(var); // || getRightOperand().isFalse() && getLeftOperand().isNonNullWhenTrue(var);
//
eq LogNotExpr.isNonNullWhenFalse(Variable var) = getOperand().isNonNullWhenTrue(var); // eq LogNotExpr.isNonNullWhenFalse(Variable var) = getOperand().isNonNullWhenTrue(var);
//
eq ParExpr.isNonNullWhenFalse(Variable var) = getExpr().isNonNullWhenFalse(var); // eq ParExpr.isNonNullWhenFalse(Variable var) = getExpr().isNonNullWhenFalse(var);
//
eq AndLogicalExpr.isNonNullWhenFalse(Variable var) = // eq AndLogicalExpr.isNonNullWhenFalse(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var) // getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var); // || getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var);
//
eq AndBitwiseExpr.isNonNullWhenFalse(Variable var) = // eq AndBitwiseExpr.isNonNullWhenFalse(Variable var) =
getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var) // getLeftOperand().isTrue() && getRightOperand().isNonNullWhenFalse(var)
|| getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var); // || getRightOperand().isTrue() && getLeftOperand().isNonNullWhenFalse(var);
//
eq OrLogicalExpr.isNonNullWhenFalse(Variable var) = // eq OrLogicalExpr.isNonNullWhenFalse(Variable var) =
getLeftOperand().isNonNullWhenFalse(var) || getRightOperand().isNonNullWhenFalse(var); // getLeftOperand().isNonNullWhenFalse(var) || getRightOperand().isNonNullWhenFalse(var);
//
eq Dot.isNonNullWhenFalse(Variable var) = // eq Dot.isNonNullWhenFalse(Variable var) =
!getLeft().isVariable(var) && getRight().isNonNullWhenFalse(var); // !getLeft().isVariable(var) && getRight().isNonNullWhenFalse(var);
//
// Assume that a method call to X.isNull_(var) is equivalent to a null test on var. // // Assume that a method call to X.isNull_(var) is equivalent to a null test on var.
eq MethodAccess.isNonNullWhenFalse(Variable var) = // eq MethodAccess.isNonNullWhenFalse(Variable var) =
name().startsWith("isNull") && getNumArg() == 1 && getArg(0).isVariable(var); // name().startsWith("isNull") && getNumArg() == 1 && getArg(0).isVariable(var);
//
eq VarAccess.isNonNullWhenFalse(Variable var) = decl().isNonNullWhenFalse(var); // eq VarAccess.isNonNullWhenFalse(Variable var) = decl().isNonNullWhenFalse(var);
//
syn boolean Variable.isNonNullWhenFalse(Variable var); // syn boolean Variable.isNonNullWhenFalse(Variable var);
eq EnumConstant.isNonNullWhenFalse(Variable var) = false; // eq EnumConstant.isNonNullWhenFalse(Variable var) = false;
eq ParameterDeclaration.isNonNullWhenFalse(Variable var) = false; // eq ParameterDeclaration.isNonNullWhenFalse(Variable var) = false;
eq FieldDeclarator.isNonNullWhenFalse(Variable var) = false; // eq FieldDeclarator.isNonNullWhenFalse(Variable var) = false;
eq CatchParameterDeclaration.isNonNullWhenFalse(Variable var) = false; // eq CatchParameterDeclaration.isNonNullWhenFalse(Variable var) = false;
eq InferredParameterDeclaration.isNonNullWhenFalse(Variable var) = false; // eq InferredParameterDeclaration.isNonNullWhenFalse(Variable var) = false;
eq VariableDeclarator.isNonNullWhenFalse(Variable var) = // eq VariableDeclarator.isNonNullWhenFalse(Variable var) =
type().isBoolean() && hasInit() && isEffectivelyFinal() // type().isBoolean() && hasInit() && isEffectivelyFinal()
? getInit().isNonNullWhenFalse(var) // ? getInit().isNonNullWhenFalse(var)
: false; // : false;
//
syn boolean Expr.isNull() = type().isNull(); // syn boolean Expr.isNull() = type().isNull();
eq NullLiteral.isNull() = true; // eq NullLiteral.isNull() = true;
} //}
...@@ -137,7 +137,7 @@ aspect PrintCfg { ...@@ -137,7 +137,7 @@ aspect PrintCfg {
eq ReturnStmt.marker().markerName() = "return"; eq ReturnStmt.marker().markerName() = "return";
eq TryStmt.tryEntryMarker().markerName() = "try"; eq TryStmt.tryEntryMarker().markerName() = "try";
eq Program.getChild().markerName() = "marker"; eq Program.getChild().markerName() = "marker";
eq Dot.nullableDereferenceMarker().markerName() = "nullable access"; // eq Dot.nullableDereferenceMarker().markerName() = "nullable access";
eq ForStmt.loopEndMarker().markerName() = "for-end"; eq ForStmt.loopEndMarker().markerName() = "for-end";
eq EnhancedForStmt.loopEndMarker().markerName() = "for-end"; eq EnhancedForStmt.loopEndMarker().markerName() = "for-end";
eq WhileStmt.loopEndMarker().markerName() = "while-end"; eq WhileStmt.loopEndMarker().markerName() = "while-end";
......
...@@ -171,7 +171,7 @@ aspect PrintCfgTest { ...@@ -171,7 +171,7 @@ aspect PrintCfgTest {
eq ReturnStmt.marker().markerVarName() = "returnMarker"; eq ReturnStmt.marker().markerVarName() = "returnMarker";
eq TryStmt.tryEntryMarker().markerVarName() = "tryEntry"; eq TryStmt.tryEntryMarker().markerVarName() = "tryEntry";
eq Program.getChild().markerVarName() = "marker"; eq Program.getChild().markerVarName() = "marker";
eq Dot.nullableDereferenceMarker().markerVarName() = "nullable"; // eq Dot.nullableDereferenceMarker().markerVarName() = "nullable";
eq ForStmt.loopEndMarker().markerVarName() = "forEnd"; eq ForStmt.loopEndMarker().markerVarName() = "forEnd";
eq EnhancedForStmt.loopEndMarker().markerVarName() = "forEnd"; eq EnhancedForStmt.loopEndMarker().markerVarName() = "forEnd";
eq WhileStmt.loopEndMarker().markerVarName() = "whileEnd"; eq WhileStmt.loopEndMarker().markerVarName() = "whileEnd";
......
...@@ -36,110 +36,114 @@ import java.util.Collection; ...@@ -36,110 +36,114 @@ import java.util.Collection;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class NullableDereferenceTest { public class NullableDereferenceTest {
@Test public void suggestedFixEndsWithNewline() { @Test public void test() {
CompilationUnit unit = StmtCfgTest.parseFile("NullableNullGuard01", // this is a dummy test to appease intellij
Program.ANALYZER_TYPE_FILTER); }
Collection<ExtendJFinding> findings = unit.findings();
assertThat(findings).isNotEmpty(); // @Test public void suggestedFixEndsWithNewline() {
ExtendJFinding finding = findings.iterator().next(); // CompilationUnit unit = StmtCfgTest.parseFile("NullableNullGuard01",
assertThat(finding.fixes).hasSize(1); // Program.ANALYZER_TYPE_FILTER);
assertThat(finding.fixes.iterator().next().newText).endsWith("\n"); // Collection<ExtendJFinding> findings = unit.findings();
} // assertThat(findings).isNotEmpty();
// ExtendJFinding finding = findings.iterator().next();
@Test public void nullGuards01() { // assertThat(finding.fixes).hasSize(1);
Collection<String> findings = StmtCfgTest.findings("NullableNullGuard01"); // assertThat(finding.fixes.iterator().next().newText).endsWith("\n");
assertThat(findings).containsExactly( // }
"../simplecfg/testdata/NullableNullGuard01.javax:42:25: Dereferencing p, which was declared @Nullable.", //
"../simplecfg/testdata/NullableNullGuard01.javax:49:12: Dereferencing p, which was declared @Nullable.", // @Test public void nullGuards01() {
"../simplecfg/testdata/NullableNullGuard01.javax:62:12: Dereferencing p, which was declared @Nullable.", // Collection<String> findings = StmtCfgTest.findings("NullableNullGuard01");
"../simplecfg/testdata/NullableNullGuard01.javax:93:12: Dereferencing q, which was declared @Nullable." // assertThat(findings).containsExactly(
); // "../simplecfg/testdata/NullableNullGuard01.javax:42:25: Dereferencing p, which was declared @Nullable.",
} // "../simplecfg/testdata/NullableNullGuard01.javax:49:12: Dereferencing p, which was declared @Nullable.",
// "../simplecfg/testdata/NullableNullGuard01.javax:62:12: Dereferencing p, which was declared @Nullable.",
@Test public void nullGuards02() { // "../simplecfg/testdata/NullableNullGuard01.javax:93:12: Dereferencing q, which was declared @Nullable."
Collection<String> findings = StmtCfgTest.findings("NullableNullGuard02"); // );
assertThat(findings).containsExactly( // }
"../simplecfg/testdata/NullableNullGuard02.javax:49:7: Dereferencing p, which was declared @Nullable.", //
"../simplecfg/testdata/NullableNullGuard02.javax:54:7: Dereferencing p, which was declared @Nullable." // @Test public void nullGuards02() {
); // Collection<String> findings = StmtCfgTest.findings("NullableNullGuard02");
} // assertThat(findings).containsExactly(
// "../simplecfg/testdata/NullableNullGuard02.javax:49:7: Dereferencing p, which was declared @Nullable.",
@Test public void nullGuards03() { // "../simplecfg/testdata/NullableNullGuard02.javax:54:7: Dereferencing p, which was declared @Nullable."
Collection<Integer> lines = StmtCfgTest.findingLines("NullableNullGuard03", // );
Program.ANALYZER_TYPE_FILTER); // }
assertThat(lines).containsExactly(28, 34, 41, 48, 113, 119); //
} // @Test public void nullGuards03() {
// Collection<Integer> lines = StmtCfgTest.findingLines("NullableNullGuard03",
@Test public void methodNullGuard01() { // Program.ANALYZER_TYPE_FILTER);
Collection<String> findings = StmtCfgTest.findings("NullableMethodNullGuard01"); // assertThat(lines).containsExactly(28, 34, 41, 48, 113, 119);
assertThat(findings).isEmpty(); // }
} //
// @Test public void methodNullGuard01() {
@Test public void dataflow01() { // Collection<String> findings = StmtCfgTest.findings("NullableMethodNullGuard01");
Collection<String> findings = StmtCfgTest.findings("NullableDataflow01"); // assertThat(findings).isEmpty();
assertThat(findings).containsExactly( // }
"../simplecfg/testdata/NullableDataflow01.javax:27:7: Dereferencing p, which was declared @Nullable.", //
"../simplecfg/testdata/NullableDataflow01.javax:35:7: Dereferencing p, which was declared @Nullable." // @Test public void dataflow01() {
); // Collection<String> findings = StmtCfgTest.findings("NullableDataflow01");
} // assertThat(findings).containsExactly(
// "../simplecfg/testdata/NullableDataflow01.javax:27:7: Dereferencing p, which was declared @Nullable.",
@Test public void instanceOf() { // "../simplecfg/testdata/NullableDataflow01.javax:35:7: Dereferencing p, which was declared @Nullable."
Collection<String> findings = StmtCfgTest.findings("NullableInstanceOf"); // );
assertThat(findings).isEmpty(); // }
} //
// @Test public void instanceOf() {
@Test public void variableArity() { // Collection<String> findings = StmtCfgTest.findings("NullableInstanceOf");
Collection<String> findings = StmtCfgTest.findings("NullableVariableArity"); // assertThat(findings).isEmpty();
assertThat(findings).isEmpty(); // }
} //
// @Test public void variableArity() {
@Test public void nullableDereference01() { // Collection<String> findings = StmtCfgTest.findings("NullableVariableArity");
Collection<String> findings = StmtCfgTest.findings("NullableDereference01"); // assertThat(findings).isEmpty();
assertThat(findings).containsExactly( // }
"../simplecfg/testdata/NullableDereference01.javax:27:12: Dereferencing p, which was declared @Nullable.", //
"../simplecfg/testdata/NullableDereference01.javax:31:12: Dereferencing p, which was declared @Nullable." // @Test public void nullableDereference01() {
); // Collection<String> findings = StmtCfgTest.findings("NullableDereference01");
} // assertThat(findings).containsExactly(
// "../simplecfg/testdata/NullableDereference01.javax:27:12: Dereferencing p, which was declared @Nullable.",
/** Test false positive for GitHub issue #10. */ // "../simplecfg/testdata/NullableDereference01.javax:31:12: Dereferencing p, which was declared @Nullable."
@Test public void issue10() { // );
Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue10"); // }
assertThat(findings).containsExactly( //
"../simplecfg/testdata/NullableDereferenceIssue10.javax:34:31: Dereferencing y, which was declared @Nullable." // /** Test false positive for GitHub issue #10. */
); // @Test public void issue10() {
} // Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue10");
// assertThat(findings).containsExactly(
@Test public void issue11() { // "../simplecfg/testdata/NullableDereferenceIssue10.javax:34:31: Dereferencing y, which was declared @Nullable."
Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue11"); // );
assertThat(findings).isEmpty(); // }
} //
// @Test public void issue11() {
@Test public void issue12() { // Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue11");
Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue12"); // assertThat(findings).isEmpty();
assertThat(findings).isEmpty(); // }
} //
// @Test public void issue12() {
@Test public void eqExpr() { // Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue12");
Collection<String> findings = StmtCfgTest.findings("NullableDereferenceEqExpr"); // assertThat(findings).isEmpty();
assertThat(findings).isEmpty(); // }
} //
// @Test public void eqExpr() {
@Test public void neExpr() { // Collection<String> findings = StmtCfgTest.findings("NullableDereferenceEqExpr");
Collection<String> findings = StmtCfgTest.findings("NullableDereferenceNeExpr"); // assertThat(findings).isEmpty();
assertThat(findings).isEmpty(); // }
} //
// @Test public void neExpr() {
@Test public void methodCall() { // Collection<String> findings = StmtCfgTest.findings("NullableDereferenceNeExpr");
Collection<String> findings = StmtCfgTest.findings("NullableDereferenceMethodCall"); // assertThat(findings).isEmpty();
assertThat(findings).containsExactly( // }
"../simplecfg/testdata/NullableDereferenceMethodCall.javax:41:16: " //
+ "Dereferencing p, which was declared @Nullable."); // @Test public void methodCall() {
} // Collection<String> findings = StmtCfgTest.findings("NullableDereferenceMethodCall");
// assertThat(findings).containsExactly(
@Test public void issue13() { // "../simplecfg/testdata/NullableDereferenceMethodCall.javax:41:16: "
Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue13"); // + "Dereferencing p, which was declared @Nullable.");
assertThat(findings).containsExactly( // }
"../simplecfg/testdata/NullableDereferenceIssue13.javax:33:7: " //
+ "Dereferencing obj, which was declared @Nullable."); // @Test public void issue13() {
} // Collection<String> findings = StmtCfgTest.findings("NullableDereferenceIssue13");
// assertThat(findings).containsExactly(
// "../simplecfg/testdata/NullableDereferenceIssue13.javax:33:7: "
// + "Dereferencing obj, which was declared @Nullable.");
// }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment