From 1f720c855984297b51641672cb694e05b179dbd0 Mon Sep 17 00:00:00 2001 From: Zack Grannan Date: Sun, 2 Mar 2014 17:45:13 -0800 Subject: [PATCH] Added safeAccessToIfThen intention --- .../jet/generators/tests/GenerateTests.kt | 1 + .../after.kt.template | 1 + .../before.kt.template | 1 + .../description.html | 5 ++ idea/src/META-INF/plugin.xml | 5 ++ .../jetbrains/jet/plugin/JetBundle.properties | 4 +- .../intentions/SafeAccessToIfThenIntention.kt | 53 +++++++++++++++++++ .../safeAccessToIfThen/binaryExpressionLhs.kt | 5 ++ .../binaryExpressionLhs.kt.after | 6 +++ .../safeAccessToIfThen/callExpression.kt | 4 ++ .../callExpression.kt.after | 5 ++ .../callExpressionParens.kt | 4 ++ .../callExpressionParens.kt.after | 5 ++ .../customGetterAsReceiver.kt | 11 ++++ .../customGetterAsReceiver.kt.after | 12 +++++ .../safeAccessToIfThen/localValAsReceiver.kt | 4 ++ .../localValAsReceiver.kt.after | 4 ++ .../safeAccessToIfThen/localValLhs.kt | 4 ++ .../safeAccessToIfThen/localValLhs.kt.after | 4 ++ .../safeAccessToIfThen/localVarLhs.kt | 5 ++ .../safeAccessToIfThen/localVarLhs.kt.after | 6 +++ .../resultAssignedToLocalVal.kt | 4 ++ .../resultAssignedToLocalVal.kt.after | 4 ++ .../safeAccessAsFunctionArgument.kt | 8 +++ .../safeAccessAsFunctionArgument.kt.after | 8 +++ .../simpleNameExpression.kt | 4 ++ .../simpleNameExpression.kt.after | 4 ++ .../simpleNameExpressionInParens.kt | 4 ++ .../simpleNameExpressionInParens.kt.after | 4 ++ .../simplePropertyAsReceiver.kt | 9 ++++ .../simplePropertyAsReceiver.kt.after | 9 ++++ .../simplePropertyAsReceiver2.kt | 13 +++++ .../simplePropertyAsReceiver2.kt.after | 13 +++++ .../simplePropertyAsReceiver3.kt | 12 +++++ .../simplePropertyAsReceiver3.kt.after | 12 +++++ .../safeAccessToIfThen/topLevelVal.kt | 4 ++ .../safeAccessToIfThen/topLevelVal.kt.after | 4 ++ .../topLevelValCustomGetter.kt | 6 +++ .../topLevelValCustomGetter.kt.after | 7 +++ .../safeAccessToIfThen/topLevelVar.kt | 4 ++ .../safeAccessToIfThen/topLevelVar.kt.after | 5 ++ .../topLevelVarCustomGetter.kt | 7 +++ .../topLevelVarCustomGetter.kt.after | 8 +++ .../safeAccessToIfThen/usedAsFunctionRhs.kt | 4 ++ .../usedAsFunctionRhs.kt.after | 4 ++ .../usedAsResultOfCheckedIf.kt | 4 ++ .../usedAsResultOfCheckedIf.kt.after | 4 ++ .../safeAccessToIfThen/usedAsReturnValue.kt | 7 +++ .../usedAsReturnValue.kt.after | 7 +++ .../usedInUncheckedIfExpression.kt | 6 +++ .../usedInUncheckedIfExpression.kt.after | 6 +++ ...QualifiedExpressionNotFirst.before.Main.kt | 5 +- .../AbstractCodeTransformationTest.java | 4 ++ 53 files changed, 349 insertions(+), 4 deletions(-) create mode 100644 idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/description.html create mode 100644 idea/src/org/jetbrains/jet/plugin/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt.after create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt create mode 100644 idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt.after diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index b7d38404a83..f93e2ea2cbb 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -349,6 +349,7 @@ fun main(args: Array) { testClass(javaClass()) { model("intentions/branched/elvisToIfThen", testMethod = "doTestElvisToIfThen") model("intentions/branched/ifThenToElvis", testMethod = "doTestIfThenToElvis") + model("intentions/branched/safeAccessToIfThen", testMethod = "doTestSafeAccessToIfThen") model("intentions/branched/folding/ifToAssignment", testMethod = "doTestFoldIfToAssignment") model("intentions/branched/folding/ifToReturn", testMethod = "doTestFoldIfToReturn") model("intentions/branched/folding/ifToReturnAsymmetrically", testMethod = "doTestFoldIfToReturnAsymmetrically") diff --git a/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/after.kt.template b/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/after.kt.template new file mode 100644 index 00000000000..1ff0c342acb --- /dev/null +++ b/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/after.kt.template @@ -0,0 +1 @@ +val result = if (maybeSomething != null) maybeSomething.perform(something) else null diff --git a/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/before.kt.template b/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/before.kt.template new file mode 100644 index 00000000000..693c07d2393 --- /dev/null +++ b/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/before.kt.template @@ -0,0 +1 @@ +val result = maybeSomething?.perform(something) diff --git a/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/description.html b/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/description.html new file mode 100644 index 00000000000..766b05cc875 --- /dev/null +++ b/idea/resources/intentionDescriptions/SafeAccessToIfThenIntention/description.html @@ -0,0 +1,5 @@ + + + Converts an expression that uses an safe-access operator to an if-then expression + + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 055b91cc3bb..6d3a746ea38 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -484,6 +484,11 @@ Kotlin + + org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions.SafeAccessToIfThenIntention + Kotlin + + org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions.IfToWhenIntention Kotlin diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 088f1b16a62..97ebf1843a5 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -222,11 +222,9 @@ unfold.call.to.when.family=Replace Method Call with 'when' Expression elvis.to.if.then=Replace elvis expression with 'if' expression elvis.to.if.then.family=Replace Elvis Expression With 'if' Expression if.then.to.elvis=Replace 'if' expression with elvis expression -if.then.to.elvis.family=Replace 'if' Expression With Elvis Expression +if.then.to.elvis.family=Replace 'if' expression With Elvis Expression safe.access.to.if.then=Replace safe access expression with 'if' expression safe.access.to.if.then.family=Replace Safe Access Expression With 'if' Expression -if.then.to.safe.access=Replace 'if' expression with safe access expression -if.then.to.safe.access.family=Replace 'if' Expression with Safe Access Expression if.to.when=Replace 'if' with 'when' if.to.when.family=Replace 'if' with 'when' when.to.if=Replace 'when' with 'if' diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt b/idea/src/org/jetbrains/jet/plugin/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt new file mode 100644 index 00000000000..8c483ff6099 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/intentions/branchedTransformations/intentions/SafeAccessToIfThenIntention.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions + +import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression +import org.jetbrains.jet.plugin.intentions.JetSelfTargetingIntention +import com.intellij.openapi.editor.Editor +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.psi.JetPsiUtil +import org.jetbrains.jet.lang.psi.JetBinaryExpression +import org.jetbrains.jet.plugin.intentions.branchedTransformations.convertToIfNotNullExpression +import org.jetbrains.jet.plugin.intentions.branchedTransformations.introduceValueForCondition +import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression +import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement +import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStableVariable + +public class SafeAccessToIfThenIntention : JetSelfTargetingIntention("safe.access.to.if.then", javaClass()) { + override fun isApplicableTo(element: JetSafeQualifiedExpression): Boolean = true + + override fun applyTo(element: JetSafeQualifiedExpression, editor: Editor) { + val receiver = JetPsiUtil.deparenthesize(element.getReceiverExpression())!! + val selector = JetPsiUtil.deparenthesize(element.getSelectorExpression()) + + val receiverIsStable = receiver.isStableVariable() + + val receiverTemplate = if (receiver is JetBinaryExpression) "(%s)" else "%s" + val receiverAsString = receiverTemplate.format(receiver.getText()) + val dotQualifiedExpression = JetPsiFactory.createExpression(element.getProject(), "${receiverAsString}.${selector!!.getText()}") + + val elseClause = if (element.isStatement()) null else JetPsiFactory.createExpression(element.getProject(), "null") + val ifExpression = element.convertToIfNotNullExpression(receiver, dotQualifiedExpression, elseClause) + + if (!receiverIsStable) { + val valueToExtract = (ifExpression.getThen() as JetDotQualifiedExpression).getReceiverExpression() + ifExpression.introduceValueForCondition(valueToExtract, editor) + } + } +} + diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt b/idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt new file mode 100644 index 00000000000..50461c5b885 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt @@ -0,0 +1,5 @@ +fun main(args: Array) { + val x: String? = null + val y: String? = "Hello" + val z = (x ?: y)?.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt.after new file mode 100644 index 00000000000..122322899c0 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/binaryExpressionLhs.kt.after @@ -0,0 +1,6 @@ +fun main(args: Array) { + val x: String? = null + val y: String? = "Hello" + val s = x ?: y + val z = if (s != null) s.length else null +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt b/idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt new file mode 100644 index 00000000000..e6d6a17999d --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt @@ -0,0 +1,4 @@ +fun foo(): String? = "foo" +fun main(args: Array) { + foo()?.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt.after new file mode 100644 index 00000000000..36fd675f675 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/callExpression.kt.after @@ -0,0 +1,5 @@ +fun foo(): String? = "foo" +fun main(args: Array) { + val s = foo() + if (s != null) s.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt b/idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt new file mode 100644 index 00000000000..d15f4d385e6 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt @@ -0,0 +1,4 @@ +fun foo(): String? = "foo" +fun main(args: Array) { + (foo())?.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt.after new file mode 100644 index 00000000000..36fd675f675 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/callExpressionParens.kt.after @@ -0,0 +1,5 @@ +fun foo(): String? = "foo" +fun main(args: Array) { + val s = foo() + if (s != null) s.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt b/idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt new file mode 100644 index 00000000000..0ca9a7ff744 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt @@ -0,0 +1,11 @@ +class Foo { + val b: String? + get() { + print("I have side effects") + return "Foo" + } +} +fun main(args: Array) { + val a = Foo() + println(a.b?.length) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt.after new file mode 100644 index 00000000000..0b73b8baa0c --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/customGetterAsReceiver.kt.after @@ -0,0 +1,12 @@ +class Foo { + val b: String? + get() { + print("I have side effects") + return "Foo" + } +} +fun main(args: Array) { + val a = Foo() + val s = a.b + println(if (s != null) s.length else null) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt b/idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt new file mode 100644 index 00000000000..eeba12cf5a0 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + val x: String? = "abc" + x?.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt.after new file mode 100644 index 00000000000..837ffd1f033 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/localValAsReceiver.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + val x: String? = "abc" + if (x != null) x.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt b/idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt new file mode 100644 index 00000000000..53516b6f062 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + val a: String? = "A" + println(a?.length) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt.after new file mode 100644 index 00000000000..6549fd41d83 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/localValLhs.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + val a: String? = "A" + println(if (a != null) a.length else null) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt b/idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt new file mode 100644 index 00000000000..20fceba6361 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt @@ -0,0 +1,5 @@ +fun main(args: Array) { + var a: String? = "A" + println(a?.length) +} + diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt.after new file mode 100644 index 00000000000..38d8108d209 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/localVarLhs.kt.after @@ -0,0 +1,6 @@ +fun main(args: Array) { + var a: String? = "A" + val s = a + println(if (s != null) s.length else null) +} + diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt b/idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt new file mode 100644 index 00000000000..5e04bb3e59e --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + val x: String? = "abc" + val y = x?.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt.after new file mode 100644 index 00000000000..328d3df4a49 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/resultAssignedToLocalVal.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + val x: String? = "abc" + val y = if (x != null) x.length else null +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt b/idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt new file mode 100644 index 00000000000..64de5978d03 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt @@ -0,0 +1,8 @@ +fun f(s: Int?) { + println(s) +} + +fun main(args: Array) { + val x: String? = "foo" + f(x?.length) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt.after new file mode 100644 index 00000000000..d126f1c8113 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/safeAccessAsFunctionArgument.kt.after @@ -0,0 +1,8 @@ +fun f(s: Int?) { + println(s) +} + +fun main(args: Array) { + val x: String? = "foo" + f(if (x != null) x.length else null) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt new file mode 100644 index 00000000000..a9e79d8e66e --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + val foo: String? = "foo" + foo?.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt.after new file mode 100644 index 00000000000..7edbddc06a4 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpression.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + val foo: String? = "foo" + if (foo != null) foo.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt new file mode 100644 index 00000000000..362ca42d6d5 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + val foo: String? = "foo" + (foo)?.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt.after new file mode 100644 index 00000000000..7edbddc06a4 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simpleNameExpressionInParens.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + val foo: String? = "foo" + if (foo != null) foo.length() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt new file mode 100644 index 00000000000..d17769e94ce --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt @@ -0,0 +1,9 @@ +class B { + val c = "ab" +} + +fun main(args: Array) { + val a: B? = B() + val x = a?.c +} + diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt.after new file mode 100644 index 00000000000..042b3ffa9aa --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver.kt.after @@ -0,0 +1,9 @@ +class B { + val c = "ab" +} + +fun main(args: Array) { + val a: B? = B() + val x = if (a != null) a.c else null +} + diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt new file mode 100644 index 00000000000..529f5178dc8 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt @@ -0,0 +1,13 @@ +class B { + val c = C() +} + +class C { + val d = "bc" +} + +fun main(args: Array) { + val a: B? = B() + val x = a?.c?.d +} + diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt.after new file mode 100644 index 00000000000..d9dbad64814 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver2.kt.after @@ -0,0 +1,13 @@ +class B { + val c = C() +} + +class C { + val d = "bc" +} + +fun main(args: Array) { + val a: B? = B() + val x = (if (a != null) a.c else null)?.d +} + diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt new file mode 100644 index 00000000000..ef5f1913eb5 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt @@ -0,0 +1,12 @@ +class B { + val c = C() +} + +class C { + val d = "bc" +} + +fun main(args: Array) { + val a: B? = B() + val x = a?.c?.d +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt.after new file mode 100644 index 00000000000..b8bb7cc654f --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/simplePropertyAsReceiver3.kt.after @@ -0,0 +1,12 @@ +class B { + val c = C() +} + +class C { + val d = "bc" +} + +fun main(args: Array) { + val a: B? = B() + val x = if (a?.c != null) a?.c.d else null +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt new file mode 100644 index 00000000000..69c79de0530 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt @@ -0,0 +1,4 @@ +val a: String? = "A" +fun main(args: Array) { + println(a?.length) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt.after new file mode 100644 index 00000000000..f39eeae1a84 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVal.kt.after @@ -0,0 +1,4 @@ +val a: String? = "A" +fun main(args: Array) { + println(if (a != null) a.length else null) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt new file mode 100644 index 00000000000..8f95e5baa74 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt @@ -0,0 +1,6 @@ +val a: String? + get() = "" + +fun main(args: Array) { + println(a?.length) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt.after new file mode 100644 index 00000000000..9e365779cb3 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelValCustomGetter.kt.after @@ -0,0 +1,7 @@ +val a: String? + get() = "" + +fun main(args: Array) { + val s = a + println(if (s != null) s.length else null) +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt new file mode 100644 index 00000000000..36f93c10162 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt @@ -0,0 +1,4 @@ +var a: String? = "A" +fun main(args: Array) { + a?.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt.after new file mode 100644 index 00000000000..3210c752652 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVar.kt.after @@ -0,0 +1,5 @@ +var a: String? = "A" +fun main(args: Array) { + val s = a + if (s != null) s.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt new file mode 100644 index 00000000000..07ceabf3af2 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt @@ -0,0 +1,7 @@ +var a: String? + get() = "" + set(v) {} + +fun main(args: Array) { + a?.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt.after new file mode 100644 index 00000000000..fcf29763a12 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/topLevelVarCustomGetter.kt.after @@ -0,0 +1,8 @@ +var a: String? + get() = "" + set(v) {} + +fun main(args: Array) { + val s = a + if (s != null) s.length +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt new file mode 100644 index 00000000000..82c1bd1734f --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt @@ -0,0 +1,4 @@ +fun foo(arg: String?): Int? = arg?.length +fun main(args: Array) { + foo("bar") +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt.after new file mode 100644 index 00000000000..2be935e3ce5 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsFunctionRhs.kt.after @@ -0,0 +1,4 @@ +fun foo(arg: String?): Int? = if (arg != null) arg.length else null +fun main(args: Array) { + foo("bar") +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt new file mode 100644 index 00000000000..8fac3f4df26 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + val foo: String? = "foo" + val y = if (true) foo?.length() else null +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt.after new file mode 100644 index 00000000000..9aa3f0e4882 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsResultOfCheckedIf.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + val foo: String? = "foo" + val y = if (true) if (foo != null) foo.length() else null else null +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt new file mode 100644 index 00000000000..ab67857d882 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt @@ -0,0 +1,7 @@ +fun doSth(): String? { + val x?: String = "abc" + return x?.reverse() +} +fun main(args: Array) { + val y = doSth() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt.after new file mode 100644 index 00000000000..71f1d7219a5 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedAsReturnValue.kt.after @@ -0,0 +1,7 @@ +fun doSth(): String? { + val x?: String = "abc" + return if (x != null) x.reverse() else null +} +fun main(args: Array) { + val y = doSth() +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt b/idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt new file mode 100644 index 00000000000..3c803c93d22 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt @@ -0,0 +1,6 @@ +fun main(args: Array) { + val foo: String? = "foo" + if (true) { + foo?.length() + } +} diff --git a/idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt.after b/idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt.after new file mode 100644 index 00000000000..6531d3ce562 --- /dev/null +++ b/idea/testData/intentions/branched/safeAccessToIfThen/usedInUncheckedIfExpression.kt.after @@ -0,0 +1,6 @@ +fun main(args: Array) { + val foo: String? = "foo" + if (true) { + if (foo != null) foo.length() + } +} diff --git a/idea/testData/quickfix/autoImports/noImportInSafeQualifiedExpressionNotFirst.before.Main.kt b/idea/testData/quickfix/autoImports/noImportInSafeQualifiedExpressionNotFirst.before.Main.kt index 12443030b22..7c0b0a41c35 100644 --- a/idea/testData/quickfix/autoImports/noImportInSafeQualifiedExpressionNotFirst.before.Main.kt +++ b/idea/testData/quickfix/autoImports/noImportInSafeQualifiedExpressionNotFirst.before.Main.kt @@ -1,6 +1,9 @@ // "class com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFixBase" "false" // ERROR: Unresolved reference: SomeTest +// ACTION: Edit intention settings +// ACTION: Replace safe access expression with 'if' expression +// ACTION: Disable 'Replace Safe Access Expression With 'if' Expression' package testing -val x = testing?.SomeTest() \ No newline at end of file +val x = testing?.SomeTest() diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java index a660ca3f1c4..6736e32c7cb 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java @@ -39,6 +39,10 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes doTestIntention(path, new IfThenToElvisIntention()); } + public void doTestSafeAccessToIfThen(@NotNull String path) throws Exception { + doTestIntention(path, new SafeAccessToIfThenIntention()); + } + public void doTestFoldIfToAssignment(@NotNull String path) throws Exception { doTestIntention(path, new FoldIfToAssignmentIntention()); }