aboutsummaryrefslogtreecommitdiff
path: root/nullaway/src/main/java/com/uber/nullaway/NullAway.java
diff options
context:
space:
mode:
Diffstat (limited to 'nullaway/src/main/java/com/uber/nullaway/NullAway.java')
-rw-r--r--nullaway/src/main/java/com/uber/nullaway/NullAway.java58
1 files changed, 41 insertions, 17 deletions
diff --git a/nullaway/src/main/java/com/uber/nullaway/NullAway.java b/nullaway/src/main/java/com/uber/nullaway/NullAway.java
index 744bddd..a23438a 100644
--- a/nullaway/src/main/java/com/uber/nullaway/NullAway.java
+++ b/nullaway/src/main/java/com/uber/nullaway/NullAway.java
@@ -28,6 +28,7 @@ import static com.sun.source.tree.Tree.Kind.IDENTIFIER;
import static com.sun.source.tree.Tree.Kind.OTHER;
import static com.sun.source.tree.Tree.Kind.PARENTHESIZED;
import static com.sun.source.tree.Tree.Kind.TYPE_CAST;
+import static com.uber.nullaway.ASTHelpersBackports.hasDirectAnnotationWithSimpleName;
import static com.uber.nullaway.ASTHelpersBackports.isStatic;
import static com.uber.nullaway.ErrorBuilder.errMsgForInitializer;
import static com.uber.nullaway.NullabilityUtil.castToNonNull;
@@ -35,6 +36,7 @@ import static com.uber.nullaway.NullabilityUtil.castToNonNull;
import com.google.auto.service.AutoService;
import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
+import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
@@ -398,16 +400,31 @@ public class NullAway extends BugChecker
if (!withinAnnotatedCode(state)) {
return Description.NO_MATCH;
}
- final Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol(tree);
- if (methodSymbol == null) {
- throw new RuntimeException("not expecting unresolved method here");
- }
+ Symbol.MethodSymbol methodSymbol = getSymbolForMethodInvocation(tree, state);
handler.onMatchMethodInvocation(this, tree, state, methodSymbol);
// assuming this list does not include the receiver
List<? extends ExpressionTree> actualParams = tree.getArguments();
return handleInvocation(tree, state, methodSymbol, actualParams);
}
+ private static Symbol.MethodSymbol getSymbolForMethodInvocation(
+ MethodInvocationTree tree, VisitorState state) {
+ Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol(tree);
+ Verify.verify(methodSymbol != null, "not expecting unresolved method here");
+ // For interface methods, if the method is an implicit method corresponding to a method from
+ // java.lang.Object, use the symbol for the java.lang.Object method instead. We do this to
+ // properly treat the method as unannotated, which is particularly important for equals()
+ // methods. This is an adaptation to a change in JDK 18; see
+ // https://bugs.openjdk.org/browse/JDK-8272564
+ if (methodSymbol.owner.isInterface()) {
+ Symbol.MethodSymbol baseSymbol = (Symbol.MethodSymbol) methodSymbol.baseSymbol();
+ if (baseSymbol != methodSymbol && baseSymbol.owner == state.getSymtab().objectType.tsym) {
+ methodSymbol = baseSymbol;
+ }
+ }
+ return methodSymbol;
+ }
+
@Override
public Description matchNewClass(NewClassTree tree, VisitorState state) {
if (!withinAnnotatedCode(state)) {
@@ -476,7 +493,7 @@ public class NullAway extends BugChecker
doUnboxingCheck(state, tree.getExpression());
}
// generics check
- if (lhsType != null && lhsType.getTypeArguments().length() > 0) {
+ if (lhsType != null && lhsType.getTypeArguments().length() > 0 && config.isJSpecifyMode()) {
GenericsChecks.checkTypeParameterNullnessForAssignability(tree, this, state);
}
@@ -486,7 +503,8 @@ public class NullAway extends BugChecker
return Description.NO_MATCH;
}
- if (Nullness.hasNullableAnnotation(assigned, config)) {
+ if (Nullness.hasNullableAnnotation(assigned, config)
+ || handler.onOverrideFieldNullability(assigned)) {
// field already annotated
return Description.NO_MATCH;
}
@@ -577,20 +595,20 @@ public class NullAway extends BugChecker
Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol(tree);
switch (nullMarkingForTopLevelClass) {
case FULLY_MARKED:
- if (ASTHelpers.hasDirectAnnotationWithSimpleName(
+ if (hasDirectAnnotationWithSimpleName(
methodSymbol, NullabilityUtil.NULLUNMARKED_SIMPLE_NAME)) {
nullMarkingForTopLevelClass = NullMarking.PARTIALLY_MARKED;
}
break;
case FULLY_UNMARKED:
- if (ASTHelpers.hasDirectAnnotationWithSimpleName(
+ if (hasDirectAnnotationWithSimpleName(
methodSymbol, NullabilityUtil.NULLMARKED_SIMPLE_NAME)) {
nullMarkingForTopLevelClass = NullMarking.PARTIALLY_MARKED;
markedMethodInUnmarkedContext = true;
}
break;
case PARTIALLY_MARKED:
- if (ASTHelpers.hasDirectAnnotationWithSimpleName(
+ if (hasDirectAnnotationWithSimpleName(
methodSymbol, NullabilityUtil.NULLMARKED_SIMPLE_NAME)) {
// We still care here if this is a transition between @NullUnmarked and @NullMarked code,
// within partially marked code, see checks below for markedMethodInUnmarkedContext.
@@ -694,7 +712,9 @@ public class NullAway extends BugChecker
if (!withinAnnotatedCode(state)) {
return Description.NO_MATCH;
}
- GenericsChecks.checkInstantiationForParameterizedTypedTree(tree, state, this, config);
+ if (config.isJSpecifyMode()) {
+ GenericsChecks.checkInstantiationForParameterizedTypedTree(tree, state, this, config);
+ }
return Description.NO_MATCH;
}
@@ -1423,7 +1443,7 @@ public class NullAway extends BugChecker
return Description.NO_MATCH;
}
VarSymbol symbol = ASTHelpers.getSymbol(tree);
- if (tree.getInitializer() != null) {
+ if (tree.getInitializer() != null && config.isJSpecifyMode()) {
GenericsChecks.checkTypeParameterNullnessForAssignability(tree, this, state);
}
@@ -1464,10 +1484,10 @@ public class NullAway extends BugChecker
*/
private boolean classAnnotationIntroducesPartialMarking(Symbol.ClassSymbol classSymbol) {
return (nullMarkingForTopLevelClass == NullMarking.FULLY_UNMARKED
- && ASTHelpers.hasDirectAnnotationWithSimpleName(
+ && hasDirectAnnotationWithSimpleName(
classSymbol, NullabilityUtil.NULLMARKED_SIMPLE_NAME))
|| (nullMarkingForTopLevelClass == NullMarking.FULLY_MARKED
- && ASTHelpers.hasDirectAnnotationWithSimpleName(
+ && hasDirectAnnotationWithSimpleName(
classSymbol, NullabilityUtil.NULLUNMARKED_SIMPLE_NAME));
}
@@ -1576,7 +1596,9 @@ public class NullAway extends BugChecker
public Description matchConditionalExpression(
ConditionalExpressionTree tree, VisitorState state) {
if (withinAnnotatedCode(state)) {
- GenericsChecks.checkTypeParameterNullnessForConditionalExpression(tree, this, state);
+ if (config.isJSpecifyMode()) {
+ GenericsChecks.checkTypeParameterNullnessForConditionalExpression(tree, this, state);
+ }
doUnboxingCheck(state, tree.getCondition());
}
return Description.NO_MATCH;
@@ -1707,8 +1729,10 @@ public class NullAway extends BugChecker
: Nullness.NONNULL);
}
}
- GenericsChecks.compareGenericTypeParameterNullabilityForCall(
- formalParams, actualParams, methodSymbol.isVarArgs(), this, state);
+ if (config.isJSpecifyMode()) {
+ GenericsChecks.compareGenericTypeParameterNullabilityForCall(
+ formalParams, actualParams, methodSymbol.isVarArgs(), this, state);
+ }
}
// Allow handlers to override the list of non-null argument positions
@@ -2233,7 +2257,7 @@ public class NullAway extends BugChecker
}
private boolean isInitializerMethod(VisitorState state, Symbol.MethodSymbol symbol) {
- if (ASTHelpers.hasDirectAnnotationWithSimpleName(symbol, "Initializer")
+ if (hasDirectAnnotationWithSimpleName(symbol, "Initializer")
|| config.isKnownInitializerMethod(symbol)) {
return true;
}