[FIR] Report UNSUPPORTED_SUSPEND_TEST

^KT-60002 Fixed
This commit is contained in:
Nikolay Lunyak
2023-08-07 11:43:53 +03:00
committed by Space Team
parent 223e590dcd
commit 921db9f8d4
11 changed files with 69 additions and 21 deletions
@@ -82,6 +82,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.UNSUPPORTED_SUSPEND_TEST) { firDiagnostic ->
UnsupportedSuspendTestImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.NEW_INFERENCE_ERROR) { firDiagnostic ->
NewInferenceErrorImpl(
firDiagnostic.a,
@@ -103,6 +103,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
val unsupportedFeature: Pair<LanguageFeature, LanguageVersionSettings>
}
interface UnsupportedSuspendTest : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = UnsupportedSuspendTest::class
}
interface NewInferenceError : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = NewInferenceError::class
val error: String
@@ -105,6 +105,11 @@ internal class UnsupportedFeatureImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.UnsupportedFeature
internal class UnsupportedSuspendTestImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.UnsupportedSuspendTest
internal class NewInferenceErrorImpl(
override val error: String,
firDiagnostic: KtPsiDiagnostic,
@@ -54,6 +54,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val UNSUPPORTED_FEATURE by error<PsiElement> {
parameter<Pair<LanguageFeature, LanguageVersionSettings>>("unsupportedFeature")
}
val UNSUPPORTED_SUSPEND_TEST by error<PsiElement>()
val NEW_INFERENCE_ERROR by error<PsiElement> {
parameter<String>("error")
}
@@ -119,6 +119,7 @@ object FirErrors {
// Meta-errors
val UNSUPPORTED by error1<PsiElement, String>()
val UNSUPPORTED_FEATURE by error1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>>()
val UNSUPPORTED_SUSPEND_TEST by error0<PsiElement>()
val NEW_INFERENCE_ERROR by error1<PsiElement, String>()
// Miscellaneous
@@ -48,6 +48,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirFunctionParameterChecker,
FirFunctionReturnChecker,
FirInlineDeclarationChecker,
FirSuspendLimitationsChecker,
)
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.StandardClassIds
object FirSuspendLimitationsChecker : FirFunctionChecker() {
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isSuspend) {
return
}
if (declaration.annotations.any { it.isKotlinTestAnnotation(context.session) }) {
declaration.getModifier(KtTokens.SUSPEND_KEYWORD)?.let {
reporter.reportOn(it.source, FirErrors.UNSUPPORTED_SUSPEND_TEST, context)
}
}
}
private fun FirAnnotation.isKotlinTestAnnotation(session: FirSession): Boolean {
val nonExpandedType = annotationTypeRef.coneType as? ConeClassLikeType
return nonExpandedType?.lookupTag?.classId == StandardClassIds.Annotations.Test
|| toAnnotationClassId(session) == StandardClassIds.Annotations.Test
}
}
@@ -607,6 +607,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_SUSPEND_TEST
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
@@ -675,6 +676,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
// Meta-errors
map.put(UNSUPPORTED, "Unsupported [{0}]", TO_STRING)
map.put(UNSUPPORTED_FEATURE, "{0}", LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.UNSUPPORTED))
map.put(UNSUPPORTED_SUSPEND_TEST, "'suspend' functions annotated with @kotlin.test.Test are unsupported")
map.put(NEW_INFERENCE_ERROR, "New inference error [{0}]", STRING)
// Miscellaneous
@@ -1,21 +0,0 @@
// ALLOW_KOTLIN_PACKAGE
// SKIP_TXT
// FILE: test.kt
package kotlin.test
annotation class IrrelevantClass
public typealias Test = IrrelevantClass
// FILE: main.kt
import kotlin.test.Test
class A {
@Test
suspend fun test() {}
}
@Test
suspend fun test() {}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ALLOW_KOTLIN_PACKAGE
// SKIP_TXT
// FILE: test.kt
@@ -21,6 +21,7 @@ object StandardClassIds {
val BASE_ENUMS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("enums"))
val BASE_CONTRACTS_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("contracts"))
val BASE_CONCURRENT_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("concurrent"))
val BASE_TEST_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("test"))
val builtInsPackages = setOf(
BASE_KOTLIN_PACKAGE,
@@ -175,6 +176,8 @@ object StandardClassIds {
val Volatile = "Volatile".concurrentId()
val Test = "Test".testId()
val RawTypeAnnotation = "RawType".internalIrId()
val FlexibleNullability = "FlexibleNullability".internalIrId()
val FlexibleMutability = "FlexibleMutability".internalIrId()
@@ -268,6 +271,8 @@ private fun String.coroutinesId() = ClassId(StandardClassIds.BASE_COROUTINES_PAC
private fun String.enumsId() = ClassId(StandardClassIds.BASE_ENUMS_PACKAGE, Name.identifier(this))
private fun String.concurrentId() = ClassId(StandardClassIds.BASE_CONCURRENT_PACKAGE, Name.identifier(this))
private fun String.testId() = ClassId(StandardClassIds.BASE_TEST_PACKAGE, Name.identifier(this))
private fun String.callableId(packageName: FqName) = CallableId(packageName, Name.identifier(this))
private fun String.callableId(classId: ClassId) = CallableId(classId, Name.identifier(this))