J2K: parenthesize receiver if needed

#KT-10121 Fixed
This commit is contained in:
Natalia Ukhorskaya
2015-12-15 16:16:16 +03:00
parent a520e93b5b
commit 3f7b8554dd
15 changed files with 55 additions and 20 deletions
@@ -17,18 +17,23 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.psiUtil.containsInside
public class RemoveUnnecessaryParenthesesIntention : SelfTargetingIntention<KtParenthesizedExpression>(javaClass(), "Remove unnecessary parentheses") {
override fun isApplicableTo(element: KtParenthesizedExpression, caretOffset: Int): Boolean {
val expression = element.getExpression() ?: return false
if (!KtPsiUtil.areParenthesesUseless(element)) return false
return !expression.getTextRange().containsInside(caretOffset)
public class RemoveUnnecessaryParenthesesIntention : SelfTargetingRangeIntention<KtParenthesizedExpression>(KtParenthesizedExpression::class.java, "Remove unnecessary parentheses") {
override fun applicabilityRange(element: KtParenthesizedExpression): TextRange? {
element.getExpression() ?: return null
if (!KtPsiUtil.areParenthesesUseless(element)) return null
return element.getTextRange()
}
override fun applyTo(element: KtParenthesizedExpression, editor: Editor) {
applyTo(element)
}
fun applyTo(element: KtParenthesizedExpression) {
element.replace(element.getExpression()!!)
}
}
@@ -64,6 +64,7 @@ object J2KPostProcessingRegistrar {
registerIntentionBasedProcessing(AddOperatorModifierIntention()) { applyTo(it) }
registerIntentionBasedProcessing(ObjectLiteralToLambdaIntention()) { applyTo(it) }
registerIntentionBasedProcessing(AnonymousFunctionToLambdaIntention()) { applyTo(it) }
registerIntentionBasedProcessing(RemoveUnnecessaryParenthesesIntention()) { applyTo(it) }
registerDiagnosticBasedProcessing<KtBinaryExpressionWithTypeRHS>(Errors.USELESS_CAST) { element, diagnostic ->
val expression = RemoveRightPartOfBinaryExpressionFix(element, "").invoke()
@@ -63,10 +63,14 @@ class CodeConverter(
public fun convertExpressions(expressions: List<PsiExpression>): List<Expression>
= expressions.map { convertExpression(it) }
public fun convertExpression(expression: PsiExpression?): Expression {
public fun convertExpression(expression: PsiExpression?, shouldParenthesize: Boolean = false): Expression {
if (expression == null) return Expression.Empty
return expressionConverter.convertExpression(expression, this).assignPrototype(expression)
val converted = expressionConverter.convertExpression(expression, this).assignPrototype(expression)
if (shouldParenthesize) {
return ParenthesizedExpression(converted).assignNoPrototype()
}
return converted
}
public fun convertLocalVariable(variable: PsiLocalVariable): LocalVariable {
@@ -268,7 +268,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val isExtension = property.isExtensionDeclaration()
val propertyAccess = if (isTopLevel) {
if (isExtension)
QualifiedExpression(codeConverter.convertExpression(arguments.firstOrNull()), propertyName).assignNoPrototype()
QualifiedExpression(codeConverter.convertExpression(arguments.firstOrNull(), true), propertyName).assignNoPrototype()
else
propertyName
}
@@ -293,7 +293,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
else if (origin is KtFunction) {
if (isTopLevel) {
result = if (origin.isExtensionDeclaration()) {
val qualifier = codeConverter.convertExpression(arguments.firstOrNull())
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), true)
MethodCallExpression.build(qualifier,
origin.name!!,
convertArguments(expression, isExtension = true),
@@ -314,7 +314,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val resolvedQualifier = (methodExpr.qualifier as? PsiReferenceExpression)?.resolve()
if (isFacadeClassFromLibrary(resolvedQualifier)) {
result = if (target.isKotlinExtensionFunction()) {
val qualifier = codeConverter.convertExpression(arguments.firstOrNull())
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), true)
MethodCallExpression.build(qualifier,
methodExpr.referenceName!!,
convertArguments(expression, isExtension = true),
@@ -306,7 +306,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
if (arguments.size < 2) return null // incorrect call
return MethodCallExpression.build(codeConverter.convertExpression(arguments[1]), "format", codeConverter.convertExpressions(listOf(arguments[0]) + arguments.drop(2)), emptyList(), false)
return MethodCallExpression.build(codeConverter.convertExpression(arguments[1], true), "format", codeConverter.convertExpressions(listOf(arguments[0]) + arguments.drop(2)), emptyList(), false)
}
},
@@ -319,7 +319,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
if (arguments.isEmpty()) return null // incorrect call
return MethodCallExpression.build(codeConverter.convertExpression(arguments.first()), "format", codeConverter.convertExpressions(arguments.drop(1)), emptyList(), false)
return MethodCallExpression.build(codeConverter.convertExpression(arguments.first(), true), "format", codeConverter.convertExpressions(arguments.drop(1)), emptyList(), false)
}
},
@@ -347,7 +347,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
STRING_VALUE_OF(JAVA_LANG_STRING, "valueOf", 1) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(codeConverter.convertExpression(arguments.single()), "toString", emptyList(), emptyList(), false)
= MethodCallExpression.build(codeConverter.convertExpression(arguments.single(), true), "toString", emptyList(), emptyList(), false)
},
SYSTEM_OUT_PRINTLN(PrintStream::class.java.name, "println", null) {
@@ -412,7 +412,7 @@ private fun convertSystemOutMethodCall(
}
private fun CodeConverter.convertToRegex(expression: PsiExpression?): Expression
= MethodCallExpression.build(convertExpression(expression), "toRegex", emptyList(), emptyList(), false).assignNoPrototype()
= MethodCallExpression.build(convertExpression(expression, true), "toRegex", emptyList(), emptyList(), false).assignNoPrototype()
private fun addIgnoreCaseArgument(
qualifier: PsiExpression?,
@@ -1 +1 @@
assert((boolMethod()))
assert(boolMethod())
@@ -0,0 +1,7 @@
//method
public static void adjust(String name, int maxLen) {
String.format("%-" + maxLen + "s", name);
String.valueOf(1 + 1);
"a".split("\\s+" + "\\s+", 2)
kotlinApi.KotlinApiKt.extensionFunction(1 + 1)
}
@@ -0,0 +1,6 @@
fun adjust(name: String, maxLen: Int) {
("%-" + maxLen + "s").format(name)
(1 + 1).toString()
"a".split(("\\s+" + "\\s+").toRegex(), 2).toTypedArray()
(1 + 1).extensionFunction()
}
@@ -1,4 +1,4 @@
// !specifyLocalVariableTypeByDefault: true
fun foo(b: Boolean) {
val s: String? = (if (b) "abc" else null)
val s: String? = if (b) "abc" else null
}
@@ -1,2 +1,2 @@
//expression
(1 + 2)
(1 + 2).foo()
@@ -1 +1 @@
(1 + 2)
(1 + 2).foo()
@@ -1,2 +1,2 @@
//expression
(str.toString() + "abc")
(str.toString() + "abc").foo()
@@ -1 +1 @@
(str.toString() + "abc")
(str.toString() + "abc").foo()
@@ -3091,6 +3091,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
doTest(fileName);
}
@TestMetadata("parameterToReceiver.java")
public void testParameterToReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/parameterToReceiver.java");
doTest(fileName);
}
@TestMetadata("simpleCall.java")
public void testSimpleCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/simpleCall.java");
@@ -3091,6 +3091,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
doTest(fileName);
}
@TestMetadata("parameterToReceiver.java")
public void testParameterToReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/parameterToReceiver.java");
doTest(fileName);
}
@TestMetadata("simpleCall.java")
public void testSimpleCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/simpleCall.java");