J2K: parenthesize receiver if needed
#KT-10121 Fixed
This commit is contained in:
+10
-5
@@ -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
-1
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user