Added DoubleBangToIfThenIntention

This commit is contained in:
Zack Grannan
2014-04-14 15:25:39 -07:00
committed by Zalim Bashorov
parent f58e1811e4
commit 8476a790bd
32 changed files with 265 additions and 0 deletions
@@ -342,6 +342,7 @@ fun main(args: Array<String>) {
}
testClass(javaClass<AbstractCodeTransformationTest>()) {
model("intentions/branched/doubleBangToIfThen", testMethod = "doTestDoubleBangToIfThen")
model("intentions/branched/elvisToIfThen", testMethod = "doTestElvisToIfThen")
model("intentions/branched/ifThenToElvis", testMethod = "doTestIfThenToElvis")
model("intentions/branched/safeAccessToIfThen", testMethod = "doTestSafeAccessToIfThen")
@@ -0,0 +1,4 @@
foo(if (maybeSomething != null)
maybeSomething
else
throw NullPointerException("expression 'maybeSomething' must not be null") )
@@ -0,0 +1 @@
foo(maybeSomething!!)
@@ -0,0 +1,6 @@
<html>
<body>
Converts an expression that uses the '!!' operator to an if-then expression that throws a
NullPointerException if the expression is null.
</body>
</html>
+5
View File
@@ -494,6 +494,11 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions.DoubleBangToIfThenIntention</className>
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.jet.plugin.intentions.branchedTransformations.intentions.ElvisToIfThenIntention</className>
<category>Kotlin</category>
@@ -221,6 +221,10 @@ unfold.return.to.when=Replace return with 'when' expression
unfold.return.to.when.family=Replace Return with 'when' Expression
unfold.call.to.when=Replace method call with 'when' expression
unfold.call.to.when.family=Replace Method Call with 'when' Expression
double.bang.to.if.then.exception.text=Expression ''{0}'' must not be null
double.bang.to.if.then.choose.exception=Choose Exception Class
double.bang.to.if.then=Replace '!!' expression with 'if' expression
double.bang.to.if.then.family=Replace '!!' Expression With 'if' 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
@@ -0,0 +1,101 @@
/*
* 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.plugin.intentions.JetSelfTargetingIntention
import com.intellij.openapi.editor.Editor
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.lang.psi.JetPsiUtil
import org.jetbrains.jet.lang.psi.JetPostfixExpression
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStableVariable
import org.jetbrains.jet.plugin.intentions.JetTypeLookupExpression
import com.intellij.codeInsight.template.TemplateEditingAdapter
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.codeInsight.template.Template
import org.jetbrains.jet.plugin.JetBundle
import org.jetbrains.jet.plugin.intentions.branchedTransformations.convertToIfNotNullExpression
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.plugin.intentions.branchedTransformations.introduceValueForCondition
import org.jetbrains.jet.lang.psi.JetThrowExpression
import com.intellij.codeInsight.template.TemplateBuilderImpl
import com.intellij.psi.PsiDocumentManager
import org.apache.commons.lang.StringEscapeUtils.escapeJava
import org.jetbrains.jet.plugin.intentions.branchedTransformations.convertToIfNullExpression
import org.jetbrains.jet.plugin.intentions.branchedTransformations.isStatement
import org.jetbrains.jet.plugin.intentions.branchedTransformations.NULL_PTR_EXCEPTION
import org.jetbrains.jet.plugin.intentions.branchedTransformations.KOTLIN_NULL_PTR_EXCEPTION
public class DoubleBangToIfThenIntention : JetSelfTargetingIntention<JetPostfixExpression>("double.bang.to.if.then", javaClass()) {
override fun isApplicableTo(element: JetPostfixExpression): Boolean =
element.getOperationToken() == JetTokens.EXCLEXCL
override fun applyTo(element: JetPostfixExpression, editor: Editor) {
val project = element.getProject()
val base = checkNotNull(JetPsiUtil.deparenthesize(element.getBaseExpression()), "Base expression cannot be null")
val expressionText = formatForUseInExceptionArgument(base.getText()!!)
val defaultException = JetPsiFactory.createExpression(project, "throw $NULL_PTR_EXCEPTION()")
val isStatement = element.isStatement()
val isStable = base.isStableVariable()
val ifStatement = if (isStatement)
element.convertToIfNullExpression(base, defaultException)
else
element.convertToIfNotNullExpression(base, base, defaultException)
val thrownExpression =
((if (isStatement) ifStatement.getThen() else ifStatement.getElse()) as JetThrowExpression).getThrownExpression()!!
val nullPtrExceptionText = "$NULL_PTR_EXCEPTION(\"%s\")".format(escapeJava(JetBundle.message("double.bang.to.if.then.exception.text", expressionText)))
val kotlinNullPtrExceptionText = "$KOTLIN_NULL_PTR_EXCEPTION()"
val exceptionLookupExpression =
object: JetTypeLookupExpression<String>(listOf(nullPtrExceptionText, kotlinNullPtrExceptionText),
nullPtrExceptionText, JetBundle.message("double.bang.to.if.then.choose.exception")) {
override fun getLookupString(element: String?) = element
override fun getResult(element: String?) = element
}
val manager = TemplateManagerImpl(project)
val builder = TemplateBuilderImpl(thrownExpression)
builder.replaceElement(thrownExpression, exceptionLookupExpression);
PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
editor.getCaretModel().moveToOffset(thrownExpression.getNode()!!.getStartOffset());
manager.startTemplate(editor, builder.buildInlineTemplate()!!, object: TemplateEditingAdapter() {
override fun templateFinished(template: Template?, brokenOff: Boolean) {
if (!isStable && !isStatement) {
ifStatement.introduceValueForCondition(ifStatement.getThen()!!, editor)
}
}
})
}
fun formatForUseInExceptionArgument(expressionText: String): String {
val lines = expressionText.split('\n')
return if (lines.size > 1)
lines.first().trim() + " ..."
else
expressionText.trim()
}
}
@@ -0,0 +1,7 @@
fun foo(): String? {
return "foo"
}
fun main(args: Array<String>) {
foo()<caret>!!
}
@@ -0,0 +1,7 @@
fun foo(): String? {
return "foo"
}
fun main(args: Array<String>) {
if (foo() == null) throw NullPointerException("Expression 'foo()' must not be null")
}
@@ -0,0 +1,7 @@
fun foo(): String? {
return "foo"
}
fun main(args: Array<String>) {
(foo())<caret>!!
}
@@ -0,0 +1,7 @@
fun foo(): String? {
return "foo"
}
fun main(args: Array<String>) {
if (foo() == null) throw NullPointerException("Expression 'foo()' must not be null")
}
@@ -0,0 +1,5 @@
fun main(args: Array<String>) {
doSomething("one")<caret>!!
}
fun doSomething(a: Any): Any? = null
@@ -0,0 +1,5 @@
fun main(args: Array<String>) {
if (doSomething("one") == null) throw NullPointerException("Expression 'doSomething(\"one\")' must not be null")
}
fun doSomething(a: Any): Any? = null
@@ -0,0 +1,7 @@
fun main(args: Array<String>) {
val t = doSomething("one" + 1,
"two",
3 * 4)<caret>!!
}
fun doSomething(vararg a: Any): Any? = null
@@ -0,0 +1,8 @@
fun main(args: Array<String>) {
val any = doSomething("one" + 1,
"two",
3 * 4)
val t = if (any != null) any else throw NullPointerException("Expression 'doSomething(\"one\" + 1, ...' must not be null")
}
fun doSomething(vararg a: Any): Any? = null
@@ -0,0 +1,4 @@
fun main(args: Array<String>) {
val a: String? = "A"
a<caret>!!
}
@@ -0,0 +1,4 @@
fun main(args: Array<String>) {
val a: String? = "A"
if (a == null) throw NullPointerException("Expression 'a' must not be null")
}
@@ -0,0 +1,6 @@
fun main(args: Array<String>) {
var a: String? = "A"
doSomething(a<caret>!!)
}
fun doSomething(a: Any){}
@@ -0,0 +1,7 @@
fun main(args: Array<String>) {
var a: String? = "A"
val s = a
doSomething(if (s != null) s else throw NullPointerException("Expression 'a' must not be null"))
}
fun doSomething(a: Any){}
@@ -0,0 +1,4 @@
fun main(args: Array<String>) {
val foo: String? = "foo"
val t = (foo)<caret>!!
}
@@ -0,0 +1,4 @@
fun main(args: Array<String>) {
val foo: String? = "foo"
val t = if (foo != null) foo else throw NullPointerException("Expression 'foo' must not be null")
}
@@ -0,0 +1,4 @@
val a: String? = "A"
fun main(args: Array<String>) {
a<caret>!!
}
@@ -0,0 +1,4 @@
val a: String? = "A"
fun main(args: Array<String>) {
if (a == null) throw NullPointerException("Expression 'a' must not be null")
}
@@ -0,0 +1,6 @@
val a: String?
get() = ""
fun main(args: Array<String>) {
val x = a<caret>!!
}
@@ -0,0 +1,7 @@
val a: String?
get() = ""
fun main(args: Array<String>) {
val s = a
val x = if (s != null) s else throw NullPointerException("Expression 'a' must not be null")
}
@@ -0,0 +1,4 @@
var a: String? = "A"
fun main(args: Array<String>) {
val t = a<caret>!!
}
@@ -0,0 +1,5 @@
var a: String? = "A"
fun main(args: Array<String>) {
val s = a
val t = if (s != null) s else throw NullPointerException("Expression 'a' must not be null")
}
@@ -0,0 +1,9 @@
var a: String?
get() = ""
set(v) {}
fun main(args: Array<String>) {
doSomething(a<caret>!!)
}
fun doSomething(a: Any){}
@@ -0,0 +1,10 @@
var a: String?
get() = ""
set(v) {}
fun main(args: Array<String>) {
val s = a
doSomething(if (s != null) s else throw NullPointerException("Expression 'a' must not be null"))
}
fun doSomething(a: Any){}
@@ -0,0 +1,4 @@
fun main(args: Array<String>) {
val foo: String? = "foo"
val x = foo<caret>!!
}
@@ -0,0 +1,4 @@
fun main(args: Array<String>) {
val foo: String? = "foo"
val x = if (foo != null) foo else throw NullPointerException("Expression 'foo' must not be null")
}
@@ -38,6 +38,10 @@ import org.junit.Assert;
import java.io.File;
public abstract class AbstractCodeTransformationTest extends LightCodeInsightTestCase {
public void doTestDoubleBangToIfThen(@NotNull String path) throws Exception {
doTestIntention(path, new DoubleBangToIfThenIntention());
}
public void doTestElvisToIfThen(@NotNull String path) throws Exception {
doTestIntention(path, new ElvisToIfThenIntention());
}