Checking for unsupported return's
This commit is contained in:
+18
-2
@@ -23,19 +23,21 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.copied
|
||||
import org.jetbrains.kotlin.idea.codeInliner.CallableUsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.codeInliner.CodeToInlineBuilder
|
||||
import org.jetbrains.kotlin.idea.codeInliner.replaceUsagesInWholeProject
|
||||
import org.jetbrains.kotlin.idea.core.copied
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtReturnExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
@@ -71,8 +73,22 @@ class KotlinInlineFunctionHandler: InlineActionHandler() {
|
||||
val replacement = if (element.hasBlockBody()) {
|
||||
bodyCopy as KtBlockExpression
|
||||
val statements = bodyCopy.statements
|
||||
//TODO: check no other return's!
|
||||
|
||||
val returnStatements = bodyCopy.collectDescendantsOfType<KtReturnExpression> {
|
||||
it.getLabelName().let { it == null || it == element.name }
|
||||
}
|
||||
|
||||
val lastReturn = statements.lastOrNull() as? KtReturnExpression
|
||||
if (returnStatements.any { it != lastReturn }) {
|
||||
val message = RefactoringBundle.getCannotRefactorMessage(
|
||||
if (returnStatements.size > 1)
|
||||
"Inline Function is not supported for functions with multiple return statements."
|
||||
else
|
||||
"Inline Function is not supported for functions with return statements not at the end of the body."
|
||||
)
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, message, "Inline Function", null)
|
||||
}
|
||||
|
||||
if (lastReturn != null) {
|
||||
replacementBuilder.prepareCodeToInline(lastReturn.returnedExpression, statements.dropLast(1), ::analyzeBodyCopy)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// ERROR: Cannot perform refactoring.\nInline Function is not supported for functions with multiple return statements.
|
||||
|
||||
fun <caret>f(p1: Int, p2: Int): Int {
|
||||
if (p1 > 0) {
|
||||
return p2
|
||||
}
|
||||
else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
fun g() {
|
||||
f(1, 2)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// ERROR: Cannot perform refactoring.\nInline Function is not supported for functions with return statements not at the end of the body.
|
||||
|
||||
fun <caret>f(p1: Int, p2: Int): Int {
|
||||
while (true) {
|
||||
if (x() > p1) return@f p2
|
||||
}
|
||||
}
|
||||
|
||||
fun x(): Int = TODO()
|
||||
|
||||
fun g() {
|
||||
f(1, 2)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fun <caret>f(list: List<String>): Boolean {
|
||||
return list.any {
|
||||
if (it.isEmpty()) return@any false
|
||||
it.length < 10
|
||||
}
|
||||
}
|
||||
|
||||
fun g() {
|
||||
println(f(listOf("a", "b")))
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
fun g() {
|
||||
println(listOf("a", "b").any {
|
||||
if (it.isEmpty()) return@any false
|
||||
it.length < 10
|
||||
})
|
||||
}
|
||||
@@ -49,6 +49,18 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MultipleReturns.kt")
|
||||
public void testMultipleReturns() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/function/MultipleReturns.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ReturnNotInTheEnd.kt")
|
||||
public void testReturnNotInTheEnd() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/function/ReturnNotInTheEnd.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UnitReturnType.kt")
|
||||
public void testUnitReturnType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/function/UnitReturnType.kt");
|
||||
@@ -150,6 +162,12 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ReturnFromLambda.kt")
|
||||
public void testReturnFromLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/function/returnAtEnd/ReturnFromLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SafeCall.kt")
|
||||
public void testSafeCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/function/returnAtEnd/SafeCall.kt");
|
||||
|
||||
Reference in New Issue
Block a user