[FIR] Add ILLEGAL_INLINE_PARAMETER_MODIFIER diagnostic

This commit is contained in:
Andrey Zinovyev
2021-07-22 14:55:52 +03:00
committed by teamcityserver
parent dabc983f6a
commit b2f3485d7c
13 changed files with 59 additions and 24 deletions
@@ -1188,6 +1188,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error<KtElement>(PositioningStrategy.REIFIED_MODIFIER) val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error<KtElement>(PositioningStrategy.REIFIED_MODIFIER)
val INLINE_PROPERTY_WITH_BACKING_FIELD by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE) val INLINE_PROPERTY_WITH_BACKING_FIELD by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE)
val ILLEGAL_INLINE_PARAMETER_MODIFIER by error<KtElement>(PositioningStrategy.INLINE_PARAMETER_MODIFIER)
} }
val IMPORTS by object : DiagnosticGroup("Imports") { val IMPORTS by object : DiagnosticGroup("Imports") {
@@ -99,6 +99,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
INCOMPATIBLE_DECLARATION, INCOMPATIBLE_DECLARATION,
ACTUAL_DECLARATION_NAME, ACTUAL_DECLARATION_NAME,
UNREACHABLE_CODE, UNREACHABLE_CODE,
INLINE_PARAMETER_MODIFIER,
; ;
@@ -614,6 +614,7 @@ object FirErrors {
val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error2<KtElement, FirExpression, FirValueParameterSymbol>() val INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE by error2<KtElement, FirExpression, FirValueParameterSymbol>()
val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error0<KtElement>(SourceElementPositioningStrategies.REIFIED_MODIFIER) val REIFIED_TYPE_PARAMETER_IN_OVERRIDE by error0<KtElement>(SourceElementPositioningStrategies.REIFIED_MODIFIER)
val INLINE_PROPERTY_WITH_BACKING_FIELD by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val INLINE_PROPERTY_WITH_BACKING_FIELD by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
val ILLEGAL_INLINE_PARAMETER_MODIFIER by error0<KtElement>(SourceElementPositioningStrategies.INLINE_PARAMETER_MODIFIER)
// Imports // Imports
val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error1<KtImportDirective, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME) val CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON by error1<KtImportDirective, Name>(SourceElementPositioningStrategies.IMPORT_LAST_NAME)
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.PersistentCheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.PersistentCheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
import org.jetbrains.kotlin.fir.analysis.checkers.isInlineOnly import org.jetbrains.kotlin.fir.analysis.checkers.isInlineOnly
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.checkers.util.checkChildrenWithCustomVisitor import org.jetbrains.kotlin.fir.analysis.checkers.util.checkChildrenWithCustomVisitor
@@ -38,7 +39,10 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
object FirInlineDeclarationChecker : FirFunctionChecker() { object FirInlineDeclarationChecker : FirFunctionChecker() {
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isInline) return if (!declaration.isInline) {
checkParametersInNotInline(declaration, context, reporter)
return
}
// local inline functions are prohibited // local inline functions are prohibited
if (declaration.isLocalMember) { if (declaration.isLocalMember) {
reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local inline functions", context) reporter.reportOn(declaration.source, FirErrors.NOT_YET_SUPPORTED_IN_INLINE, "Local inline functions", context)
@@ -341,12 +345,18 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
reporter: DiagnosticReporter reporter: DiagnosticReporter
) { ) {
for (param in function.valueParameters) { for (param in function.valueParameters) {
if (param.isNoinline) continue
val coneType = param.returnTypeRef.coneType val coneType = param.returnTypeRef.coneType
val isFunctionalType = coneType.isFunctionalType(context.session) val isFunctionalType = coneType.isFunctionalType(context.session)
val isSuspendFunctionalType = coneType.isSuspendFunctionType(context.session)
val defaultValue = param.defaultValue val defaultValue = param.defaultValue
if (function.isSuspend && defaultValue != null && coneType.isSuspendFunctionType(context.session)) {
if (!(isFunctionalType || isSuspendFunctionalType) && (param.isNoinline || param.isCrossinline)) {
reporter.reportOn(param.source, FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER, context)
}
if (param.isNoinline) continue
if (function.isSuspend && defaultValue != null && isSuspendFunctionalType) {
reporter.reportOn( reporter.reportOn(
param.source, param.source,
FirErrors.NOT_YET_SUPPORTED_IN_INLINE, FirErrors.NOT_YET_SUPPORTED_IN_INLINE,
@@ -403,6 +413,14 @@ object FirInlineDeclarationChecker : FirFunctionChecker() {
} }
} }
private fun checkParametersInNotInline(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
for (param in function.valueParameters) {
if (param.isNoinline || param.isCrossinline) {
reporter.reportOn(param.source, FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER, context)
}
}
}
private fun FirCallableDeclaration.getOverriddenSymbols(context: CheckerContext): List<FirCallableSymbol<out FirCallableDeclaration>> { private fun FirCallableDeclaration.getOverriddenSymbols(context: CheckerContext): List<FirCallableSymbol<out FirCallableDeclaration>> {
if (!this.isOverride) return emptyList() if (!this.isOverride) return emptyList()
val classSymbol = this.containingClass()?.toSymbol(context.session) as? FirClassSymbol<*> ?: return emptyList() val classSymbol = this.containingClass()?.toSymbol(context.session) as? FirClassSymbol<*> ?: return emptyList()
@@ -190,6 +190,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GENERIC_THROWABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_FUNCTION_AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_FUNCTION_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SELECTOR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_SELECTOR
@@ -1515,6 +1516,8 @@ class FirDefaultErrorMessages {
map.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", SYMBOL) map.put(SUPER_CALL_FROM_PUBLIC_INLINE, "Accessing super members from public-API inline function is deprecated", SYMBOL)
map.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier is allowed only for function parameters of an inline function")
//imports //imports
map.put( map.put(
CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON, CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON,
@@ -358,6 +358,9 @@ object LightTreePositioningStrategies {
val DATA_MODIFIER: LightTreePositioningStrategy = val DATA_MODIFIER: LightTreePositioningStrategy =
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.DATA_KEYWORD)) ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.DATA_KEYWORD))
val INLINE_PARAMETER_MODIFIER: LightTreePositioningStrategy =
ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.NOINLINE_KEYWORD, KtTokens.CROSSINLINE_KEYWORD))
val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark( override fun mark(
node: LighterASTNode, node: LighterASTNode,
@@ -286,4 +286,9 @@ object SourceElementPositioningStrategies {
LightTreePositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT, LightTreePositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT,
PositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT PositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT
) )
val INLINE_PARAMETER_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.INLINE_PARAMETER_MODIFIER,
PositioningStrategies.INLINE_PARAMETER_MODIFIER
)
} }
@@ -496,6 +496,10 @@ object PositioningStrategies {
val INNER_MODIFIER: PositioningStrategy<KtModifierListOwner> = val INNER_MODIFIER: PositioningStrategy<KtModifierListOwner> =
ModifierSetBasedPositioningStrategy(TokenSet.create(KtTokens.INNER_KEYWORD)) ModifierSetBasedPositioningStrategy(TokenSet.create(KtTokens.INNER_KEYWORD))
@JvmField
val INLINE_PARAMETER_MODIFIER: PositioningStrategy<KtModifierListOwner> =
ModifierSetBasedPositioningStrategy(TokenSet.create(KtTokens.NOINLINE_KEYWORD, KtTokens.CROSSINLINE_KEYWORD))
@JvmField @JvmField
val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() { val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() {
override fun mark(element: KtTypeProjection): List<TextRange> { override fun mark(element: KtTypeProjection): List<TextRange> {
@@ -1,20 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
<!NOTHING_TO_INLINE!>inline<!> fun foo(noinline x: Int) {}
<!NOTHING_TO_INLINE!>inline<!> fun bar(y: Int, crossinline x: String) {}
fun gav(noinline x: (Int) -> Unit, crossinline y: (String) -> Int) {}
inline fun correct(noinline x: (Int) -> Unit, crossinline y: (String) -> Int) {}
<!NOTHING_TO_INLINE!>inline<!> fun incompatible(<!INCOMPATIBLE_MODIFIERS!>noinline<!> <!INCOMPATIBLE_MODIFIERS!>crossinline<!> x: () -> String) {}
class FunctionSubtype : () -> Unit {
override fun invoke() {}
}
<!NOTHING_TO_INLINE!>inline<!> fun functionSubtype(
noinline f: FunctionSubtype,
crossinline g: FunctionSubtype
) { }
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
<!NOTHING_TO_INLINE!>inline<!> fun foo(<!ILLEGAL_INLINE_PARAMETER_MODIFIER!>noinline<!> x: Int) {} <!NOTHING_TO_INLINE!>inline<!> fun foo(<!ILLEGAL_INLINE_PARAMETER_MODIFIER!>noinline<!> x: Int) {}
@@ -3205,6 +3205,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token, token,
) )
} }
add(FirErrors.ILLEGAL_INLINE_PARAMETER_MODIFIER) { firDiagnostic ->
IllegalInlineParameterModifierImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON) { firDiagnostic -> add(FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON) { firDiagnostic ->
CannotAllUnderImportFromSingletonImpl( CannotAllUnderImportFromSingletonImpl(
firDiagnostic.a, firDiagnostic.a,
@@ -2236,6 +2236,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = InlinePropertyWithBackingField::class override val diagnosticClass get() = InlinePropertyWithBackingField::class
} }
abstract class IllegalInlineParameterModifier : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = IllegalInlineParameterModifier::class
}
abstract class CannotAllUnderImportFromSingleton : KtFirDiagnostic<KtImportDirective>() { abstract class CannotAllUnderImportFromSingleton : KtFirDiagnostic<KtImportDirective>() {
override val diagnosticClass get() = CannotAllUnderImportFromSingleton::class override val diagnosticClass get() = CannotAllUnderImportFromSingleton::class
abstract val objectName: Name abstract val objectName: Name
@@ -3611,6 +3611,13 @@ internal class InlinePropertyWithBackingFieldImpl(
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
} }
internal class IllegalInlineParameterModifierImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.IllegalInlineParameterModifier(), KtAbstractFirDiagnostic<KtElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class CannotAllUnderImportFromSingletonImpl( internal class CannotAllUnderImportFromSingletonImpl(
override val objectName: Name, override val objectName: Name,
firDiagnostic: FirPsiDiagnostic, firDiagnostic: FirPsiDiagnostic,