Extract Function: Fix detection of suspend calls containing extracted parameters
#KT-16251 Fixed
This commit is contained in:
+25
-16
@@ -655,9 +655,6 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
|||||||
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(paramsInfo.errorMessage!!))
|
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(paramsInfo.errorMessage!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
val virtualContext = virtualBlock.analyze(BodyResolveMode.PARTIAL)
|
|
||||||
val isSuspendExpected = virtualContext.diagnostics.all().any { it.factory == Errors.ILLEGAL_SUSPEND_FUNCTION_CALL }
|
|
||||||
|
|
||||||
val messages = ArrayList<ErrorMessage>()
|
val messages = ArrayList<ErrorMessage>()
|
||||||
|
|
||||||
val modifiedVarDescriptorsForControlFlow = HashMap(modifiedVarDescriptorsWithExpressions)
|
val modifiedVarDescriptorsForControlFlow = HashMap(modifiedVarDescriptorsWithExpressions)
|
||||||
@@ -703,20 +700,32 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
|||||||
val receiverParameter = if (receiverCandidates.size == 1 && !options.canWrapInWith) receiverCandidates.first() else null
|
val receiverParameter = if (receiverCandidates.size == 1 && !options.canWrapInWith) receiverCandidates.first() else null
|
||||||
receiverParameter?.let { adjustedParameters.remove(it) }
|
receiverParameter?.let { adjustedParameters.remove(it) }
|
||||||
|
|
||||||
|
var descriptor = ExtractableCodeDescriptor(
|
||||||
|
this,
|
||||||
|
bindingContext,
|
||||||
|
suggestFunctionNames(returnType),
|
||||||
|
getDefaultVisibility(),
|
||||||
|
adjustedParameters.sortedBy { it.name },
|
||||||
|
receiverParameter,
|
||||||
|
paramsInfo.typeParameters.sortedBy { it.originalDeclaration.name!! },
|
||||||
|
paramsInfo.replacementMap,
|
||||||
|
if (messages.isEmpty()) controlFlow else controlFlow.toDefault(),
|
||||||
|
returnType,
|
||||||
|
emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
val body = ExtractionGeneratorConfiguration(
|
||||||
|
descriptor,
|
||||||
|
ExtractionGeneratorOptions(inTempFile = true, allowExpressionBody = false)
|
||||||
|
).generateDeclaration().declaration.getGeneratedBody()
|
||||||
|
val virtualContext = body.analyzeFully()
|
||||||
|
if (virtualContext.diagnostics.all().any { it.factory == Errors.ILLEGAL_SUSPEND_FUNCTION_CALL }) {
|
||||||
|
descriptor = descriptor.copy(modifiers = listOf(KtTokens.SUSPEND_KEYWORD))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return AnalysisResult(
|
return AnalysisResult(
|
||||||
ExtractableCodeDescriptor(
|
descriptor,
|
||||||
this,
|
|
||||||
bindingContext,
|
|
||||||
suggestFunctionNames(returnType),
|
|
||||||
getDefaultVisibility(),
|
|
||||||
adjustedParameters.sortedBy { it.name },
|
|
||||||
receiverParameter,
|
|
||||||
paramsInfo.typeParameters.sortedBy { it.originalDeclaration.name!! },
|
|
||||||
paramsInfo.replacementMap,
|
|
||||||
if (messages.isEmpty()) controlFlow else controlFlow.toDefault(),
|
|
||||||
returnType,
|
|
||||||
if (isSuspendExpected) listOf(KtTokens.SUSPEND_KEYWORD) else emptyList()
|
|
||||||
),
|
|
||||||
if (messages.isEmpty()) Status.SUCCESS else Status.NON_CRITICAL_ERROR,
|
if (messages.isEmpty()) Status.SUCCESS else Status.NON_CRITICAL_ERROR,
|
||||||
messages
|
messages
|
||||||
)
|
)
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// PARAM_TYPES: D
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter d: D defined in test1
|
||||||
|
class D {
|
||||||
|
suspend fun await() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIBLING:
|
||||||
|
suspend fun test1(d: D) {
|
||||||
|
<selection>d.await()</selection>
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// PARAM_TYPES: D
|
||||||
|
// PARAM_DESCRIPTOR: value-parameter d: D defined in test1
|
||||||
|
class D {
|
||||||
|
suspend fun await() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIBLING:
|
||||||
|
suspend fun test1(d: D) {
|
||||||
|
__dummyTestFun__(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun __dummyTestFun__(d: D) {
|
||||||
|
d.await()
|
||||||
|
}
|
||||||
+6
@@ -1102,6 +1102,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
|||||||
doExtractFunctionTest(fileName);
|
doExtractFunctionTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("suspendCallWithExtractedParameter.kt")
|
||||||
|
public void testSuspendCallWithExtractedParameter() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/suspendCallWithExtractedParameter.kt");
|
||||||
|
doExtractFunctionTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("topLevelValUnderSmartCast.kt")
|
@TestMetadata("topLevelValUnderSmartCast.kt")
|
||||||
public void testTopLevelValUnderSmartCast() throws Exception {
|
public void testTopLevelValUnderSmartCast() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/topLevelValUnderSmartCast.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/topLevelValUnderSmartCast.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user