Skip to content

Commit

Permalink
Merge branch 'master' into wip-jdk-21-api-stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
msridhar committed Nov 21, 2023
2 parents 72c5733 + 8f4f8a6 commit 89474f7
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 30 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
Changelog
=========
Version 0.10.17
---------------
* Fix bug with computing direct type use annotations on parameters (#864)
* Model Apache Flink's RichFunction.open as an @Initializer method (#862)
* Support for JSpecify's 0.3.0 annotation [experimental]
- JSpecify: adding com.google.common to annotated packages in build.gradle (#857)
- JSpecify: handling the return of a diamond operator anonymous object method caller (#858)
- Create com.uber.nullaway.generics package (#855)
- Clarifications and small fixes for checking JSpecify @Nullable annotation (#859)
- Apply minor cleanups suggested by IntelliJ in generics code (#860)

Version 0.10.16
---------------
NOTE: Maven Central signing key rotated for this release following a revocation.
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ org.gradle.caching=true
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m

GROUP=com.uber.nullaway
VERSION_NAME=0.10.17-SNAPSHOT
VERSION_NAME=0.10.18-SNAPSHOT

POM_DESCRIPTION=A fast annotation-based null checker for Java

Expand Down
2 changes: 1 addition & 1 deletion gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def test = [
"org.junit.jupiter:junit-jupiter-api:5.0.2",
"org.apiguardian:apiguardian-api:1.0.0"
],
jetbrainsAnnotations : "org.jetbrains:annotations:13.0",
jetbrainsAnnotations : "org.jetbrains:annotations:24.1.0",
cfQual : "org.checkerframework:checker-qual:${versions.checkerFramework}",
// 2.5.5 is the last release to contain this artifact
cfCompatQual : "org.checkerframework:checker-compat-qual:2.5.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ final class ErrorProneCLIFlagsConfig extends AbstractConfig {
"androidx.fragment.app.Fragment.onActivityCreated",
"androidx.fragment.app.Fragment.onViewCreated",
// Multidex app
"android.support.multidex.Application.onCreate");
"android.support.multidex.Application.onCreate",
// Apache Flink
// See docs:
// https://nightlies.apache.org/flink/flink-docs-master/api/java/org/apache/flink/api/common/functions/RichFunction.html#open-org.apache.flink.api.common.functions.OpenContext-
"org.apache.flink.api.common.functions.RichFunction.open");

static final ImmutableSet<String> DEFAULT_INITIALIZER_ANNOT =
ImmutableSet.of(
Expand Down
9 changes: 6 additions & 3 deletions nullaway/src/main/java/com/uber/nullaway/NullabilityUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ public static TreePath findEnclosingMethodOrLambdaOrInitializer(TreePath path) {

/**
* NOTE: this method does not work for getting all annotations of parameters of methods from class
* files. For that case, use {@link #getAllAnnotationsForParameter(Symbol.MethodSymbol, int)}
* files. For that case, use {@link #getAllAnnotationsForParameter(Symbol.MethodSymbol, int,
* Config)}
*
* @param symbol the symbol
* @return all annotations on the symbol and on the type of the symbol
Expand Down Expand Up @@ -259,18 +260,20 @@ public static Stream<? extends AnnotationMirror> getAllAnnotations(Symbol symbol
*
* @param symbol the method symbol
* @param paramInd index of the parameter
* @param config NullAway configuration
* @return all declaration and type-use annotations for the parameter
*/
public static Stream<? extends AnnotationMirror> getAllAnnotationsForParameter(
Symbol.MethodSymbol symbol, int paramInd) {
Symbol.MethodSymbol symbol, int paramInd, Config config) {
Symbol.VarSymbol varSymbol = symbol.getParameters().get(paramInd);
return Stream.concat(
varSymbol.getAnnotationMirrors().stream(),
symbol.getRawTypeAttributes().stream()
.filter(
t ->
t.position.type.equals(TargetType.METHOD_FORMAL_PARAMETER)
&& t.position.parameter_index == paramInd));
&& t.position.parameter_index == paramInd
&& NullabilityUtil.isDirectTypeUseAnnotation(t, config)));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions nullaway/src/main/java/com/uber/nullaway/Nullness.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public static boolean paramHasNullableAnnotation(
return true;
}
return hasNullableAnnotation(
NullabilityUtil.getAllAnnotationsForParameter(symbol, paramInd), config);
NullabilityUtil.getAllAnnotationsForParameter(symbol, paramInd, config), config);
}

private static boolean isRecordEqualsParam(Symbol.MethodSymbol symbol, int paramInd) {
Expand Down Expand Up @@ -249,6 +249,6 @@ private static boolean isRecordEqualsParam(Symbol.MethodSymbol symbol, int param
public static boolean paramHasNonNullAnnotation(
Symbol.MethodSymbol symbol, int paramInd, Config config) {
return hasNonNullAnnotation(
NullabilityUtil.getAllAnnotationsForParameter(symbol, paramInd), config);
NullabilityUtil.getAllAnnotationsForParameter(symbol, paramInd, config), config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public Boolean visitClassType(Type.ClassType lhsType, Type rhsType) {
Types types = state.getTypes();
// The base type of rhsType may be a subtype of lhsType's base type. In such cases, we must
// compare lhsType against the supertype of rhsType with a matching base type.
rhsType = (Type.ClassType) types.asSuper(rhsType, lhsType.tsym);
rhsType = types.asSuper(rhsType, lhsType.tsym);
// This is impossible, considering the fact that standard Java subtyping succeeds before
// running NullAway
if (rhsType == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public final class GenericsChecks {

/**
* Supplier for the JSpecify {@code @Nullable} annotation. Required since for now, certain checks
* related to generics specifically look for {@code @org.jspecify.ananotations.Nullable}
* related to generics specifically look for {@code @org.jspecify.annotations.Nullable}
* annotations and do not apply to other {@code @Nullable} annotations.
*/
static final Supplier<Type> JSPECIFY_NULLABLE_TYPE_SUPPLIER =
Expand All @@ -64,7 +64,7 @@ public static void checkInstantiationForParameterizedTypedTree(
return;
}
List<? extends Tree> typeArguments = tree.getTypeArguments();
if (typeArguments.size() == 0) {
if (typeArguments.isEmpty()) {
return;
}
Map<Integer, Tree> nullableTypeArguments = new HashMap<>();
Expand Down Expand Up @@ -302,8 +302,7 @@ public static void checkTypeParameterNullnessForAssignability(
Type rhsType = getTreeType(rhsTree, state);

if (lhsType instanceof Type.ClassType && rhsType instanceof Type.ClassType) {
boolean isAssignmentValid =
compareNullabilityAnnotations((Type.ClassType) lhsType, (Type.ClassType) rhsType, state);
boolean isAssignmentValid = compareNullabilityAnnotations(lhsType, rhsType, state);
if (!isAssignmentValid) {
reportInvalidAssignmentInstantiationError(tree, lhsType, rhsType, state, analysis);
}
Expand Down Expand Up @@ -337,8 +336,7 @@ public static void checkTypeParameterNullnessForFunctionReturnType(
if (formalReturnType instanceof Type.ClassType
&& returnExpressionType instanceof Type.ClassType) {
boolean isReturnTypeValid =
compareNullabilityAnnotations(
(Type.ClassType) formalReturnType, (Type.ClassType) returnExpressionType, state);
compareNullabilityAnnotations(formalReturnType, returnExpressionType, state);
if (!isReturnTypeValid) {
reportInvalidReturnTypeError(
retExpr, formalReturnType, returnExpressionType, state, analysis);
Expand Down Expand Up @@ -411,15 +409,13 @@ public static void checkTypeParameterNullnessForConditionalExpression(
// type of the whole expression
if (condExprType instanceof Type.ClassType) {
if (truePartType instanceof Type.ClassType) {
if (!compareNullabilityAnnotations(
(Type.ClassType) condExprType, (Type.ClassType) truePartType, state)) {
if (!compareNullabilityAnnotations(condExprType, truePartType, state)) {
reportMismatchedTypeForTernaryOperator(
truePartTree, condExprType, truePartType, state, analysis);
}
}
if (falsePartType instanceof Type.ClassType) {
if (!compareNullabilityAnnotations(
(Type.ClassType) condExprType, (Type.ClassType) falsePartType, state)) {
if (!compareNullabilityAnnotations(condExprType, falsePartType, state)) {
reportMismatchedTypeForTernaryOperator(
falsePartTree, condExprType, falsePartType, state, analysis);
}
Expand Down Expand Up @@ -458,8 +454,7 @@ public static void compareGenericTypeParameterNullabilityForCall(
Type actualParameter = getTreeType(actualParams.get(i), state);
if (formalParameter instanceof Type.ClassType
&& actualParameter instanceof Type.ClassType) {
if (!compareNullabilityAnnotations(
(Type.ClassType) formalParameter, (Type.ClassType) actualParameter, state)) {
if (!compareNullabilityAnnotations(formalParameter, actualParameter, state)) {
reportInvalidParametersNullabilityError(
formalParameter, actualParameter, actualParams.get(i), state, analysis);
}
Expand All @@ -470,13 +465,12 @@ public static void compareGenericTypeParameterNullabilityForCall(
Type.ArrayType varargsArrayType =
(Type.ArrayType) formalParams.get(formalParams.size() - 1).type;
Type varargsElementType = varargsArrayType.elemtype;
if (varargsElementType.getTypeArguments().size() > 0) {
if (!varargsElementType.getTypeArguments().isEmpty()) {
for (int i = formalParams.size() - 1; i < actualParams.size(); i++) {
Type actualParameter = getTreeType(actualParams.get(i), state);
if (varargsElementType instanceof Type.ClassType
&& actualParameter instanceof Type.ClassType) {
if (!compareNullabilityAnnotations(
(Type.ClassType) varargsElementType, (Type.ClassType) actualParameter, state)) {
if (!compareNullabilityAnnotations(varargsElementType, actualParameter, state)) {
reportInvalidParametersNullabilityError(
varargsElementType, actualParameter, actualParams.get(i), state, analysis);
}
Expand Down Expand Up @@ -786,9 +780,7 @@ private static void checkTypeParameterNullnessForOverridingMethodParameterType(
if (overriddenMethodParameterType instanceof Type.ClassType
&& overridingMethodParameterType instanceof Type.ClassType) {
if (!compareNullabilityAnnotations(
(Type.ClassType) overriddenMethodParameterType,
(Type.ClassType) overridingMethodParameterType,
state)) {
overriddenMethodParameterType, overridingMethodParameterType, state)) {
reportInvalidOverridingMethodParamTypeError(
methodParameters.get(i),
overriddenMethodParameterType,
Expand Down Expand Up @@ -819,9 +811,7 @@ private static void checkTypeParameterNullnessForOverridingMethodReturnType(
}
Preconditions.checkArgument(overridingMethodReturnType instanceof Type.ClassType);
if (!compareNullabilityAnnotations(
(Type.ClassType) overriddenMethodReturnType,
(Type.ClassType) overridingMethodReturnType,
state)) {
overriddenMethodReturnType, overridingMethodReturnType, state)) {
reportInvalidOverridingMethodReturnTypeError(
tree, overriddenMethodReturnType, overridingMethodReturnType, analysis, state);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,31 @@ public void nullUnmarkedAndAcknowledgeRestrictiveAnnotations() {
.doTest();
}

@Test
public void nullUnmarkedRestrictiveAnnotationsAndGenerics() {
makeTestHelperWithArgs(
Arrays.asList(
"-d",
temporaryFolder.getRoot().getAbsolutePath(),
"-XepOpt:NullAway:AnnotatedPackages=com.uber",
"-XepOpt:NullAway:AcknowledgeRestrictiveAnnotations=true"))
.addSourceLines(
"Test.java",
"package com.uber;",
"import org.jspecify.annotations.NullUnmarked;",
"import org.jetbrains.annotations.Nullable;",
"import org.jetbrains.annotations.NotNull;",
"import java.util.List;",
"public class Test {",
" @NullUnmarked",
" public static void takesNullable(@Nullable List<@NotNull String> l) {}",
" public static void test() {",
" takesNullable(null);",
" }",
"}")
.doTest();
}

@Test
public void nullMarkedStaticImports() {
makeTestHelperWithArgs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,28 @@ public void annotationAppliedToTypeParameter() {
"import java.util.List;",
"import java.util.ArrayList;",
"import org.checkerframework.checker.nullness.qual.Nullable;",
"import org.checkerframework.checker.nullness.qual.NonNull;",
"class TypeArgumentAnnotation {",
" List<@Nullable String> fSafe = new ArrayList<>();",
" @Nullable List<String> fUnsafe = new ArrayList<>();",
" void useParamSafe(List<@Nullable String> list) {",
" list.hashCode();",
" }",
" void unsafeCall() {",
" // BUG: Diagnostic contains: passing @Nullable parameter",
" useParamSafe(null);",
" }",
" void useParamUnsafe(@Nullable List<String> list) {",
" // BUG: Diagnostic contains: dereferenced",
" list.hashCode();",
" }",
" void useParamUnsafeNonNullElements(@Nullable List<@NonNull String> list) {",
" // BUG: Diagnostic contains: dereferenced",
" list.hashCode();",
" }",
" void safeCall() {",
" useParamUnsafeNonNullElements(null);",
" }",
" void useFieldSafe() {",
" fSafe.hashCode();",
" }",
Expand Down

0 comments on commit 89474f7

Please sign in to comment.