From 5db6bb04e331f6d9db30124c27c103bbcfff5d9c Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 3 Feb 2015 15:08:37 +0300 Subject: [PATCH] Basic Java nullability warnings implemented #KT-6723 In Progress --- .../load/kotlin/KotlinJvmCheckerProvider.kt | 40 ++++++- .../diagnostics/DefaultErrorMessagesJvm.java | 4 + .../resolve/jvm/diagnostics/ErrorsJvm.java | 23 ++++ .../resolve/AdditionalCheckerProvider.kt | 7 +- .../jdk-annotations/sql/DriverManager.kt | 10 +- .../tests/jdk-annotations/sql/Statement.kt | 4 +- .../nullabilityWarnings/arithmetic.kt | 58 +++++++++ .../nullabilityWarnings/arithmetic.txt | 3 + .../nullabilityWarnings/array.kt | 34 ++++++ .../nullabilityWarnings/array.txt | 3 + .../nullabilityWarnings/assignToVar.kt | 29 +++++ .../nullabilityWarnings/assignToVar.txt | 5 + .../nullabilityWarnings/conditions.kt | 50 ++++++++ .../nullabilityWarnings/conditions.txt | 3 + .../nullabilityWarnings/dataFlowInfo.kt | 34 ++++++ .../nullabilityWarnings/dataFlowInfo.txt | 4 + .../nullabilityWarnings/defaultParameters.kt | 30 +++++ .../nullabilityWarnings/defaultParameters.txt | 3 + .../delegatedProperties.kt | 26 ++++ .../delegatedProperties.txt | 5 + .../nullabilityWarnings/delegation.kt | 21 ++++ .../nullabilityWarnings/delegation.txt | 55 +++++++++ .../nullabilityWarnings/derefenceExtension.kt | 36 ++++++ .../derefenceExtension.txt | 5 + .../nullabilityWarnings/derefenceMember.kt | 31 +++++ .../nullabilityWarnings/derefenceMember.txt | 3 + .../nullabilityWarnings/expectedType.kt | 33 +++++ .../nullabilityWarnings/expectedType.txt | 3 + .../platformTypes/nullabilityWarnings/for.kt | 31 +++++ .../platformTypes/nullabilityWarnings/for.txt | 3 + .../nullabilityWarnings/functionArguments.kt | 30 +++++ .../nullabilityWarnings/functionArguments.txt | 5 + .../nullabilityWarnings/invoke.kt | 27 +++++ .../nullabilityWarnings/invoke.txt | 3 + .../nullabilityWarnings/multiDeclaration.kt | 36 ++++++ .../nullabilityWarnings/multiDeclaration.txt | 3 + .../nullabilityWarnings/passToJava.kt | 92 ++++++++++++++ .../nullabilityWarnings/passToJava.txt | 3 + .../nullabilityWarnings/throw.kt | 28 +++++ .../nullabilityWarnings/throw.txt | 5 + .../checkers/JetDiagnosticsTestGenerated.java | 113 +++++++++++++++++- .../java/lazy/types/LazyJavaTypeResolver.kt | 3 +- .../js/resolve/KotlinJsCheckerProvider.kt | 3 +- spec-docs/flexible-java-types.md | 21 +++- 44 files changed, 953 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.txt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt index 7d61eecc811..d080c4899ca 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmCheckerProvider.kt @@ -42,10 +42,21 @@ import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeFunChecker import org.jetbrains.kotlin.psi.JetPropertyAccessor import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.resolve.jvm.calls.checkers.NeedSyntheticChecker +import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker +import org.jetbrains.kotlin.psi.JetExpression +import org.jetbrains.kotlin.types.JetType +import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.load.java.lazy.types.isMarkedNullable +import org.jetbrains.kotlin.load.java.lazy.types.isMarkedNotNull +import org.jetbrains.kotlin.types.isFlexible +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.NullabilityInformationSource public object KotlinJvmCheckerProvider : AdditionalCheckerProvider( annotationCheckers = listOf(PlatformStaticAnnotationChecker(), LocalFunInlineChecker(), ReifiedTypeParameterAnnotationChecker(), NativeFunChecker()), - additionalCallCheckers = listOf(NeedSyntheticChecker()) + additionalCallCheckers = listOf(NeedSyntheticChecker()), + additionalTypeCheckers = listOf(JavaNullabilityWarningsChecker()) ) public class LocalFunInlineChecker : AnnotationChecker { @@ -127,3 +138,30 @@ private fun checkTypeParameterDescriptorsAreNotReified( ) } } + +public class JavaNullabilityWarningsChecker : AdditionalTypeChecker { + private fun JetType.mayBeNull(): NullabilityInformationSource? { + if (!isFlexible() && TypeUtils.isNullableType(this)) return NullabilityInformationSource.KOTLIN + if (getAnnotations().isMarkedNullable()) return NullabilityInformationSource.JAVA + return null + } + + private fun JetType.mustNotBeNull(): NullabilityInformationSource? { + if (!isFlexible() && !TypeUtils.isNullableType(this)) return NullabilityInformationSource.KOTLIN + if (getAnnotations().isMarkedNotNull()) return NullabilityInformationSource.JAVA + return null + } + + override fun checkType(expression: JetExpression, expressionType: JetType, c: ResolutionContext<*>) { + if (TypeUtils.noExpectedType(c.expectedType)) return + + val expectedMustNotBeNull = c.expectedType.mustNotBeNull() + val actualNullabilityInKotlin = c.dataFlowInfo.getNullability(DataFlowValueFactory.createDataFlowValue(expression, expressionType, c.trace.getBindingContext())) + val actualMayBeNull = if (!actualNullabilityInKotlin.canBeNull()) null else expressionType.mayBeNull() + + if (expectedMustNotBeNull != null && actualMayBeNull != null) { + c.trace.report(ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.on(expression, expectedMustNotBeNull, actualMayBeNull)) + } + } + +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index 97a09d54a03..8f91ea1ca30 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages; import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap; +import org.jetbrains.kotlin.diagnostics.rendering.Renderers; import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.renderer.Renderer; @@ -51,6 +52,9 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { MAP.put(ErrorsJvm.NATIVE_DECLARATION_CANNOT_HAVE_BODY, "Native declaration can not have a body"); MAP.put(ErrorsJvm.NATIVE_DECLARATION_IN_TRAIT, "Members of traits can not be native"); MAP.put(ErrorsJvm.NATIVE_DECLARATION_CANNOT_BE_INLINED, "Members of traits can not be inlined"); + + MAP.put(ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS, + "Expected type does not accept nulls in {0}, but the value may be null in {1}", Renderers.TO_STRING, Renderers.TO_STRING); } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 631fc04c936..4fceaf418f7 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -17,14 +17,18 @@ package org.jetbrains.kotlin.resolve.jvm.diagnostics; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1; +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.psi.JetDeclaration; +import org.jetbrains.kotlin.psi.JetExpression; import static org.jetbrains.kotlin.diagnostics.PositioningStrategies.*; import static org.jetbrains.kotlin.diagnostics.Severity.ERROR; +import static org.jetbrains.kotlin.diagnostics.Severity.WARNING; public interface ErrorsJvm { DiagnosticFactory1 CONFLICTING_JVM_DECLARATIONS = @@ -42,6 +46,25 @@ public interface ErrorsJvm { DiagnosticFactory0 NATIVE_DECLARATION_IN_TRAIT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0 NATIVE_DECLARATION_CANNOT_BE_INLINED = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + enum NullabilityInformationSource { + KOTLIN { + @NotNull + @Override + public String toString() { + return "Kotlin"; + } + }, + JAVA { + @NotNull + @Override + public String toString() { + return "Java"; + } + }; + } + + DiagnosticFactory2 NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS = DiagnosticFactory2.create(WARNING); + @SuppressWarnings("UnusedDeclaration") Object _initializer = new Object() { { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt index b4758c7cd06..b6a725d42a5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt @@ -23,11 +23,12 @@ private val DEFAULT_TYPE_CHECKERS = listOf(TypeApproximator()) public abstract class AdditionalCheckerProvider( public val annotationCheckers: List, - additionalCallCheckers: List + additionalCallCheckers: List, + additionalTypeCheckers: List ) { public val callCheckers: List = DEFAULT_CALL_CHECKERS + additionalCallCheckers - public val additionalTypeCheckers: List = DEFAULT_TYPE_CHECKERS + public val additionalTypeCheckers: List = DEFAULT_TYPE_CHECKERS + additionalTypeCheckers - public object DefaultProvider : AdditionalCheckerProvider(listOf(), listOf()) {} + public object DefaultProvider : AdditionalCheckerProvider(listOf(), listOf(), listOf()) {} } diff --git a/compiler/testData/diagnostics/tests/jdk-annotations/sql/DriverManager.kt b/compiler/testData/diagnostics/tests/jdk-annotations/sql/DriverManager.kt index f6caf2a1b6a..616d7f32d44 100644 --- a/compiler/testData/diagnostics/tests/jdk-annotations/sql/DriverManager.kt +++ b/compiler/testData/diagnostics/tests/jdk-annotations/sql/DriverManager.kt @@ -1,29 +1,29 @@ import java.sql.DriverManager fun getConnection(url: String?) { - DriverManager.getConnection(url) + DriverManager.getConnection(url) DriverManager.getConnection(url!!) : java.sql.Connection } fun getConnection(url: String?, props: java.util.Properties?) { - DriverManager.getConnection(url, props) + DriverManager.getConnection(url, props) DriverManager.getConnection(url!!, props) : java.sql.Connection } fun getConnection(url: String?, user: String?, password: String?) { - DriverManager.getConnection(url, user!!, password!!) + DriverManager.getConnection(url, user!!, password!!) DriverManager.getConnection(url!!, user, password!!) DriverManager.getConnection(url!!, user!!, password) DriverManager.getConnection(url!!, user!!, password!!) : java.sql.Connection } fun getDriver(url: String?) { - DriverManager.getDriver(url) + DriverManager.getDriver(url) DriverManager.getDriver(url!!) : java.sql.Driver } fun registerDriver(driver: java.sql.Driver?) { - DriverManager.registerDriver(driver) + DriverManager.registerDriver(driver) DriverManager.registerDriver(driver!!) } diff --git a/compiler/testData/diagnostics/tests/jdk-annotations/sql/Statement.kt b/compiler/testData/diagnostics/tests/jdk-annotations/sql/Statement.kt index 8d29bc6afcd..29796b31720 100644 --- a/compiler/testData/diagnostics/tests/jdk-annotations/sql/Statement.kt +++ b/compiler/testData/diagnostics/tests/jdk-annotations/sql/Statement.kt @@ -1,5 +1,5 @@ fun executeQuery(statement: java.sql.Statement, cmd: String?) { - statement.executeQuery(cmd) + statement.executeQuery(cmd) statement.executeQuery(cmd!!) : java.sql.ResultSet } @@ -8,6 +8,6 @@ fun executeQuery(statement: java.sql.PreparedStatement) { } fun executeUpdate(statement: java.sql.Statement, cmd: String?) { - statement.executeUpdate(cmd) + statement.executeUpdate(cmd) statement.executeUpdate(cmd!!) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt new file mode 100644 index 00000000000..9f0893f8617 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt @@ -0,0 +1,58 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static Integer staticNN; + @Nullable + public static Integer staticN; + public static Integer staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + var platformNN = J.staticNN + // @Nullable platform type + var platformN = J.staticN + // platform type with no annotation + var platformJ = J.staticJ + + +platformNN + +platformN + +platformJ + + ++platformNN + ++platformN + ++platformJ + + platformNN++ + platformN++ + platformJ++ + + 1 + platformNN + 1 + platformN + 1 + platformJ + + platformNN + 1 + platformN + 1 + platformJ + 1 + + 1 plus platformNN + 1 plus platformN + 1 plus platformJ + + platformNN plus 1 + platformN plus 1 + platformJ plus 1 + + platformNN += 1 + platformN += 1 + platformJ += 1 +} + diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt new file mode 100644 index 00000000000..42086763d95 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt @@ -0,0 +1,34 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static Integer[] staticNN; + @Nullable + public static Integer[] staticN; + public static Integer[] staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + platformNN[0] + platformN[0] + platformJ[0] + + platformNN[0] = 1 + platformN[0] = 1 + platformJ[0] = 1 +} + diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.kt new file mode 100644 index 00000000000..600db661622 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.kt @@ -0,0 +1,29 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; + public static J staticJ; +} + +// FILE: k.kt + +import p.* + +var v: J = J() +var n: J? = J() + +fun test() { + v = J.staticNN + v = J.staticN + v = J.staticJ + + n = J.staticNN + n = J.staticN + n = J.staticJ +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.txt new file mode 100644 index 00000000000..b258b62a31a --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.txt @@ -0,0 +1,5 @@ +package + +internal var n: p.J? +internal var v: p.J +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.kt new file mode 100644 index 00000000000..4e875c499b7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.kt @@ -0,0 +1,50 @@ +// !DIAGNOSTICS: -UNUSED_EXPRESSION +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static Boolean staticNN; + @Nullable + public static Boolean staticN; + public static Boolean staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + if (platformNN) {} + if (platformN) {} + if (platformJ) {} + + while (platformNN) {} + while (platformN) {} + while (platformJ) {} + + do {} while (platformNN) + do {} while (platformN) + do {} while (platformJ) + + platformNN && false + platformN && false + platformJ && false + + platformNN || false + platformN || false + platformJ || false + + !platformNN + !platformN + !platformJ +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.kt new file mode 100644 index 00000000000..eb1fd9521cd --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.kt @@ -0,0 +1,34 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; +} + +// FILE: k.kt + +import p.* + +fun test() { + val n = J.staticN + foo(n) + J.staticNN = n + if (n != null) { + foo(n) + J.staticNN = n + } + + val x: J? = null + J.staticNN = x + if (x != null) { + J.staticNN = x + } +} + +fun foo(j: J) {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.txt new file mode 100644 index 00000000000..7719efbbb09 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.txt @@ -0,0 +1,4 @@ +package + +internal fun foo(/*0*/ j: p.J): kotlin.Unit +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.kt new file mode 100644 index 00000000000..b9cbbe9a057 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.kt @@ -0,0 +1,30 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; + public static J staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + fun foo(p: J = platformNN, p1: J = platformN, p2: J = platformJ) {} + + fun foo1(p: J? = platformNN, p1: J? = platformN, p2: J? = platformJ) {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.kt new file mode 100644 index 00000000000..779de1aa89a --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.kt @@ -0,0 +1,26 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + + public interface DP { + String get(Object a, Object b); + String set(Object a, Object b, Object c); + } + + @NotNull + public static DP staticNN; + @Nullable + public static DP staticN; + public static DP staticJ; +} + +// FILE: k.kt + +import p.* + +var A by J.staticNN +var B by J.staticN +var C by J.staticJ \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.txt new file mode 100644 index 00000000000..be11c83820c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.txt @@ -0,0 +1,5 @@ +package + +internal var A: kotlin.String! +internal var B: kotlin.String! +internal var C: kotlin.String! diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.kt new file mode 100644 index 00000000000..38f22824d4b --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.kt @@ -0,0 +1,21 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; +import java.util.*; + +public class J { + @NotNull + public static List staticNN; + @Nullable + public static List staticN; + public static List staticJ; +} + +// FILE: k.kt + +import p.* + +class A : List by J.staticNN +class B : List by J.staticN +class C : List by J.staticJ \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.txt new file mode 100644 index 00000000000..8088400d541 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.txt @@ -0,0 +1,55 @@ +package + +internal final class A : kotlin.List { + public constructor A() + public open override /*1*/ /*delegation*/ fun contains(/*0*/ o: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun get(/*0*/ index: kotlin.Int): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*delegation*/ fun indexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*delegation*/ fun isEmpty(): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun iterator(): kotlin.Iterator + public open override /*1*/ /*delegation*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*delegation*/ fun listIterator(): kotlin.ListIterator + public open override /*1*/ /*delegation*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.ListIterator + public open override /*1*/ /*delegation*/ fun size(): kotlin.Int + public open override /*1*/ /*delegation*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.List + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class B : kotlin.List { + public constructor B() + public open override /*1*/ /*delegation*/ fun contains(/*0*/ o: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun get(/*0*/ index: kotlin.Int): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*delegation*/ fun indexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*delegation*/ fun isEmpty(): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun iterator(): kotlin.Iterator + public open override /*1*/ /*delegation*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*delegation*/ fun listIterator(): kotlin.ListIterator + public open override /*1*/ /*delegation*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.ListIterator + public open override /*1*/ /*delegation*/ fun size(): kotlin.Int + public open override /*1*/ /*delegation*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.List + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class C : kotlin.List { + public constructor C() + public open override /*1*/ /*delegation*/ fun contains(/*0*/ o: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun get(/*0*/ index: kotlin.Int): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*delegation*/ fun indexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*delegation*/ fun isEmpty(): kotlin.Boolean + public open override /*1*/ /*delegation*/ fun iterator(): kotlin.Iterator + public open override /*1*/ /*delegation*/ fun lastIndexOf(/*0*/ o: kotlin.Any?): kotlin.Int + public open override /*1*/ /*delegation*/ fun listIterator(): kotlin.ListIterator + public open override /*1*/ /*delegation*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.ListIterator + public open override /*1*/ /*delegation*/ fun size(): kotlin.Int + public open override /*1*/ /*delegation*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.List + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.kt new file mode 100644 index 00000000000..f347587985e --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.kt @@ -0,0 +1,36 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; + public static J staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + platformNN.foo() + platformN.foo() + platformJ.foo() + + platformNN.bar() + platformN.bar() + platformJ.bar() +} + +fun J.foo() {} +fun J?.bar() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.txt new file mode 100644 index 00000000000..7a159d150bd --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.txt @@ -0,0 +1,5 @@ +package + +internal fun test(): kotlin.Unit +internal fun p.J?.bar(): kotlin.Unit +internal fun p.J.foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.kt new file mode 100644 index 00000000000..ab50a82968a --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.kt @@ -0,0 +1,31 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; + public static J staticJ; + + public void foo() {} +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + platformNN.foo() + platformN.foo() + platformJ.foo() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.kt new file mode 100644 index 00000000000..67de74a347c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.kt @@ -0,0 +1,33 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; + public static J staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + platformNN : J + platformN : J + platformJ : J + + platformNN : J? + platformN : J? + platformJ : J? +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.kt new file mode 100644 index 00000000000..61019d75c5b --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.kt @@ -0,0 +1,31 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; +import java.util.*; + +public class J { + @NotNull + public static List staticNN; + @Nullable + public static List staticN; + public static List staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + for (x in platformNN) {} + for (x in platformN) {} + for (x in platformJ) {} +} + diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.kt new file mode 100644 index 00000000000..dcca95d883d --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.kt @@ -0,0 +1,30 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; + public static J staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + foo(J.staticNN) + foo(J.staticN) + foo(J.staticJ) + + bar(J.staticNN) + bar(J.staticN) + bar(J.staticJ) +} + +fun foo(j: J) {} +fun bar(j: J?) {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.txt new file mode 100644 index 00000000000..febe9fdde72 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.txt @@ -0,0 +1,5 @@ +package + +internal fun bar(/*0*/ j: p.J?): kotlin.Unit +internal fun foo(/*0*/ j: p.J): kotlin.Unit +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt new file mode 100644 index 00000000000..d7805c85fff --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt @@ -0,0 +1,27 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + public interface Invoke { + void invoke(); + } + + @NotNull + public static Invoke staticNN; + @Nullable + public static Invoke staticN; + public static Invoke staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + J.staticNN() + J.staticN() + J.staticJ() +} + diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.kt new file mode 100644 index 00000000000..dd4b48f3ed1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.kt @@ -0,0 +1,36 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + public interface Multi { + String component1(); + String component2(); + } + + @NotNull + public static Multi staticNN; + @Nullable + public static Multi staticN; + public static Multi staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + val (a1, b1) = platformNN + val (a2, b2) = platformN + val (a3, b3) = platformJ +} + diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.txt new file mode 100644 index 00000000000..b8def46715c --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.txt @@ -0,0 +1,3 @@ +package + +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.kt new file mode 100644 index 00000000000..89f3a61f6f2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.kt @@ -0,0 +1,92 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static J staticNN; + @Nullable + public static J staticN; + public static J staticJ; + + public static void staticSet(@NotNull J nn, @Nullable J n, J j) {} + + public J(@NotNull J nn, @Nullable J n, J j) {} + public J() {} + + @NotNull + public J nn; + @Nullable + public J n; + public J j; + + public void set(@NotNull J nn, @Nullable J n, J j) {} +} + +// FILE: k.kt + +import p.* + +fun test(n: J?, nn: J) { + // @NotNull platform type + val platformNN = J.staticNN + // @Nullable platform type + val platformN = J.staticN + // platform type with no annotation + val platformJ = J.staticJ + + J.staticNN = n + J.staticNN = platformN + J.staticNN = nn + J.staticNN = platformNN + J.staticNN = platformJ + + J.staticN = n + J.staticN = platformN + J.staticN = nn + J.staticN = platformNN + J.staticN = platformJ + + J.staticJ = n + J.staticJ = platformN + J.staticJ = nn + J.staticJ = platformNN + J.staticJ = platformJ + + J.staticSet(nn, nn, nn) + J.staticSet(platformNN, platformNN, platformNN) + J.staticSet(n, n, n) + J.staticSet(platformN, platformN, platformN) + J.staticSet(platformJ, platformJ, platformJ) + + J().nn = n + J().nn = platformN + J().nn = nn + J().nn = platformNN + J().nn = platformJ + + J().n = n + J().n = platformN + J().n = nn + J().n = platformNN + J().n = platformJ + + J().j = n + J().j = platformN + J().j = nn + J().j = platformNN + J().j = platformJ + + J().set(nn, nn, nn) + J().set(platformNN, platformNN, platformNN) + J().set(n, n, n) + J().set(platformN, platformN, platformN) + J().set(platformJ, platformJ, platformJ) + + J(nn, nn, nn) + J(platformNN, platformNN, platformNN) + J(n, n, n) + J(platformN, platformN, platformN) + J(platformJ, platformJ, platformJ) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.txt new file mode 100644 index 00000000000..468c30694dc --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.txt @@ -0,0 +1,3 @@ +package + +internal fun test(/*0*/ n: p.J?, /*1*/ nn: p.J): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt new file mode 100644 index 00000000000..9d74d623335 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt @@ -0,0 +1,28 @@ +// FILE: p/J.java +package p; + +import org.jetbrains.annotations.*; + +public class J { + @NotNull + public static Exception staticNN; + @Nullable + public static Exception staticN; + public static Exception staticJ; +} + +// FILE: k.kt + +import p.* + +fun test() { + throw J.staticNN +} + +fun test1() { + throw J.staticN +} + +fun test2() { + throw J.staticJ +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.txt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.txt new file mode 100644 index 00000000000..324eef14d41 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.txt @@ -0,0 +1,5 @@ +package + +internal fun test(): kotlin.Unit +internal fun test1(): kotlin.Unit +internal fun test2(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 81051aa43eb..5133abe2e90 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -8262,7 +8262,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { @TestMetadata("compiler/testData/diagnostics/tests/platformTypes") @TestDataPath("$PROJECT_ROOT") - @InnerTestClasses({PlatformTypes.CommonSupertype.class, PlatformTypes.Intersection.class, PlatformTypes.MethodCall.class}) + @InnerTestClasses({PlatformTypes.CommonSupertype.class, PlatformTypes.Intersection.class, PlatformTypes.MethodCall.class, PlatformTypes.NullabilityWarnings.class}) @RunWith(JUnit3RunnerWithInners.class) public static class PlatformTypes extends AbstractJetDiagnosticsTest { public void testAllFilesPresentInPlatformTypes() throws Exception { @@ -8529,6 +8529,117 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class NullabilityWarnings extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInNullabilityWarnings() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("arithmetic.kt") + public void testArithmetic() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt"); + doTest(fileName); + } + + @TestMetadata("array.kt") + public void testArray() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/array.kt"); + doTest(fileName); + } + + @TestMetadata("assignToVar.kt") + public void testAssignToVar() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/assignToVar.kt"); + doTest(fileName); + } + + @TestMetadata("conditions.kt") + public void testConditions() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/conditions.kt"); + doTest(fileName); + } + + @TestMetadata("dataFlowInfo.kt") + public void testDataFlowInfo() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/dataFlowInfo.kt"); + doTest(fileName); + } + + @TestMetadata("defaultParameters.kt") + public void testDefaultParameters() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/defaultParameters.kt"); + doTest(fileName); + } + + @TestMetadata("delegatedProperties.kt") + public void testDelegatedProperties() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegatedProperties.kt"); + doTest(fileName); + } + + @TestMetadata("delegation.kt") + public void testDelegation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/delegation.kt"); + doTest(fileName); + } + + @TestMetadata("derefenceExtension.kt") + public void testDerefenceExtension() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceExtension.kt"); + doTest(fileName); + } + + @TestMetadata("derefenceMember.kt") + public void testDerefenceMember() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/derefenceMember.kt"); + doTest(fileName); + } + + @TestMetadata("expectedType.kt") + public void testExpectedType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/expectedType.kt"); + doTest(fileName); + } + + @TestMetadata("for.kt") + public void testFor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/for.kt"); + doTest(fileName); + } + + @TestMetadata("functionArguments.kt") + public void testFunctionArguments() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/functionArguments.kt"); + doTest(fileName); + } + + @TestMetadata("invoke.kt") + public void testInvoke() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/invoke.kt"); + doTest(fileName); + } + + @TestMetadata("multiDeclaration.kt") + public void testMultiDeclaration() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/multiDeclaration.kt"); + doTest(fileName); + } + + @TestMetadata("passToJava.kt") + public void testPassToJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/passToJava.kt"); + doTest(fileName); + } + + @TestMetadata("throw.kt") + public void testThrow() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/diagnostics/tests/recovery") diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt index 54f082c9efe..51bc4d349b1 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt @@ -362,7 +362,8 @@ class LazyJavaTypeAttributes( private fun Annotations.isMarkedReadOnly() = findAnnotation(JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION) != null private fun Annotations.isMarkedMutable() = findAnnotation(JvmAnnotationNames.JETBRAINS_MUTABLE_ANNOTATION) != null -private fun Annotations.isMarkedNotNull() = findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null +internal fun Annotations.isMarkedNotNull() = findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null +internal fun Annotations.isMarkedNullable() = findAnnotation(JvmAnnotationNames.JETBRAINS_NULLABLE_ANNOTATION) != null fun TypeUsage.toAttributes(allowFlexible: Boolean = true) = object : JavaTypeAttributes { override val howThisTypeIsUsed: TypeUsage = this@toAttributes diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/KotlinJsCheckerProvider.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/KotlinJsCheckerProvider.kt index 6b7032ba4ba..75f7415a78d 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/KotlinJsCheckerProvider.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/KotlinJsCheckerProvider.kt @@ -35,7 +35,8 @@ import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker public object KotlinJsCheckerProvider : AdditionalCheckerProvider( annotationCheckers = listOf(NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker()), - additionalCallCheckers = listOf() + additionalCallCheckers = listOf(), + additionalTypeCheckers = listOf() ) private abstract class AbstractNativeAnnotationsChecker(private val requiredAnnotation: PredefinedAnnotation) : AnnotationChecker { diff --git a/spec-docs/flexible-java-types.md b/spec-docs/flexible-java-types.md index eff40dee5f7..d4a5081fceb 100644 --- a/spec-docs/flexible-java-types.md +++ b/spec-docs/flexible-java-types.md @@ -120,4 +120,23 @@ Constructs in question: anything that provides an expected type, i.e. - all kinds of calls (foo, foo(), x[], x foo y, x + y, x++, x += 3, for loop, multi-declarations, invoke-convention, ...) - explicit expected type (foo: Bar) - for booleans: if (foo), foo || bar, foo && bar (!foo is a call) - - argument of throw \ No newline at end of file + - argument of throw + +## Warnings on nullability misuse + +A type loaded from Java is said to *bare* a `@Nullable`/`@NotNull` annotation when + - it's a return type a method so annotated; + - it's a type of a field or a parameter so annotated; + - it's a so annotated type (Java 8 and later). + +A value is `@Nullable`/`@NotNull` when its type bares such an annotation. + +Inside this section, a value is *nullable*/*not-null* when + - it's `@Nullable`/`@NotNull`, or + - it's type in Kotlin when refined with data flow info is nullable/not-null. + +The compiler issues warnings specific to `@Nullable`/`@NotNull` in the following situations: + - a `@Nullable` value is assigned to a not-null location (including passing parameters and receivers to functions/properties); + - a nullable value is assigned to a `@NotNull` location; + - a `@NotNull` value is dereferenced with a safe call (`?.`), used in `!!` or on the left-hand side of an elvis operator `?:`; + - a `@NotNull` value is compared with `null` through `==`, `!=`, `===` or `!==` \ No newline at end of file