Implicit callable type check refactoring, additional check for property with explicit Nothing type
This commit is contained in:
@@ -727,6 +727,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory2<KtElement, KotlinType, KotlinType> INCOMPATIBLE_TYPES = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<KtElement, KotlinType, KotlinType> INCOMPATIBLE_TYPES = DiagnosticFactory2.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory0<PsiElement> IMPLICIT_NOTHING_RETURN_TYPE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> IMPLICIT_NOTHING_RETURN_TYPE = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<PsiElement> IMPLICIT_NOTHING_PROPERTY_TYPE = DiagnosticFactory0.create(WARNING);
|
||||||
DiagnosticFactory1<PsiElement, KotlinType> IMPLICIT_INTERSECTION_TYPE = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, KotlinType> IMPLICIT_INTERSECTION_TYPE = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
// Context tracking
|
// Context tracking
|
||||||
|
|||||||
+1
@@ -527,6 +527,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(TYPE_MISMATCH_IN_CONDITION, "Condition must be of type kotlin.Boolean, but is of type {0}", RENDER_TYPE);
|
MAP.put(TYPE_MISMATCH_IN_CONDITION, "Condition must be of type kotlin.Boolean, but is of type {0}", RENDER_TYPE);
|
||||||
MAP.put(INCOMPATIBLE_TYPES, "Incompatible types: {0} and {1}", RENDER_TYPE, RENDER_TYPE);
|
MAP.put(INCOMPATIBLE_TYPES, "Incompatible types: {0} and {1}", RENDER_TYPE, RENDER_TYPE);
|
||||||
MAP.put(IMPLICIT_NOTHING_RETURN_TYPE, "''Nothing'' return type needs to be specified explicitly");
|
MAP.put(IMPLICIT_NOTHING_RETURN_TYPE, "''Nothing'' return type needs to be specified explicitly");
|
||||||
|
MAP.put(IMPLICIT_NOTHING_PROPERTY_TYPE, "Deprecated: ''Nothing'' property type needs to be specified explicitly");
|
||||||
MAP.put(IMPLICIT_INTERSECTION_TYPE, "Inferred type {0} is an intersection, please specify the required type explicitly", RENDER_TYPE);
|
MAP.put(IMPLICIT_INTERSECTION_TYPE, "Inferred type {0} is an intersection, please specify the required type explicitly", RENDER_TYPE);
|
||||||
MAP.put(EXPECTED_CONDITION, "Expected condition of type kotlin.Boolean");
|
MAP.put(EXPECTED_CONDITION, "Expected condition of type kotlin.Boolean");
|
||||||
|
|
||||||
|
|||||||
@@ -435,13 +435,7 @@ class DeclarationsChecker(
|
|||||||
checkTypeParameterConstraints(property)
|
checkTypeParameterConstraints(property)
|
||||||
checkPropertyExposedType(property, propertyDescriptor)
|
checkPropertyExposedType(property, propertyDescriptor)
|
||||||
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
|
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
|
||||||
propertyDescriptor.returnType?.let {
|
checkImplicitCallableType(property, propertyDescriptor)
|
||||||
if (property.typeReference == null) {
|
|
||||||
if (it.constructor is IntersectionTypeConstructor) {
|
|
||||||
trace.report(IMPLICIT_INTERSECTION_TYPE.on(property.nameIdentifier ?: property, it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
||||||
@@ -656,19 +650,25 @@ class DeclarationsChecker(
|
|||||||
if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier) {
|
if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier) {
|
||||||
trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
||||||
}
|
}
|
||||||
functionDescriptor.returnType?.let {
|
checkImplicitCallableType(function, functionDescriptor)
|
||||||
if (!function.hasDeclaredReturnType()) {
|
checkFunctionExposedType(function, functionDescriptor)
|
||||||
|
checkVarargParameters(trace, functionDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkImplicitCallableType(declaration: KtCallableDeclaration, descriptor: CallableDescriptor) {
|
||||||
|
descriptor.returnType?.let {
|
||||||
|
if (declaration.typeReference == null) {
|
||||||
|
val target = declaration.nameIdentifier ?: declaration
|
||||||
if (it.isNothing()) {
|
if (it.isNothing()) {
|
||||||
trace.report(IMPLICIT_NOTHING_RETURN_TYPE.on(nameIdentifier ?: function))
|
trace.report(
|
||||||
|
(if (declaration is KtProperty) IMPLICIT_NOTHING_PROPERTY_TYPE else IMPLICIT_NOTHING_RETURN_TYPE).on(target)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (it.constructor is IntersectionTypeConstructor) {
|
if (it.constructor is IntersectionTypeConstructor) {
|
||||||
trace.report(IMPLICIT_INTERSECTION_TYPE.on(nameIdentifier ?: function, it))
|
trace.report(IMPLICIT_INTERSECTION_TYPE.on(target, it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFunctionExposedType(function, functionDescriptor)
|
|
||||||
checkVarargParameters(trace, functionDescriptor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkFunctionExposedType(function: KtFunction, functionDescriptor: FunctionDescriptor) {
|
private fun checkFunctionExposedType(function: KtFunction, functionDescriptor: FunctionDescriptor) {
|
||||||
|
|||||||
@@ -5,3 +5,14 @@ fun <!IMPLICIT_NOTHING_RETURN_TYPE!>bar<!>() = null!!
|
|||||||
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>baz<!>() = bar()
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>baz<!>() = bar()
|
||||||
|
|
||||||
fun gav(): Any = null!!
|
fun gav(): Any = null!!
|
||||||
|
|
||||||
|
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>x<!> = null!!
|
||||||
|
|
||||||
|
val y: Nothing = throw Exception()
|
||||||
|
|
||||||
|
fun check() {
|
||||||
|
// Error: KT-10449
|
||||||
|
fun local() = bar()
|
||||||
|
// Unreachable / unused, but not implicit Nothing
|
||||||
|
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>x<!> =<!> null!!
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
|
public val x: kotlin.Nothing
|
||||||
|
public val y: kotlin.Nothing
|
||||||
public fun bar(): kotlin.Nothing
|
public fun bar(): kotlin.Nothing
|
||||||
public fun baz(): kotlin.Nothing
|
public fun baz(): kotlin.Nothing
|
||||||
|
public fun check(): kotlin.Unit
|
||||||
public fun foo(): kotlin.Nothing
|
public fun foo(): kotlin.Nothing
|
||||||
public fun gav(): kotlin.Any
|
public fun gav(): kotlin.Any
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
fun fn(): Nothing = throw java.lang.RuntimeException("oops")
|
fun fn(): Nothing = throw java.lang.RuntimeException("oops")
|
||||||
|
|
||||||
val x = throw java.lang.RuntimeException("oops")
|
val x: Nothing = throw java.lang.RuntimeException("oops")
|
||||||
|
|
||||||
class SomeClass {
|
class SomeClass {
|
||||||
fun method() {
|
fun method() {
|
||||||
|
|||||||
Reference in New Issue
Block a user