[kotlin] k2 extract function: rely on compiler checks to detect suspend problems

- otherwise we would need to check enclosing suspend functions manually

^KTIJ-29873 fixed

GitOrigin-RevId: 177244574eea1ac93381da4debab6b368b9eb300
This commit is contained in:
Anna Kozlova
2024-05-12 17:48:41 +00:00
committed by intellij-monorepo-bot
parent 477463f520
commit 786684a1e7
5 changed files with 61 additions and 13 deletions
@@ -1148,6 +1148,11 @@ public abstract class ExtractionTestGenerated extends AbstractExtractionTest {
runTest("testData/refactoring/extractFunction/basic/suspendCall.kt");
}
@TestMetadata("suspendCallInsideSuspendContinuation.kt")
public void testSuspendCallInsideSuspendContinuation() throws Exception {
runTest("testData/refactoring/extractFunction/basic/suspendCallInsideSuspendContinuation.kt");
}
@TestMetadata("suspendCallWithExtractedParameter.kt")
public void testSuspendCallWithExtractedParameter() throws Exception {
runTest("testData/refactoring/extractFunction/basic/suspendCallWithExtractedParameter.kt");
@@ -0,0 +1,13 @@
// PARAM_TYPES: D
// PARAM_DESCRIPTOR: value-parameter d: D defined in test1
fun m(block: suspend () -> Unit) {}
class D {
suspend fun await() {}
}
fun test1(d: D) {
<selection>m {
d.await()
}</selection>
}
@@ -0,0 +1,17 @@
// PARAM_TYPES: D
// PARAM_DESCRIPTOR: value-parameter d: D defined in test1
fun m(block: suspend () -> Unit) {}
class D {
suspend fun await() {}
}
fun test1(d: D) {
__dummyTestFun__(d)
}
private fun __dummyTestFun__(d: D) {
m {
d.await()
}
}
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.analysis.api.components.KtDataFlowExitPointSnapshot
import org.jetbrains.kotlin.analysis.api.components.KtDiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KtFirDiagnostic
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
import org.jetbrains.kotlin.analysis.api.types.KtType
@@ -56,6 +55,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtBreakExpression
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtContinueExpression
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
@@ -224,26 +224,34 @@ internal class ExtractionDataAnalyzer(private val extractionData: ExtractionData
replacementMap = replacementMap,
controlFlow = flow,
returnType = returnType,
modifiers = if (hasSuspendReference(extractionData)) listOf(KtTokens.SUSPEND_KEYWORD) else emptyList(),
modifiers = emptyList(),
optInMarkers = experimentalMarkers.optInMarkers,
annotationClassIds = experimentalMarkers.propagatingMarkerClassIds
)
val config = ExtractionGeneratorConfiguration(
descriptor,
ExtractionGeneratorOptions(inTempFile = true, allowExpressionBody = false)
)
val generatedDeclaration = Generator.generateDeclaration(config, null).declaration
val illegalSuspendInside = analyzeCopy(generatedDeclaration, DanglingFileResolutionMode.PREFER_SELF) {
generatedDeclaration.descendantsOfType<KtExpression>()
.flatMap {
it.getDiagnostics(KtDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS)
.map { it.diagnosticClass }
}
.any { it == KtFirDiagnostic.IllegalSuspendFunctionCall::class || it == KtFirDiagnostic.IllegalSuspendPropertyAccess::class }
}
if (illegalSuspendInside) {
descriptor = descriptor.copy(modifiers = listOf(KtTokens.SUSPEND_KEYWORD))
}
for (analyser in ExtractFunctionDescriptorModifier.EP_NAME.extensionList) {
descriptor = analyser.modifyDescriptor(descriptor)
}
return descriptor
}
private fun hasSuspendReference(extractionData: ExtractionData): Boolean {
return extractionData.expressions
.flatMap { it.descendantsOfType<KtSimpleNameExpression>() }
.any { nameExpression ->
analyze(nameExpression) {
val symbol = nameExpression.mainReference.resolveToSymbol()
symbol is KtFunctionSymbol && symbol.isSuspend
}
}
}
}
private data class ExperimentalMarkers(
@@ -306,6 +306,11 @@ public abstract class K2IntroduceFunctionTestGenerated extends AbstractK2Introdu
runTest("../../idea/tests/testData/refactoring/extractFunction/basic/suspendCall.kt");
}
@TestMetadata("suspendCallInsideSuspendContinuation.kt")
public void testSuspendCallInsideSuspendContinuation() throws Exception {
runTest("../../idea/tests/testData/refactoring/extractFunction/basic/suspendCallInsideSuspendContinuation.kt");
}
@TestMetadata("suspendCallWithExtractedParameter.kt")
public void testSuspendCallWithExtractedParameter() throws Exception {
runTest("../../idea/tests/testData/refactoring/extractFunction/basic/suspendCallWithExtractedParameter.kt");