Do not annotate bare type parameters as @Nullable

This is to account for the case of, say

     class Function<R> { fun invoke(): R }

it would be a shame to put @Nullable on the return type of the function, and force all callers to check for null,
so we put no annotations
This commit is contained in:
Andrey Breslav
2014-02-05 11:17:40 +01:00
parent e0ca1abe4b
commit 9229062926
4 changed files with 37 additions and 1 deletions
@@ -25,7 +25,6 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationArgumentVisitor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.evaluate.EvaluatePackage;
import org.jetbrains.jet.lang.psi.JetAnnotationEntry;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetModifierList;
@@ -36,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.constants.StringValue;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.lang.annotation.Retention;
@@ -123,6 +123,14 @@ public abstract class AnnotationCodegen {
private void generateNullabilityAnnotation(@Nullable JetType type, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
if (type == null) return;
if (isBareTypeParameterWithNullableUpperBound(type)) {
// This is to account for the case of, say
// class Function<R> { fun invoke(): R }
// it would be a shame to put @Nullable on the return type of the function, and force all callers to check for null,
// so we put no annotations
return;
}
boolean isNullableType = CodegenUtil.isNullableType(type);
if (!isNullableType && KotlinBuiltIns.getInstance().isPrimitiveType(type)) return;
@@ -134,6 +142,11 @@ public abstract class AnnotationCodegen {
}
}
private static boolean isBareTypeParameterWithNullableUpperBound(@NotNull JetType type) {
ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor();
return !type.isNullable() && classifier instanceof TypeParameterDescriptor && TypeUtils.hasNullableSuperType(type);
}
private static boolean isVolatile(@NotNull AnnotationDescriptor annotationDescriptor) {
ClassifierDescriptor classDescriptor = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor();
return KotlinBuiltIns.getInstance().getVolatileAnnotationClass().equals(classDescriptor);
@@ -0,0 +1,12 @@
public interface Generic <N, NN> extends jet.JetObject {
N a(@jet.runtime.typeinfo.JetValueParameter(name = "n") N n);
@org.jetbrains.annotations.NotNull
NN b(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "nn") NN nn);
@org.jetbrains.annotations.Nullable
N a1(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "n", type = "?") N n);
@org.jetbrains.annotations.Nullable
NN b1(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nn", type = "?") NN nn);
}
@@ -0,0 +1,7 @@
trait Generic<N, NN: Any> {
fun a(n: N): N
fun b(nn: NN): NN
fun a1(n: N?): N?
fun b1(nn: NN?): NN?
}
@@ -86,6 +86,10 @@ public class NullabilityAnnotationsTest extends KotlinAsJavaTestBase {
doTest(getTestName(false));
}
public void testGeneric() throws Exception {
doTest(getTestName(false));
}
private void doTest(@NotNull String fqName) {
PsiClass psiClass = finder.findClass(fqName, GlobalSearchScope.allScope(getProject()));
if (!(psiClass instanceof KotlinLightClass)) {