Refine expression kind definition in postfix templates
- Do not treat if without else as values - Some statements aren't contained in block (see tests) #KT-14107 Fixed #KT-14110 Fixed
This commit is contained in:
+11
-3
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.idea.intentions.negate
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -128,16 +129,23 @@ private class KtExpressionPostfixTemplateSelector(
|
|||||||
// Both KtLambdaExpression and KtFunctionLiteral have the same offset, so we add only one of them -> KtLambdaExpression
|
// Both KtLambdaExpression and KtFunctionLiteral have the same offset, so we add only one of them -> KtLambdaExpression
|
||||||
if (it is KtFunctionLiteral) return@Condition false
|
if (it is KtFunctionLiteral) return@Condition false
|
||||||
|
|
||||||
if (statementsOnly && it.parent !is KtBlockExpression) return@Condition false
|
val context by lazy { it.analyze(BodyResolveMode.PARTIAL_FOR_COMPLETION) }
|
||||||
|
|
||||||
|
if (statementsOnly && it.parent !is KtBlockExpression && !it.isUsedAsStatement(context)) return@Condition false
|
||||||
if (checkCanBeUsedAsValue && !it.canBeUsedAsValue()) return@Condition false
|
if (checkCanBeUsedAsValue && !it.canBeUsedAsValue()) return@Condition false
|
||||||
|
|
||||||
typePredicate == null || it.getType(it.analyze(BodyResolveMode.PARTIAL_FOR_COMPLETION))?.let { typePredicate(it) } ?: false
|
typePredicate == null || it.getType(context)?.let { typePredicate(it) } ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtExpression.canBeUsedAsValue() =
|
private fun KtExpression.canBeUsedAsValue() =
|
||||||
!KtPsiUtil.isAssignment(this) &&
|
!KtPsiUtil.isAssignment(this) &&
|
||||||
!this.isNamedDeclaration &&
|
!this.isNamedDeclaration &&
|
||||||
this !is KtLoopExpression
|
this !is KtLoopExpression &&
|
||||||
|
// if's only with else may be treated as expressions
|
||||||
|
!isIfWithoutElse
|
||||||
|
|
||||||
|
private val KtExpression.isIfWithoutElse: Boolean
|
||||||
|
get() = (this is KtIfExpression && this.elseKeyword == null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExpressions(context: PsiElement, document: Document, offset: Int): List<PsiElement> {
|
override fun getExpressions(context: PsiElement, document: Document, offset: Int): List<PsiElement> {
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
for (i in 1..9)
|
||||||
|
i.return<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
for (i in 1..9)
|
||||||
|
return i
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo(x: Int, y: Int) {
|
||||||
|
if (x > y)
|
||||||
|
x.sout<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo(x: Int, y: Int) {
|
||||||
|
if (x > y)
|
||||||
|
println(x)
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
for (i in 1..9)
|
||||||
|
i.sout<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
for (i in 1..9)
|
||||||
|
println(i)
|
||||||
|
}
|
||||||
+18
@@ -137,12 +137,30 @@ public class PostfixTemplateProviderTestGenerated extends AbstractPostfixTemplat
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("returnFromLoop.kt")
|
||||||
|
public void testReturnFromLoop() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/returnFromLoop.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("sout.kt")
|
@TestMetadata("sout.kt")
|
||||||
public void testSout() throws Exception {
|
public void testSout() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/sout.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/sout.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("soutInIf.kt")
|
||||||
|
public void testSoutInIf() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/soutInIf.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("soutInLoop.kt")
|
||||||
|
public void testSoutInLoop() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/soutInLoop.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("try.kt")
|
@TestMetadata("try.kt")
|
||||||
public void testTry() throws Exception {
|
public void testTry() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/try.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/postfix/try.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user