ConvertAssertToIfWithThrowIntention: smaller availability range + minor code refactorings
This commit is contained in:
@@ -333,8 +333,6 @@ insert.explicit.type.arguments=Add explicit type arguments
|
|||||||
insert.explicit.type.arguments.family=Add Explicit Type Arguments
|
insert.explicit.type.arguments.family=Add Explicit Type Arguments
|
||||||
remove.explicit.type.arguments=Remove explicit type arguments
|
remove.explicit.type.arguments=Remove explicit type arguments
|
||||||
remove.explicit.type.arguments.family=Remove Explicit Type Arguments
|
remove.explicit.type.arguments.family=Remove Explicit Type Arguments
|
||||||
convert.assert.to.if.with.throw=Replace 'assert' with 'if' statement
|
|
||||||
convert.assert.to.if.with.throw.family=Replace 'assert' with 'if' Statement
|
|
||||||
convert.if.with.throw.to.assert=Replace 'if' with 'assert' statement
|
convert.if.with.throw.to.assert=Replace 'if' with 'assert' statement
|
||||||
convert.if.with.throw.to.assert.family=Replace 'if' with 'assert' Statement
|
convert.if.with.throw.to.assert.family=Replace 'if' with 'assert' Statement
|
||||||
make.type.explicit.in.lambda=Make types explicit in lambda
|
make.type.explicit.in.lambda=Make types explicit in lambda
|
||||||
|
|||||||
+46
-68
@@ -17,121 +17,99 @@
|
|||||||
package org.jetbrains.kotlin.idea.intentions
|
package org.jetbrains.kotlin.idea.intentions
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import org.jetbrains.kotlin.psi.JetCallExpression
|
|
||||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
|
||||||
import org.jetbrains.kotlin.psi.JetPrefixExpression
|
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
|
||||||
import org.jetbrains.kotlin.psi.JetCallableReferenceExpression
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import kotlin.properties.Delegates
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.psi.JetIfExpression
|
|
||||||
import org.jetbrains.kotlin.psi.JetDotQualifiedExpression
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|
||||||
import org.jetbrains.kotlin.psi.JetBlockExpression
|
|
||||||
import org.jetbrains.kotlin.psi.JetThrowExpression
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
|
||||||
public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingOffsetIndependentIntention<JetCallExpression>(
|
public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Replace 'assert' with 'if' statement") {
|
||||||
"convert.assert.to.if.with.throw", javaClass()) {
|
override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean {
|
||||||
|
val callee = element.getCalleeExpression() ?: return false
|
||||||
|
if (callee.getText() != "assert") return false
|
||||||
|
if (!callee.getTextRange().containsOffset(caretOffset)) return false
|
||||||
|
|
||||||
private var messageIsAFunction : Boolean by Delegates.notNull()
|
val argumentSize = element.getValueArguments().size()
|
||||||
|
|
||||||
override fun isApplicableTo(element: JetCallExpression): Boolean {
|
|
||||||
if (element.getCalleeExpression()?.getText() != "assert") return false
|
|
||||||
|
|
||||||
val argumentSize = element.getValueArguments().size
|
|
||||||
if (argumentSize !in 1..2) return false
|
if (argumentSize !in 1..2) return false
|
||||||
if (element.getFunctionLiteralArguments().size == 1 && argumentSize == 1) return false
|
if (element.getFunctionLiteralArguments().size() == 1 && argumentSize == 1) return false
|
||||||
|
|
||||||
val context = element.analyze()
|
|
||||||
val resolvedCall = element.getResolvedCall(context)
|
|
||||||
if (resolvedCall == null) return false
|
|
||||||
|
|
||||||
val valParameters = resolvedCall.getResultingDescriptor().getValueParameters()
|
|
||||||
if (valParameters.size > 1) {
|
|
||||||
messageIsAFunction = (valParameters[1].getType() != KotlinBuiltIns.getInstance().getAnyType())
|
|
||||||
} else {
|
|
||||||
messageIsAFunction = false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return false
|
||||||
return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).asString() == "kotlin.assert"
|
return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).asString() == "kotlin.assert"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: JetCallExpression, editor: Editor) {
|
override fun applyTo(element: JetCallExpression, editor: Editor) {
|
||||||
val args = element.getValueArguments()
|
val args = element.getValueArguments()
|
||||||
val conditionText = args[0]?.getArgumentExpression()?.getText() ?: return
|
val conditionText = args[0]?.getArgumentExpression()?.getText() ?: return
|
||||||
val lambdas = element.getFunctionLiteralArguments()
|
val functionLiterals = element.getFunctionLiteralArguments()
|
||||||
|
val messageIsFunction = messageIsFunction(element)
|
||||||
|
|
||||||
val psiFactory = JetPsiFactory(element)
|
val psiFactory = JetPsiFactory(element)
|
||||||
val messageExpr =
|
|
||||||
if (args.size == 2) {
|
|
||||||
args[1]?.getArgumentExpression()
|
|
||||||
}
|
|
||||||
else if (lambdas.isNotEmpty()) {
|
|
||||||
element.getFunctionLiteralArguments()[0]
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
psiFactory.createExpression("\"Assertion failed\"")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messageExpr == null) return
|
val messageExpr = when {
|
||||||
|
args.size() == 2 -> args[1]?.getArgumentExpression() ?: return
|
||||||
|
functionLiterals.isNotEmpty() -> functionLiterals.first()
|
||||||
|
else -> psiFactory.createExpression("\"Assertion failed\"")
|
||||||
|
}
|
||||||
|
|
||||||
val replaced = replaceWithIfThenThrowExpression(element)
|
val ifExpression = replaceWithIfThenThrowExpression(element)
|
||||||
|
|
||||||
ShortenReferences.DEFAULT.process(replaced.getThen()!!)
|
// shorten java.lang.AssertionError
|
||||||
|
ShortenReferences.DEFAULT.process(ifExpression.getThen()!!)
|
||||||
|
|
||||||
fun replaceMessage() {
|
fun replaceMessage() {
|
||||||
val thrownExpression = ((replaced.getThen() as JetBlockExpression).getStatements().first() as JetThrowExpression).getThrownExpression()
|
val thrownExpression = ((ifExpression.getThen() as JetBlockExpression).getStatements().single() as JetThrowExpression).getThrownExpression()
|
||||||
val assertionErrorCall = if (thrownExpression is JetCallExpression) {
|
val assertionErrorCall = if (thrownExpression is JetCallExpression)
|
||||||
thrownExpression: JetCallExpression
|
thrownExpression
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
(thrownExpression as JetDotQualifiedExpression).getSelectorExpression() as JetCallExpression
|
(thrownExpression as JetDotQualifiedExpression).getSelectorExpression() as JetCallExpression
|
||||||
}
|
|
||||||
|
|
||||||
val message = psiFactory.createExpression(
|
val message = psiFactory.createExpression(
|
||||||
if (messageIsAFunction && messageExpr is JetCallableReferenceExpression) {
|
if (messageIsFunction && messageExpr is JetCallableReferenceExpression) {
|
||||||
"${messageExpr.getCallableReference().getText()}()"
|
messageExpr.getCallableReference().getText() + "()"
|
||||||
}
|
}
|
||||||
else if (messageIsAFunction) {
|
else if (messageIsFunction) {
|
||||||
"${messageExpr.getText()}()"
|
messageExpr.getText() + "()"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
"${messageExpr.getText()}"
|
messageExpr.getText()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
assertionErrorCall.getValueArguments().single()!!.getArgumentExpression()!!.replace(message)
|
assertionErrorCall.getValueArguments().single().getArgumentExpression()!!.replace(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun replaceCondition() {
|
fun replaceCondition() {
|
||||||
val ifCondition = replaced.getCondition() as JetPrefixExpression
|
val ifCondition = ifExpression.getCondition() as JetPrefixExpression
|
||||||
ifCondition.getBaseExpression()!!.replace(psiFactory.createExpression(conditionText))
|
ifCondition.getBaseExpression()!!.replace(psiFactory.createExpression(conditionText))
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceCondition()
|
replaceCondition()
|
||||||
replaceMessage()
|
replaceMessage()
|
||||||
|
|
||||||
simplifyConditionIfPossible(editor, replaced)
|
simplifyConditionIfPossible(ifExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun simplifyConditionIfPossible(editor: Editor, replaced: JetIfExpression) {
|
private fun messageIsFunction(callExpr: JetCallExpression): Boolean {
|
||||||
val condition = replaced.getCondition() as JetPrefixExpression
|
val resolvedCall = callExpr.getResolvedCall(callExpr.analyze()) ?: return false
|
||||||
|
val valParameters = resolvedCall.getResultingDescriptor().getValueParameters()
|
||||||
|
return valParameters.size() > 1 && valParameters[1].getType() != KotlinBuiltIns.getInstance().getAnyType()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun simplifyConditionIfPossible(ifExpression: JetIfExpression) {
|
||||||
|
val condition = ifExpression.getCondition() as JetPrefixExpression
|
||||||
val simplifier = SimplifyNegatedBinaryExpressionIntention()
|
val simplifier = SimplifyNegatedBinaryExpressionIntention()
|
||||||
if (simplifier.isApplicableTo(condition)) {
|
if (simplifier.isApplicableTo(condition)) {
|
||||||
simplifier.applyTo(condition, editor)
|
simplifier.applyTo(condition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun replaceWithIfThenThrowExpression(original: JetCallExpression): JetIfExpression {
|
private fun replaceWithIfThenThrowExpression(original: JetCallExpression): JetIfExpression {
|
||||||
val replacement = JetPsiFactory(original).createExpression("if (!true) { throw java.lang.AssertionError(\"\") }") as JetIfExpression
|
val replacement = JetPsiFactory(original).createExpression("if (!true) { throw java.lang.AssertionError(\"\") }") as JetIfExpression
|
||||||
val parent = original.getParent()
|
val parent = original.getParent()
|
||||||
return if (parent is JetDotQualifiedExpression) {
|
return if (parent is JetDotQualifiedExpression)
|
||||||
parent.replaced(replacement)
|
parent.replaced(replacement)
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
original.replaced(replacement)
|
original.replaced(replacement)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user