Forbid suspend functions annotated with @kotlin.test.Test
#KT-26200 Fixed
This commit is contained in:
@@ -116,7 +116,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
DynamicReceiverChecker,
|
||||
DelegationChecker(),
|
||||
KClassWithIncorrectTypeArgumentChecker,
|
||||
SuspendOperatorsCheckers,
|
||||
SuspendLimitationsChecker,
|
||||
InlineClassDeclarationChecker,
|
||||
PropertiesWithBackingFieldsInsideInlineClass(),
|
||||
AnnotationClassTargetAndRetentionChecker(),
|
||||
|
||||
+19
-3
@@ -18,12 +18,17 @@ package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.abbreviationFqName
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.types.getAbbreviation
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object SuspendOperatorsCheckers : DeclarationChecker {
|
||||
object SuspendLimitationsChecker : DeclarationChecker {
|
||||
private val UNSUPPORTED_OPERATOR_NAMES = setOf(
|
||||
OperatorNameConventions.CONTAINS,
|
||||
OperatorNameConventions.GET, OperatorNameConventions.SET,
|
||||
@@ -31,11 +36,22 @@ object SuspendOperatorsCheckers : DeclarationChecker {
|
||||
)
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor is FunctionDescriptor && descriptor.isSuspend && descriptor.isOperator &&
|
||||
descriptor.name in UNSUPPORTED_OPERATOR_NAMES) {
|
||||
if (descriptor !is FunctionDescriptor || !descriptor.isSuspend) return
|
||||
|
||||
if (descriptor.isOperator && descriptor.name in UNSUPPORTED_OPERATOR_NAMES) {
|
||||
declaration.modifierList?.getModifier(KtTokens.OPERATOR_KEYWORD)?.let {
|
||||
context.trace.report(Errors.UNSUPPORTED.on(it, "suspend operator \"${descriptor.name}\""))
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor.annotations.any(AnnotationDescriptor::isKotlinTestAnnotation)) {
|
||||
declaration.modifierList?.getModifier(KtTokens.SUSPEND_KEYWORD)?.let {
|
||||
context.trace.report(Errors.UNSUPPORTED.on(it, "suspend test functions"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val KOTLIN_TEST_TEST_FQNAME = FqName("kotlin.test.Test")
|
||||
private fun AnnotationDescriptor.isKotlinTestAnnotation() =
|
||||
fqName == KOTLIN_TEST_TEST_FQNAME || abbreviationFqName == KOTLIN_TEST_TEST_FQNAME
|
||||
@@ -0,0 +1,20 @@
|
||||
// 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
|
||||
<!UNSUPPORTED!>suspend<!> fun test() {}
|
||||
}
|
||||
|
||||
@Test
|
||||
<!UNSUPPORTED!>suspend<!> fun test() {}
|
||||
+5
@@ -1653,6 +1653,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendOverridability.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendTest.kt")
|
||||
public void testSuspendTest() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendTest.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspesionInDefaultValue.kt")
|
||||
public void testSuspesionInDefaultValue() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspesionInDefaultValue.kt");
|
||||
|
||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+5
@@ -1653,6 +1653,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendOverridability.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspendTest.kt")
|
||||
public void testSuspendTest() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendTest.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("suspesionInDefaultValue.kt")
|
||||
public void testSuspesionInDefaultValue() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspesionInDefaultValue.kt");
|
||||
|
||||
+6
-3
@@ -18,21 +18,24 @@ package org.jetbrains.kotlin.descriptors.annotations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.getAbbreviation
|
||||
|
||||
interface AnnotationDescriptor {
|
||||
val type: KotlinType
|
||||
|
||||
val fqName: FqName?
|
||||
get() = annotationClass?.takeUnless(ErrorUtils::isError)?.fqNameUnsafe?.takeIf(FqNameUnsafe::isSafe)?.toSafe()
|
||||
get() = annotationClass?.takeUnless(ErrorUtils::isError)?.fqNameOrNull()
|
||||
|
||||
val allValueArguments: Map<Name, ConstantValue<*>>
|
||||
|
||||
val source: SourceElement
|
||||
}
|
||||
|
||||
val AnnotationDescriptor.abbreviationFqName: FqName?
|
||||
get() = type.getAbbreviation()?.constructor?.declarationDescriptor?.fqNameOrNull()
|
||||
|
||||
@@ -221,7 +221,7 @@ val DeclarationDescriptor.parents: Sequence<DeclarationDescriptor>
|
||||
val CallableMemberDescriptor.propertyIfAccessor: CallableMemberDescriptor
|
||||
get() = if (this is PropertyAccessorDescriptor) correspondingProperty else this
|
||||
|
||||
fun CallableDescriptor.fqNameOrNull(): FqName? = fqNameUnsafe.takeIf { it.isSafe }?.toSafe()
|
||||
fun DeclarationDescriptor.fqNameOrNull(): FqName? = fqNameUnsafe.takeIf { it.isSafe }?.toSafe()
|
||||
|
||||
fun CallableMemberDescriptor.firstOverridden(
|
||||
useOriginal: Boolean = false,
|
||||
|
||||
Reference in New Issue
Block a user