Fold initializer & if to elvis: search for variable usage inside if first #KT-14889 Fixed
This commit is contained in:
+13
-13
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.idea.intentions
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiWhiteSpace
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
|
import com.intellij.psi.search.LocalSearchScope
|
||||||
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.core.replaced
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
import org.jetbrains.kotlin.idea.core.setType
|
import org.jetbrains.kotlin.idea.core.setType
|
||||||
@@ -27,10 +29,7 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.expressionCo
|
|||||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
@@ -107,21 +106,22 @@ class FoldInitializerAndIfToElvisIntention : SelfTargetingRangeIntention<KtIfExp
|
|||||||
} as? KtNameReferenceExpression ?: return null
|
} as? KtNameReferenceExpression ?: return null
|
||||||
|
|
||||||
if (ifExpression.parent !is KtBlockExpression) return null
|
if (ifExpression.parent !is KtBlockExpression) return null
|
||||||
val prevStatement = ifExpression.siblings(forward = false, withItself = false)
|
val prevStatement = (ifExpression.siblings(forward = false, withItself = false)
|
||||||
.firstIsInstanceOrNull<KtExpression>() ?: return null
|
.firstIsInstanceOrNull<KtExpression>() ?: return null) as? KtVariableDeclaration
|
||||||
if (prevStatement !is KtVariableDeclaration) return null
|
prevStatement ?: return null
|
||||||
if (prevStatement.nameAsName != value.getReferencedNameAsName()) return null
|
if (prevStatement.nameAsName != value.getReferencedNameAsName()) return null
|
||||||
val initializer = prevStatement.initializer ?: return null
|
val initializer = prevStatement.initializer ?: return null
|
||||||
val then = ifExpression.then ?: return null
|
val then = ifExpression.then ?: return null
|
||||||
val typeReference = (operationExpression as? KtIsExpression)?.typeReference
|
val typeReference = (operationExpression as? KtIsExpression)?.typeReference
|
||||||
|
|
||||||
if (then is KtBlockExpression) {
|
val statement = if (then is KtBlockExpression) then.statements.singleOrNull() else then
|
||||||
val statement = then.statements.singleOrNull() ?: return null
|
statement ?: return null
|
||||||
return Data(initializer, prevStatement, statement, typeReference)
|
|
||||||
}
|
if (ReferencesSearch.search(prevStatement, LocalSearchScope(statement)).findFirst() != null) {
|
||||||
else {
|
return null
|
||||||
return Data(initializer, prevStatement, then, typeReference)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Data(initializer, prevStatement, statement, typeReference)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiChildRange.withoutLastStatement(): PsiChildRange {
|
private fun PsiChildRange.withoutLastStatement(): PsiChildRange {
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
val s: String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() = Any()
|
||||||
|
|
||||||
|
fun test(): String {
|
||||||
|
val y = foo()
|
||||||
|
<caret>if (y !is A) return y.toString()
|
||||||
|
return y.s
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
val s: String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() = Any()
|
||||||
|
|
||||||
|
fun test(): String {
|
||||||
|
val y = foo()
|
||||||
|
<caret>if (y !is A) return "Expected A: $y"
|
||||||
|
return y.s
|
||||||
|
}
|
||||||
@@ -7397,6 +7397,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UsedInside.kt")
|
||||||
|
public void testUsedInside() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/foldInitializerAndIfToElvis/UsedInside.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UsedInsideInTemplate.kt")
|
||||||
|
public void testUsedInsideInTemplate() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/foldInitializerAndIfToElvis/UsedInsideInTemplate.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Var.kt")
|
@TestMetadata("Var.kt")
|
||||||
public void testVar() throws Exception {
|
public void testVar() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/foldInitializerAndIfToElvis/Var.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/foldInitializerAndIfToElvis/Var.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user