[FIR] Add NULLABLE_INLINE_PARAMETER diagnostic

This commit is contained in:
Andrey Zinovyev
2021-07-20 15:32:10 +03:00
committed by teamcityserver
parent 015c2d1875
commit 4e06814bc5
11 changed files with 61 additions and 36 deletions
@@ -1136,6 +1136,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val NOTHING_TO_INLINE by warning<KtDeclaration>(PositioningStrategy.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT)
val NULLABLE_INLINE_PARAMETER by error<KtDeclaration>() {
parameter<FirValueParameterSymbol>("parameter")
parameter<Symbol>("function")
}
val RECURSION_IN_INLINE by error<KtElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Symbol>("symbol")
}
@@ -600,6 +600,7 @@ object FirErrors {
val NON_LOCAL_RETURN_NOT_ALLOWED by error1<KtElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val NOT_YET_SUPPORTED_IN_INLINE by error1<KtDeclaration, String>(SourceElementPositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT)
val NOTHING_TO_INLINE by warning0<KtDeclaration>(SourceElementPositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT)
val NULLABLE_INLINE_PARAMETER by error2<KtDeclaration, FirValueParameterSymbol, FirBasedSymbol<*>>()
val RECURSION_IN_INLINE by error1<KtElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val NON_PUBLIC_CALL_FROM_PUBLIC_INLINE by error2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val PROTECTED_CONSTRUCTOR_CALL_FROM_PUBLIC_INLINE by error2<KtElement, FirBasedSymbol<*>, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -338,17 +338,28 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
private fun checkParameters(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (function !is FirSimpleFunction) return
if (function.isSuspend) {
function.valueParameters
.filter { !it.isNoinline && it.defaultValue != null && it.returnTypeRef.coneType.isSuspendFunctionType(context.session) }
.forEach { param ->
reporter.reportOn(
param.source,
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
"Suspend functional parameters with default values",
context
)
}
for (param in function.valueParameters) {
if (param.isNoinline) continue
val coneType = param.returnTypeRef.coneType
if (function.isSuspend && param.defaultValue != null && coneType.isSuspendFunctionType(context.session)) {
reporter.reportOn(
param.source,
FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
"Suspend functional parameters with default values",
context
)
}
if (coneType.isNullable && coneType.isFunctionalType(context.session)) {
reporter.reportOn(
param.source,
FirErrors.NULLABLE_INLINE_PARAMETER,
param.symbol,
function.symbol,
context
)
}
}
//check for inherited default values
@@ -288,6 +288,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RETURN_IN_FUNC
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SET_METHOD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_VALUE_FOR_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_INLINE_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER
@@ -1488,6 +1489,13 @@ class FirDefaultErrorMessages {
NOTHING_TO_INLINE,
"Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types"
)
map.put(
NULLABLE_INLINE_PARAMETER,
"Inline-parameter ''{0}'' of ''{1}'' must not be nullable. Add ''noinline'' modifier to the parameter declaration or make its type not nullable",
SYMBOL,
SYMBOL
)
map.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", SYMBOL)
//imports
@@ -1,4 +0,0 @@
inline fun test(s: () -> Unit, p: (() -> Unit)?) {
s()
p?.invoke()
}
+1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
inline fun test(s: () -> Unit, <!NULLABLE_INLINE_PARAMETER!>p: (() -> Unit)?<!>) {
s()
p?.invoke()
@@ -1,21 +0,0 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -CONFLICTING_JVM_DECLARATIONS
public inline fun <T> Function1<Int, Int>?.submit(action: ()->T) {
this?.invoke(11)
}
public inline fun <T> submit(action: Function1<Int, Int>?, s: () -> Int) {
action?.invoke(10)
}
public inline fun <T> submitNoInline(noinline action: Function1<Int, Int>?, s: () -> Int) {
action?.invoke(10)
}
public <!NOTHING_TO_INLINE!>inline<!> fun <T> Function1<Int, Int>?.submit() {
}
public <!NOTHING_TO_INLINE!>inline<!> fun <T> submit(action: Function1<Int, Int>?) {
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -CONFLICTING_JVM_DECLARATIONS
public inline fun <T> Function1<Int, Int>?.submit(action: ()->T) {
@@ -3105,6 +3105,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.NULLABLE_INLINE_PARAMETER) { firDiagnostic ->
NullableInlineParameterImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
firSymbolBuilder.buildSymbol(firDiagnostic.b.fir),
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.RECURSION_IN_INLINE) { firDiagnostic ->
RecursionInInlineImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
@@ -2164,6 +2164,12 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = NothingToInline::class
}
abstract class NullableInlineParameter : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = NullableInlineParameter::class
abstract val parameter: KtSymbol
abstract val function: KtSymbol
}
abstract class RecursionInInline : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = RecursionInInline::class
abstract val symbol: KtSymbol
@@ -3497,6 +3497,15 @@ internal class NothingToInlineImpl(
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class NullableInlineParameterImpl(
override val parameter: KtSymbol,
override val function: KtSymbol,
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.NullableInlineParameter(), KtAbstractFirDiagnostic<KtDeclaration> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class RecursionInInlineImpl(
override val symbol: KtSymbol,
firDiagnostic: FirPsiDiagnostic,