Basic Java nullability warnings implemented
#KT-6723 In Progress
This commit is contained in:
+39
-1
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+23
@@ -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<PsiElement, ConflictingJvmDeclarationsData> CONFLICTING_JVM_DECLARATIONS =
|
||||
@@ -42,6 +46,25 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<JetDeclaration> NATIVE_DECLARATION_IN_TRAIT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<JetDeclaration> 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<JetExpression, NullabilityInformationSource, NullabilityInformationSource> NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS = DiagnosticFactory2.create(WARNING);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user