diff --git a/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.fir.txt b/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.fir.txt index 72b9a08afce..a5a60533b23 100644 --- a/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.fir.txt @@ -53,3 +53,9 @@ FILE: funInterfaceDeclaration.kt public abstract fun test(): R|kotlin/Unit| } + public abstract interface Test14 : R|kotlin/Any| { + public abstract suspend fun test(): R|kotlin/Unit| + + } + public abstract interface Test15 : R|Test14| { + } diff --git a/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.kt b/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.kt index 2905d35fc64..f9503657621 100644 --- a/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.kt +++ b/compiler/fir/analysis-tests/testData/resolve/funInterfaceDeclaration.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: -SuspendFunctionsInFunInterfaces + fun interface Test1{ fun foo() fun boo() @@ -8,13 +10,13 @@ fun interface Test3 { fun foo() } fun interface Test4{ - fun <T> foo(a: T) + fun foo(a: T) } fun interface Test5{ fun foo(a: Int = 5) } fun interface Test6{ - suspend fun foo() + suspend fun foo() } fun interface Test7{ fun foo() @@ -36,3 +38,8 @@ interface Test11 { fun interface Test12 : Test11 { fun test() } +interface Test14 { + suspend fun test() +} +fun interface Test15 : Test14 + diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt index f81e6743d3c..4aa0f309100 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticData.kt @@ -66,7 +66,7 @@ enum class PositioningStrategy(private val strategy: String? = null) { TYPE_PARAMETERS_LIST, FUN_MODIFIER, SUSPEND_MODIFIER, - FUN_INTERFACE_ABSTRACT_PROPERTY, + FUN_INTERFACE, ; diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index becdd036846..8e438f46e8d 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -500,10 +500,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val FUN_INTERFACES by object : DiagnosticGroup("Fun interfaces") { val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) val FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS by error(PositioningStrategy.FUN_MODIFIER) - val FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES by error(PositioningStrategy.FUN_INTERFACE_ABSTRACT_PROPERTY) - val FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS by error() - val FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE by error() - val FUN_INTERFACE_WITH_SUSPEND_FUNCTION by error(PositioningStrategy.SUSPEND_MODIFIER) + val FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES by error(PositioningStrategy.FUN_INTERFACE) + val FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS by error(PositioningStrategy.FUN_INTERFACE) + val FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE by error(PositioningStrategy.FUN_INTERFACE) + val FUN_INTERFACE_WITH_SUSPEND_FUNCTION by error(PositioningStrategy.FUN_INTERFACE) } val PROPERTIES_AND_ACCESSORS by object : DiagnosticGroup("Properties & accessors") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 82da6970cbe..8c0eef37386 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -311,10 +311,10 @@ object FirErrors { // Fun interfaces val FUN_INTERFACE_CONSTRUCTOR_REFERENCE by error0(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS by error0(SourceElementPositioningStrategies.FUN_MODIFIER) - val FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES by error0(SourceElementPositioningStrategies.FUN_INTERFACE_ABSTRACT_PROPERTY) - val FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS by error0() - val FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE by error0() - val FUN_INTERFACE_WITH_SUSPEND_FUNCTION by error0(SourceElementPositioningStrategies.SUSPEND_MODIFIER) + val FUN_INTERFACE_CANNOT_HAVE_ABSTRACT_PROPERTIES by error0(SourceElementPositioningStrategies.FUN_INTERFACE) + val FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS by error0(SourceElementPositioningStrategies.FUN_INTERFACE) + val FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE by error0(SourceElementPositioningStrategies.FUN_INTERFACE) + val FUN_INTERFACE_WITH_SUSPEND_FUNCTION by error0(SourceElementPositioningStrategies.FUN_INTERFACE) // Properties & accessors val ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS by error2(SourceElementPositioningStrategies.MODALITY_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt index 367a0de2f57..1033678534d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt @@ -63,23 +63,33 @@ object FirFunInterfaceDeclarationChecker : FirRegularClassChecker() { return } + val inFunInterface = abstractFunction.getContainingClass(context) === declaration + when { abstractFunction.typeParameters.isNotEmpty() -> reporter.reportOn( - abstractFunction.typeParameters.first().source, + if (inFunInterface) abstractFunction.source else declaration.source, FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS, context ) abstractFunction.isSuspend -> if (!context.session.languageVersionSettings.supportsFeature(LanguageFeature.SuspendFunctionsInFunInterfaces)) { - reporter.reportOn(abstractFunction.source, FUN_INTERFACE_WITH_SUSPEND_FUNCTION, context) + reporter.reportOn( + if (inFunInterface) abstractFunction.source else declaration.source, + FUN_INTERFACE_WITH_SUSPEND_FUNCTION, + context + ) } } abstractFunction.valueParameters.forEach { if (it.defaultValue != null) { - reporter.reportOn(it.source, FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE, context) + reporter.reportOn( + if (inFunInterface) it.source else declaration.source, + FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE, + context + ) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index e2d45305385..e52b4eb3b72 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -346,6 +346,9 @@ object LightTreePositioningStrategies { val SUSPEND_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.SUSPEND_KEYWORD)) + private val SUSPEND_OR_FUN_MODIFIER: LightTreePositioningStrategy = + ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.SUSPEND_KEYWORD, KtTokens.FUN_KEYWORD)) + val INLINE_OR_VALUE_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(TokenSet.create(KtTokens.INLINE_KEYWORD, KtTokens.VALUE_KEYWORD)) @@ -449,7 +452,7 @@ object LightTreePositioningStrategies { } } - val FUN_INTERFACE_ABSTRACT_PROPERTY: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { + val FUN_INTERFACE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, startOffset: Int, @@ -459,6 +462,13 @@ object LightTreePositioningStrategies { return when (node.tokenType) { KtNodeTypes.CLASS -> FUN_MODIFIER.mark(node, startOffset, endOffset, tree) KtNodeTypes.PROPERTY -> VAL_OR_VAR_NODE.mark(node, startOffset, endOffset, tree) + KtNodeTypes.FUN -> { + if (tree.typeParametersList(node) != null) { + TYPE_PARAMETERS_LIST.mark(node, startOffset, endOffset, tree) + } else { + SUSPEND_OR_FUN_MODIFIER.mark(node, startOffset, endOffset, tree) + } + } else -> DEFAULT.mark(node, startOffset, endOffset, tree) } } @@ -498,7 +508,7 @@ object LightTreePositioningStrategies { when (selector.tokenType) { KtNodeTypes.REFERENCE_EXPRESSION -> return markElement(selector, startOffset, endOffset, tree, node) - KtNodeTypes.CALL_EXPRESSION, KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL,KtNodeTypes.SUPER_TYPE_CALL_ENTRY -> + KtNodeTypes.CALL_EXPRESSION, KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL, KtNodeTypes.SUPER_TYPE_CALL_ENTRY -> return markElement( tree.referenceExpression(selector, locateReferencedName) ?: selector, startOffset, @@ -603,7 +613,7 @@ object LightTreePositioningStrategies { } } - val WHOLE_ELEMENT = object : LightTreePositioningStrategy() { } + val WHOLE_ELEMENT = object : LightTreePositioningStrategy() {} val LONG_LITERAL_SUFFIX = object : LightTreePositioningStrategy() { override fun mark( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt index 1d0a4f5b76b..8da4001479d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt @@ -18,9 +18,9 @@ object SourceElementPositioningStrategies { PositioningStrategies.VAL_OR_VAR_NODE ) - val FUN_INTERFACE_ABSTRACT_PROPERTY = SourceElementPositioningStrategy( - LightTreePositioningStrategies.FUN_INTERFACE_ABSTRACT_PROPERTY, - PositioningStrategies.FUN_INTERFACE_ABSTRACT_PROPERTY + val FUN_INTERFACE = SourceElementPositioningStrategy( + LightTreePositioningStrategies.FUN_INTERFACE, + PositioningStrategies.FUN_INTERFACE ) val COMPANION_OBJECT = SourceElementPositioningStrategy( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 1db9becbb87..b0c17347c72 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -784,12 +784,20 @@ object PositioningStrategies { } @JvmField - val FUN_INTERFACE_ABSTRACT_PROPERTY: PositioningStrategy = object : PositioningStrategy() { + val FUN_INTERFACE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: KtDeclaration): List { return when (element) { is KtClass -> FUN_MODIFIER.mark(element) is KtProperty -> markElement(element.valOrVarKeyword) - else -> error("Expect interface or property, but was " + element.getElementTextWithContext()) + is KtNamedFunction -> { + val typeParameterList = element.typeParameterList + when { + typeParameterList != null -> markElement(typeParameterList) + element.hasModifier(KtTokens.SUSPEND_KEYWORD) -> SUSPEND_MODIFIER.mark(element) + else -> markElement(element.funKeyword ?: element) + } + } + else -> markElement(element) } } } diff --git a/compiler/testData/diagnostics/tests/funInterface/funInterfaceDeclarationCheck.fir.kt b/compiler/testData/diagnostics/tests/funInterface/funInterfaceDeclarationCheck.fir.kt index f9ca9fce267..16e34ac02d3 100644 --- a/compiler/testData/diagnostics/tests/funInterface/funInterfaceDeclarationCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/funInterface/funInterfaceDeclarationCheck.fir.kt @@ -55,7 +55,7 @@ fun interface GoodWithPropAndBase : BaseWithSAM { } fun interface Foo8 { - fun <T> invoke(x: T) + fun invoke(x: T) } fun interface GoodGeneric { @@ -63,10 +63,10 @@ fun interface GoodGeneric { } interface BaseWithGeneric { - fun <T> invoke(x: T) + fun invoke(x: T) } -fun interface Foo9 : BaseWithGeneric +fun interface Foo9 : BaseWithGeneric fun interface GoodExtensionGeneric : GoodGeneric @@ -97,8 +97,8 @@ fun interface WithDefaultValue { } interface BaseWithDefaultValue { - fun invoke(s: String = "") + fun invoke(s: String = "") } -fun interface DeriveDefault : BaseWithDefaultValue +fun interface DeriveDefault : BaseWithDefaultValue diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 28ed97c65b2..5d23f6d9195 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1006,15 +1006,15 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = FunInterfaceCannotHaveAbstractProperties::class } - abstract class FunInterfaceAbstractMethodWithTypeParameters : KtFirDiagnostic() { + abstract class FunInterfaceAbstractMethodWithTypeParameters : KtFirDiagnostic() { override val diagnosticClass get() = FunInterfaceAbstractMethodWithTypeParameters::class } - abstract class FunInterfaceAbstractMethodWithDefaultValue : KtFirDiagnostic() { + abstract class FunInterfaceAbstractMethodWithDefaultValue : KtFirDiagnostic() { override val diagnosticClass get() = FunInterfaceAbstractMethodWithDefaultValue::class } - abstract class FunInterfaceWithSuspendFunction : KtFirDiagnostic() { + abstract class FunInterfaceWithSuspendFunction : KtFirDiagnostic() { override val diagnosticClass get() = FunInterfaceWithSuspendFunction::class } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 724e8585083..b2adfa8560e 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1625,21 +1625,21 @@ internal class FunInterfaceCannotHaveAbstractPropertiesImpl( internal class FunInterfaceAbstractMethodWithTypeParametersImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.FunInterfaceAbstractMethodWithTypeParameters(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.FunInterfaceAbstractMethodWithTypeParameters(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } internal class FunInterfaceAbstractMethodWithDefaultValueImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.FunInterfaceAbstractMethodWithDefaultValue(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.FunInterfaceAbstractMethodWithDefaultValue(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } internal class FunInterfaceWithSuspendFunctionImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken, -) : KtFirDiagnostic.FunInterfaceWithSuspendFunction(), KtAbstractFirDiagnostic { +) : KtFirDiagnostic.FunInterfaceWithSuspendFunction(), KtAbstractFirDiagnostic { override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) }