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) {
|
||||
val element = element ?: return
|
||||
val elvis = elvisOrEmpty(notNullNeeded)
|
||||
val elvis = element.elvisOrEmpty(notNullNeeded)
|
||||
val betweenReceiverAndOperation = element.elementsBetweenReceiverAndOperation().joinToString(separator = "") { it.text }
|
||||
val newExpression = KtPsiFactory(element).createExpressionByPattern(
|
||||
"$0$betweenReceiverAndOperation$operation$1$elvis",
|
||||
@@ -54,7 +54,7 @@ abstract class ReplaceCallFix(
|
||||
element.selectorExpression!!
|
||||
)
|
||||
val replacement = element.replace(newExpression)
|
||||
if (notNullNeeded) {
|
||||
if (elvis.isNotEmpty()) {
|
||||
replacement.moveCaretToEnd(editor, project)
|
||||
}
|
||||
}
|
||||
@@ -78,10 +78,10 @@ class ReplaceImplicitReceiverCallFix(
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||
val element = element ?: return
|
||||
val elvis = elvisOrEmpty(notNullNeeded)
|
||||
val elvis = element.elvisOrEmpty(notNullNeeded)
|
||||
val newExpression = KtPsiFactory(element).createExpressionByPattern("this?.$0$elvis", element)
|
||||
val replacement = element.replace(newExpression)
|
||||
if (notNullNeeded) {
|
||||
if (elvis.isNotEmpty()) {
|
||||
replacement.moveCaretToEnd(editor, project)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,14 +21,20 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
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.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
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.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 {
|
||||
val parent = parent
|
||||
|
||||
@@ -43,7 +43,7 @@ class ReplaceInfixOrOperatorCallFix(
|
||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||
val element = element ?: return
|
||||
val psiFactory = KtPsiFactory(file)
|
||||
val elvis = elvisOrEmpty(notNullNeeded)
|
||||
val elvis = element.elvisOrEmpty(notNullNeeded)
|
||||
var replacement: PsiElement? = null
|
||||
when (element) {
|
||||
is KtArrayAccessExpression -> {
|
||||
@@ -83,7 +83,7 @@ class ReplaceInfixOrOperatorCallFix(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notNullNeeded) {
|
||||
if (elvis.isNotEmpty()) {
|
||||
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");
|
||||
}
|
||||
|
||||
@TestMetadata("hasElvis.kt")
|
||||
public void testHasElvis() throws Exception {
|
||||
runTest("idea/testData/quickfix/replaceInfixOrOperatorCall/hasElvis.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("list.kt")
|
||||
public void testList() throws Exception {
|
||||
runTest("idea/testData/quickfix/replaceInfixOrOperatorCall/list.kt");
|
||||
@@ -11098,6 +11103,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
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")
|
||||
public void testInvokeOperator() throws Exception {
|
||||
runTest("idea/testData/quickfix/replaceWithSafeCall/invokeOperator.kt");
|
||||
|
||||
Reference in New Issue
Block a user