Introduce FirFunctionReturnTypeMismatchChecker
This commit is contained in:
+8
@@ -986,6 +986,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.RETURN_TYPE_MISMATCH) { firDiagnostic ->
|
||||
ReturnTypeMismatchImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED) { firDiagnostic ->
|
||||
ExtensionInClassReferenceNotAllowedImpl(
|
||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a as FirCallableDeclaration),
|
||||
|
||||
+6
@@ -701,6 +701,12 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val typeParametersOwner: KtSymbol
|
||||
}
|
||||
|
||||
abstract class ReturnTypeMismatch : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = ReturnTypeMismatch::class
|
||||
abstract val expected: KtType
|
||||
abstract val actual: KtType
|
||||
}
|
||||
|
||||
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = ExtensionInClassReferenceNotAllowed::class
|
||||
abstract val referencedDeclaration: KtCallableSymbol
|
||||
|
||||
+9
@@ -1131,6 +1131,15 @@ internal class NameInConstraintIsNotATypeParameterImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ReturnTypeMismatchImpl(
|
||||
override val expected: KtType,
|
||||
override val actual: KtType,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ReturnTypeMismatch(), KtAbstractFirDiagnostic<KtExpression> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ExtensionInClassReferenceNotAllowedImpl(
|
||||
override val referencedDeclaration: KtCallableSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
|
||||
+28
-28
@@ -6,14 +6,14 @@ fun none() {}
|
||||
fun unitEmptyInfer() {}
|
||||
fun unitEmpty() : Unit {}
|
||||
fun unitEmptyReturn() : Unit {return}
|
||||
fun unitIntReturn() : Unit {return 1}
|
||||
fun unitIntReturn() : Unit {return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Unit, actual kotlin/Int">1</error>}
|
||||
fun unitUnitReturn() : Unit {return Unit}
|
||||
fun test1() : Any = { <error descr="[RETURN_NOT_ALLOWED] 'return' is not allowed here">return</error> }
|
||||
fun test2() : Any = a@ {return@a 1}
|
||||
fun test3() : Any { return }
|
||||
|
||||
fun bbb() {
|
||||
return 1
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Unit, actual kotlin/Int">1</error>
|
||||
}
|
||||
|
||||
fun foo(expr: StringBuilder): Int {
|
||||
@@ -26,8 +26,8 @@ fun foo(expr: StringBuilder): Int {
|
||||
|
||||
|
||||
fun unitShort() : Unit = Unit
|
||||
fun unitShortConv() : Unit = 1
|
||||
fun unitShortNull() : Unit = null
|
||||
fun unitShortConv() : Unit = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Unit, actual kotlin/Int">1</error>
|
||||
fun unitShortNull() : Unit = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Unit, actual kotlin/Nothing?">null</error>
|
||||
|
||||
fun intEmpty() : Int {}
|
||||
fun intShortInfer() = 1
|
||||
@@ -36,56 +36,56 @@ fun intShort() : Int = 1
|
||||
fun intBlock() : Int {return 1}
|
||||
fun intBlock1() : Int {1}
|
||||
|
||||
fun intString(): Int = "s"
|
||||
fun intFunctionLiteral(): Int = { 10 }
|
||||
fun intString(): Int = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/String">"s"</error>
|
||||
fun intFunctionLiteral(): Int = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Function0<kotlin/Int>">{ 10 }</error>
|
||||
|
||||
fun blockReturnUnitMismatch() : Int {return}
|
||||
fun blockReturnValueTypeMismatch() : Int {return 3.4}
|
||||
fun blockReturnUnitMismatch() : Int {<error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Unit">return</error>}
|
||||
fun blockReturnValueTypeMismatch() : Int {return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">3.4</error>}
|
||||
fun blockReturnValueTypeMatch() : Int {return 1}
|
||||
fun blockReturnValueTypeMismatchUnit() : Int {return Unit}
|
||||
fun blockReturnValueTypeMismatchUnit() : Int {return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Unit">Unit</error>}
|
||||
|
||||
fun blockAndAndMismatch() : Int {
|
||||
true && false
|
||||
}
|
||||
fun blockAndAndMismatch1() : Int {
|
||||
return true && false
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Boolean">true && false</error>
|
||||
}
|
||||
fun blockAndAndMismatch2() : Int {
|
||||
(return true) && (return false)
|
||||
(return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Boolean">true</error>) && (return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Boolean">false</error>)
|
||||
}
|
||||
|
||||
fun blockAndAndMismatch3() : Int {
|
||||
true || false
|
||||
}
|
||||
fun blockAndAndMismatch4() : Int {
|
||||
return true || false
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Boolean">true || false</error>
|
||||
}
|
||||
fun blockAndAndMismatch5() : Int {
|
||||
(return true) || (return false)
|
||||
(return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Boolean">true</error>) || (return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Boolean">false</error>)
|
||||
}
|
||||
fun blockReturnValueTypeMatch1() : Int {
|
||||
return if (1 > 2) 1.0 else 2.0
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">if (1 > 2) 1.0 else 2.0</error>
|
||||
}
|
||||
fun blockReturnValueTypeMatch2() : Int {
|
||||
return <error descr="[INVALID_IF_AS_EXPRESSION] 'if' must have both main and 'else' branches if used as an expression">if</error> (1 > 2) 1
|
||||
}
|
||||
fun blockReturnValueTypeMatch3() : Int {
|
||||
return if (1 > 2) else 1
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Any">if (1 > 2) else 1</error>
|
||||
}
|
||||
fun blockReturnValueTypeMatch4() : Int {
|
||||
if (1 > 2)
|
||||
return 1.0
|
||||
else return 2.0
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">1.0</error>
|
||||
else return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">2.0</error>
|
||||
}
|
||||
fun blockReturnValueTypeMatch5() : Int {
|
||||
if (1 > 2)
|
||||
return 1.0
|
||||
return 2.0
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">1.0</error>
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">2.0</error>
|
||||
}
|
||||
fun blockReturnValueTypeMatch6() : Int {
|
||||
if (1 > 2)
|
||||
else return 1.0
|
||||
return 2.0
|
||||
else return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">1.0</error>
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">2.0</error>
|
||||
}
|
||||
fun blockReturnValueTypeMatch7() : Int {
|
||||
if (1 > 2)
|
||||
@@ -112,7 +112,7 @@ fun blockReturnValueTypeMatch11() : Int {
|
||||
fun blockReturnValueTypeMatch12() : Int {
|
||||
if (1 > 2)
|
||||
return 1
|
||||
else return 1.0
|
||||
else return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Double">1.0</error>
|
||||
}
|
||||
fun blockNoReturnIfValDeclaration(): Int {
|
||||
val x = 1
|
||||
@@ -130,23 +130,23 @@ fun blockNoReturnIfUnitInOneBranch(): Int {
|
||||
}
|
||||
}
|
||||
}
|
||||
fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) {} else {}
|
||||
fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) {} else 2
|
||||
fun nonBlockReturnIfEmptyIf(): Int = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Unit">if (1 < 2) {} else {}</error>
|
||||
fun nonBlockNoReturnIfUnitInOneBranch(): Int = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/Any">if (1 < 2) {} else 2</error>
|
||||
|
||||
val a = <error descr="[RETURN_NOT_ALLOWED] 'return' is not allowed here">return</error> 1
|
||||
|
||||
class A() {
|
||||
}
|
||||
fun illegalConstantBody(): Int = "s"
|
||||
fun illegalConstantBody(): Int = <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/String">"s"</error>
|
||||
fun illegalConstantBlock(): String {
|
||||
return 1
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/String, actual kotlin/Int">1</error>
|
||||
}
|
||||
fun illegalIfBody(): Int =
|
||||
if (1 < 2) 'a' else { 1.0 }
|
||||
<error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual it(kotlin/Comparable<*> & java/io/Serializable)">if (1 < 2) 'a' else { 1.0 }</error>
|
||||
fun illegalIfBlock(): Boolean {
|
||||
if (1 < 2)
|
||||
return false
|
||||
else { return 1 }
|
||||
else { return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Boolean, actual kotlin/Int">1</error> }
|
||||
}
|
||||
fun illegalReturnIf(): Char {
|
||||
return if (1 < 2) 'a' else { 1 }
|
||||
|
||||
+8
-8
@@ -161,7 +161,7 @@ fun illegalWhenBody(a: Any): Int = when(a) {
|
||||
fun illegalWhenBlock(a: Any): Int {
|
||||
when(a) {
|
||||
is Int -> return a
|
||||
is String -> return a
|
||||
is String -> return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/Int, actual kotlin/String">a</error>
|
||||
else -> return 1
|
||||
}
|
||||
}
|
||||
@@ -218,11 +218,11 @@ fun f(): String {
|
||||
if (a is String) {
|
||||
val i: String = a
|
||||
a.compareTo("f")
|
||||
val f: Function0<String> = {
|
||||
val f: Function0<String> = <error descr="[INITIALIZER_TYPE_MISMATCH] Initializer type mismatch: expected kotlin/Function0<kotlin/String>, actual kotlin/Function0<kotlin/Int>">{
|
||||
a = 42
|
||||
a
|
||||
}
|
||||
return a
|
||||
}</error>
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/String, actual kotlin/Int">a</error>
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -234,13 +234,13 @@ class Mutable(var x: String?) {
|
||||
|
||||
fun foo(): String {
|
||||
if (x is String) {
|
||||
return x
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/String, actual kotlin/String?">x</error>
|
||||
}
|
||||
if (x != null) {
|
||||
return x
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/String, actual kotlin/String?">x</error>
|
||||
}
|
||||
if (xx is String) {
|
||||
return xx
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/String, actual kotlin/String?">xx</error>
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -248,7 +248,7 @@ class Mutable(var x: String?) {
|
||||
fun bar(other: Mutable): String {
|
||||
var y = other
|
||||
if (y.x is String) {
|
||||
return y.x
|
||||
return <error descr="[RETURN_TYPE_MISMATCH] Return type mismatch: expected kotlin/String, actual kotlin/String?">y.x</error>
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user