Do not generate @NotNull annotations on void- or primitive-returning methods

#KT-4834 Fixed
  #KT-5255 Fixed
This commit is contained in:
Andrey Breslav
2014-06-21 15:08:43 +04:00
parent b6aff9e9ee
commit 38d4ca5469
27 changed files with 136 additions and 48 deletions
@@ -85,7 +85,10 @@ public abstract class AnnotationCodegen {
bindingContext = typeMapper.getBindingContext();
}
public void genAnnotations(Annotated annotated) {
/**
* @param returnType can be null if not applicable (e.g. {@code annotated} is a class)
*/
public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) {
if (annotated == null) {
return;
}
@@ -111,7 +114,7 @@ public abstract class AnnotationCodegen {
}
if (modifierList == null) {
generateAdditionalAnnotations(annotated, Collections.<String>emptySet());
generateAdditionalAnnotations(annotated, returnType, Collections.<String>emptySet());
return;
}
@@ -131,10 +134,14 @@ public abstract class AnnotationCodegen {
}
}
generateAdditionalAnnotations(annotated, annotationDescriptorsAlreadyPresent);
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent);
}
private void generateAdditionalAnnotations(@NotNull Annotated annotated, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
private void generateAdditionalAnnotations(
@NotNull Annotated annotated,
@Nullable Type returnType,
@NotNull Set<String> annotationDescriptorsAlreadyPresent
) {
if (annotated instanceof CallableDescriptor) {
CallableDescriptor descriptor = (CallableDescriptor) annotated;
@@ -142,7 +149,9 @@ public abstract class AnnotationCodegen {
if (isInvisibleFromTheOutside(descriptor)) return;
if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return;
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
if (returnType != null && !AsmUtil.isPrimitive(returnType)) {
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
}
}
}
@@ -166,7 +175,6 @@ public abstract class AnnotationCodegen {
}
boolean isNullableType = JvmCodegenUtil.isNullableType(type);
if (!isNullableType && KotlinBuiltIns.getInstance().isPrimitiveType(type)) return;
Class<?> annotationClass = isNullableType ? Nullable.class : NotNull.class;
@@ -143,7 +143,7 @@ public class FunctionCodegen extends ParentCodegenAware {
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
}
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor);
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType());
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
@@ -180,7 +180,8 @@ public class FunctionCodegen extends ParentCodegenAware {
List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
for (int i = 0; i < kotlinParameterTypes.size(); i++) {
JvmMethodParameterKind kind = kotlinParameterTypes.get(i).getKind();
JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
JvmMethodParameterKind kind = parameterSignature.getKind();
if (kind.isSkippedInGenericSignature()) {
markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
continue;
@@ -189,7 +190,7 @@ public class FunctionCodegen extends ParentCodegenAware {
if (kind == JvmMethodParameterKind.VALUE) {
ValueParameterDescriptor parameter = iterator.next();
v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter);
AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType());
}
}
}
@@ -54,7 +54,6 @@ import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmClassSignature;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -67,10 +66,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
@@ -78,6 +74,9 @@ import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class ImplementationBodyCodegen extends ClassBodyCodegen {
@@ -208,7 +207,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
writeInnerClasses();
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
}
@Override
@@ -1083,11 +1082,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (PropertyAndDefaultValue info : classObjectPropertiesToCopy) {
PropertyDescriptor property = info.descriptor;
Type type = typeMapper.mapType(property);
FieldVisitor fv = v.newField(OtherOrigin(property), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(property, false),
typeMapper.mapType(property).getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
type.getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
info.defaultValue);
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property);
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type);
//This field are always static and final so if it has constant initializer don't do anything in clinit,
//field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
@@ -145,18 +145,15 @@ public class PropertyCodegen {
return false;
}
FieldVisitor fv;
if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
fv = generateBackingFieldAccess(p, descriptor);
generateBackingFieldAccess(p, descriptor);
}
else if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) {
fv = generatePropertyDelegateAccess((JetProperty) p, descriptor);
generatePropertyDelegateAccess((JetProperty) p, descriptor);
}
else {
return false;
}
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor);
return true;
}
@@ -172,7 +169,7 @@ public class PropertyCodegen {
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null);
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor);
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor, Type.VOID_TYPE);
mv.visitCode();
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
@@ -187,7 +184,7 @@ public class PropertyCodegen {
}
}
private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
private void generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) {
@@ -230,21 +227,22 @@ public class PropertyCodegen {
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name));
return builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
typeMapper.mapFieldSignature(jetType), defaultValue);
FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
typeMapper.mapFieldSignature(jetType), defaultValue);
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(propertyDescriptor, type);
}
private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression());
if (delegateType == null) {
// If delegate expression is unresolved reference
delegateType = ErrorUtils.createErrorType("Delegate type");
}
return generateBackingField(p, propertyDescriptor, true, delegateType, null);
generateBackingField(p, propertyDescriptor, true, delegateType, null);
}
private FieldVisitor generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
private void generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
Object value = null;
if (shouldWriteFieldInitializer(propertyDescriptor)) {
@@ -254,7 +252,7 @@ public class PropertyCodegen {
}
}
return generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
}
private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) {
@@ -1,5 +1,4 @@
public final class Derived implements kotlin.jvm.internal.KObject, Base {
@org.jetbrains.annotations.NotNull
public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -1,5 +1,4 @@
public final class Derived implements kotlin.jvm.internal.KObject, Base {
@org.jetbrains.annotations.NotNull
public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -34,7 +34,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.Nullable
public final java.lang.String getNullableVar() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>", type = "?") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -43,7 +42,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
public final java.lang.String getNotNullVar() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@@ -55,7 +53,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
public final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@org.jetbrains.annotations.NotNull
public final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -69,6 +66,5 @@ public final class Class implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
public final void setNullableVarWithGetSet(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "v", type = "?") java.lang.String v) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public Class() { /* compiled code */ }
}
@@ -4,7 +4,6 @@ public final class ClassObjectField implements kotlin.jvm.internal.KObject {
private static final java.lang.String y = "";
public static final ClassObjectField.object object$;
@org.jetbrains.annotations.NotNull
public ClassObjectField() { /* compiled code */ }
public static final class object implements kotlin.jvm.internal.KObject {
@@ -1,4 +1,3 @@
public final class ClassWithConstructor implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
public ClassWithConstructor(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ }
}
@@ -10,6 +10,5 @@ public final class ClassWithConstructorAndProperties implements kotlin.jvm.inter
@org.jetbrains.annotations.NotNull
public final java.lang.String getNotNull() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public ClassWithConstructorAndProperties(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ }
}
@@ -0,0 +1,11 @@
public final class C implements kotlin.jvm.internal.KObject, Tr {
private final int v = 1;
@org.jetbrains.annotations.NotNull
public java.lang.Integer foo() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public java.lang.Integer getV() { /* compiled code */ }
public C() { /* compiled code */ }
}
@@ -0,0 +1,12 @@
// C
trait Tr {
fun foo(): Any
val v: Any
}
class C: Tr {
override fun foo() = 1
override val v = 1
}
@@ -0,0 +1,4 @@
public final class _DefaultPackage {
@org.jetbrains.annotations.Nullable
public static final kotlin.Unit foo() { /* compiled code */ }
}
@@ -0,0 +1,3 @@
// _DefaultPackage
fun foo(): Unit? = null
@@ -0,0 +1,5 @@
public final class C implements kotlin.jvm.internal.KObject, Base {
public void foo() { /* compiled code */ }
public C() { /* compiled code */ }
}
@@ -0,0 +1,9 @@
// C
trait Base {
fun foo(): Any
}
class C : Base {
override fun foo(): Unit {}
}
@@ -1,14 +1,11 @@
public final class Synthetic implements kotlin.jvm.internal.KObject {
private final void foo() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public Synthetic() { /* compiled code */ }
public final class Inner implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
public final void test() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public Inner() { /* compiled code */ }
}
}
@@ -25,7 +25,6 @@ public interface Trait extends kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.Nullable
java.lang.String getNullableVar();
@org.jetbrains.annotations.NotNull
void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>", type = "?") java.lang.String p);
@org.jetbrains.annotations.NotNull
@@ -34,6 +33,5 @@ public interface Trait extends kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
java.lang.String getNotNullVar();
@org.jetbrains.annotations.NotNull
void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>") java.lang.String p);
}
@@ -0,0 +1,5 @@
public final class C implements kotlin.jvm.internal.KObject, Base<kotlin.Unit> {
public void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "t") kotlin.Unit t) { /* compiled code */ }
public C() { /* compiled code */ }
}
@@ -0,0 +1,9 @@
// C
trait Base<T> {
fun foo(t: T): T
}
class C : Base<Unit> {
override fun foo(t: Unit) {}
}
@@ -0,0 +1,3 @@
public final class _DefaultPackage {
public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") kotlin.Unit s) { /* compiled code */ }
}
@@ -0,0 +1,3 @@
// _DefaultPackage
fun foo(s: Unit) {}
@@ -0,0 +1,3 @@
public final class _DefaultPackage {
public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") java.lang.String s) { /* compiled code */ }
}
@@ -0,0 +1,3 @@
// _DefaultPackage
fun foo(s: String) {}
@@ -9,7 +9,6 @@ public final class _DefaultPackage {
@org.jetbrains.annotations.NotNull
public static final java.lang.String getNotNullVar() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public static final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@@ -17,7 +16,6 @@ public final class _DefaultPackage {
public static final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@org.jetbrains.annotations.NotNull
public static final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@@ -30,7 +28,6 @@ public final class _DefaultPackage {
@org.jetbrains.annotations.Nullable
public static final java.lang.String getNullableVar() { /* compiled code */ }
@org.jetbrains.annotations.NotNull
public static final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>", type = "?") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -86,6 +86,21 @@ public class KotlinLightClassTestGenerated extends AbstractKotlinLightClassTest
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Generic.kt");
}
@TestMetadata("IntOverridesAny.kt")
public void testIntOverridesAny() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt");
}
@TestMetadata("NullableUnitReturn.kt")
public void testNullableUnitReturn() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt");
}
@TestMetadata("OverrideAnyWithUnit.kt")
public void testOverrideAnyWithUnit() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt");
}
@TestMetadata("Primitives.kt")
public void testPrimitives() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt");
@@ -116,6 +131,21 @@ public class KotlinLightClassTestGenerated extends AbstractKotlinLightClassTest
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/TraitClassObjectField.kt");
}
@TestMetadata("UnitAsGenericArgument.kt")
public void testUnitAsGenericArgument() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt");
}
@TestMetadata("UnitParameter.kt")
public void testUnitParameter() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt");
}
@TestMetadata("VoidReturn.kt")
public void testVoidReturn() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt");
}
@TestMetadata("_DefaultPackage.kt")
public void test_DefaultPackage() throws Exception {
doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.kt");
@@ -1,11 +1,9 @@
package foo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class JavaClass {
@NotNull
@Override
public void bar(@Nullable String price) {