Replace with safe call: do not add redundant elvis operator
#KT-34432 Fixed
This commit is contained in:
committed by
Dmitry Gridin
parent
fa0398ffd3
commit
e8effe6727
@@ -46,7 +46,7 @@ abstract class ReplaceCallFix(
|
|||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
val element = element ?: return
|
val element = element ?: return
|
||||||
val elvis = elvisOrEmpty(notNullNeeded)
|
val elvis = element.elvisOrEmpty(notNullNeeded)
|
||||||
val betweenReceiverAndOperation = element.elementsBetweenReceiverAndOperation().joinToString(separator = "") { it.text }
|
val betweenReceiverAndOperation = element.elementsBetweenReceiverAndOperation().joinToString(separator = "") { it.text }
|
||||||
val newExpression = KtPsiFactory(element).createExpressionByPattern(
|
val newExpression = KtPsiFactory(element).createExpressionByPattern(
|
||||||
"$0$betweenReceiverAndOperation$operation$1$elvis",
|
"$0$betweenReceiverAndOperation$operation$1$elvis",
|
||||||
@@ -54,7 +54,7 @@ abstract class ReplaceCallFix(
|
|||||||
element.selectorExpression!!
|
element.selectorExpression!!
|
||||||
)
|
)
|
||||||
val replacement = element.replace(newExpression)
|
val replacement = element.replace(newExpression)
|
||||||
if (notNullNeeded) {
|
if (elvis.isNotEmpty()) {
|
||||||
replacement.moveCaretToEnd(editor, project)
|
replacement.moveCaretToEnd(editor, project)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,10 +78,10 @@ class ReplaceImplicitReceiverCallFix(
|
|||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
val element = element ?: return
|
val element = element ?: return
|
||||||
val elvis = elvisOrEmpty(notNullNeeded)
|
val elvis = element.elvisOrEmpty(notNullNeeded)
|
||||||
val newExpression = KtPsiFactory(element).createExpressionByPattern("this?.$0$elvis", element)
|
val newExpression = KtPsiFactory(element).createExpressionByPattern("this?.$0$elvis", element)
|
||||||
val replacement = element.replace(newExpression)
|
val replacement = element.replace(newExpression)
|
||||||
if (notNullNeeded) {
|
if (elvis.isNotEmpty()) {
|
||||||
replacement.moveCaretToEnd(editor, project)
|
replacement.moveCaretToEnd(editor, project)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,14 +21,20 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
|
|
||||||
fun elvisOrEmpty(notNullNeeded: Boolean): String = if (notNullNeeded) "?:" else ""
|
fun KtExpression.elvisOrEmpty(notNullNeeded: Boolean): String {
|
||||||
|
if (!notNullNeeded) return ""
|
||||||
|
val binaryExpression = getStrictParentOfType<KtBinaryExpression>()
|
||||||
|
return if (binaryExpression?.left == this && binaryExpression.operationToken == KtTokens.ELVIS) "" else "?:"
|
||||||
|
}
|
||||||
|
|
||||||
fun KtExpression.shouldHaveNotNullType(): Boolean {
|
fun KtExpression.shouldHaveNotNullType(): Boolean {
|
||||||
val parent = parent
|
val parent = parent
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class ReplaceInfixOrOperatorCallFix(
|
|||||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
val element = element ?: return
|
val element = element ?: return
|
||||||
val psiFactory = KtPsiFactory(file)
|
val psiFactory = KtPsiFactory(file)
|
||||||
val elvis = elvisOrEmpty(notNullNeeded)
|
val elvis = element.elvisOrEmpty(notNullNeeded)
|
||||||
var replacement: PsiElement? = null
|
var replacement: PsiElement? = null
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtArrayAccessExpression -> {
|
is KtArrayAccessExpression -> {
|
||||||
@@ -83,7 +83,7 @@ class ReplaceInfixOrOperatorCallFix(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notNullNeeded) {
|
if (elvis.isNotEmpty()) {
|
||||||
replacement?.moveCaretToEnd(editor, project)
|
replacement?.moveCaretToEnd(editor, project)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// "Replace with safe (?.) call" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(list: List<String>?) {
|
||||||
|
var s = ""
|
||||||
|
s = list[0]<caret> ?: ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// "Replace with safe (?.) call" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo(list: List<String>?) {
|
||||||
|
var s = ""
|
||||||
|
s = list?.get(0) ?: ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Replace with safe (?.) call" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
var a = foo()<caret>.length ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): String? {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Replace with safe (?.) call" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
var a = foo()?.length ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): String? {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// "Replace with safe (this?.) call" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
fun foo(a: String?) {
|
||||||
|
a.run {
|
||||||
|
i = <caret>length ?: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// "Replace with safe (this?.) call" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
fun foo(a: String?) {
|
||||||
|
a.run {
|
||||||
|
i = this?.length ?: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10901,6 +10901,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
runTest("idea/testData/quickfix/replaceInfixOrOperatorCall/callExpression.kt");
|
runTest("idea/testData/quickfix/replaceInfixOrOperatorCall/callExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("hasElvis.kt")
|
||||||
|
public void testHasElvis() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/replaceInfixOrOperatorCall/hasElvis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("list.kt")
|
@TestMetadata("list.kt")
|
||||||
public void testList() throws Exception {
|
public void testList() throws Exception {
|
||||||
runTest("idea/testData/quickfix/replaceInfixOrOperatorCall/list.kt");
|
runTest("idea/testData/quickfix/replaceInfixOrOperatorCall/list.kt");
|
||||||
@@ -11098,6 +11103,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
runTest("idea/testData/quickfix/replaceWithSafeCall/functionCall.kt");
|
runTest("idea/testData/quickfix/replaceWithSafeCall/functionCall.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("hasElvis.kt")
|
||||||
|
public void testHasElvis() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/replaceWithSafeCall/hasElvis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("hasElvis2.kt")
|
||||||
|
public void testHasElvis2() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/replaceWithSafeCall/hasElvis2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("invokeOperator.kt")
|
@TestMetadata("invokeOperator.kt")
|
||||||
public void testInvokeOperator() throws Exception {
|
public void testInvokeOperator() throws Exception {
|
||||||
runTest("idea/testData/quickfix/replaceWithSafeCall/invokeOperator.kt");
|
runTest("idea/testData/quickfix/replaceWithSafeCall/invokeOperator.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user