Extract Function: Fix detection of suspend calls containing extracted parameters

#KT-16251 Fixed
This commit is contained in:
Alexey Sedunov
2017-02-09 12:18:26 +03:00
parent 574a0e629e
commit add16dec3d
4 changed files with 55 additions and 16 deletions
@@ -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,8 +700,7 @@ 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) }
return AnalysisResult( var descriptor = ExtractableCodeDescriptor(
ExtractableCodeDescriptor(
this, this,
bindingContext, bindingContext,
suggestFunctionNames(returnType), suggestFunctionNames(returnType),
@@ -715,8 +711,21 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
paramsInfo.replacementMap, paramsInfo.replacementMap,
if (messages.isEmpty()) controlFlow else controlFlow.toDefault(), if (messages.isEmpty()) controlFlow else controlFlow.toDefault(),
returnType, returnType,
if (isSuspendExpected) listOf(KtTokens.SUSPEND_KEYWORD) else emptyList() 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(
descriptor,
if (messages.isEmpty()) Status.SUCCESS else Status.NON_CRITICAL_ERROR, if (messages.isEmpty()) Status.SUCCESS else Status.NON_CRITICAL_ERROR,
messages messages
) )
@@ -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>
}
@@ -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()
}
@@ -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");