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
|
package org.jetbrains.kotlin.idea.intentions
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
|
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
|
||||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containsInside
|
import org.jetbrains.kotlin.psi.psiUtil.containsInside
|
||||||
|
|
||||||
public class RemoveUnnecessaryParenthesesIntention : SelfTargetingIntention<KtParenthesizedExpression>(javaClass(), "Remove unnecessary parentheses") {
|
public class RemoveUnnecessaryParenthesesIntention : SelfTargetingRangeIntention<KtParenthesizedExpression>(KtParenthesizedExpression::class.java, "Remove unnecessary parentheses") {
|
||||||
override fun isApplicableTo(element: KtParenthesizedExpression, caretOffset: Int): Boolean {
|
override fun applicabilityRange(element: KtParenthesizedExpression): TextRange? {
|
||||||
val expression = element.getExpression() ?: return false
|
element.getExpression() ?: return null
|
||||||
if (!KtPsiUtil.areParenthesesUseless(element)) return false
|
if (!KtPsiUtil.areParenthesesUseless(element)) return null
|
||||||
return !expression.getTextRange().containsInside(caretOffset)
|
return element.getTextRange()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: KtParenthesizedExpression, editor: Editor) {
|
override fun applyTo(element: KtParenthesizedExpression, editor: Editor) {
|
||||||
|
applyTo(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun applyTo(element: KtParenthesizedExpression) {
|
||||||
element.replace(element.getExpression()!!)
|
element.replace(element.getExpression()!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ object J2KPostProcessingRegistrar {
|
|||||||
registerIntentionBasedProcessing(AddOperatorModifierIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(AddOperatorModifierIntention()) { applyTo(it) }
|
||||||
registerIntentionBasedProcessing(ObjectLiteralToLambdaIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(ObjectLiteralToLambdaIntention()) { applyTo(it) }
|
||||||
registerIntentionBasedProcessing(AnonymousFunctionToLambdaIntention()) { applyTo(it) }
|
registerIntentionBasedProcessing(AnonymousFunctionToLambdaIntention()) { applyTo(it) }
|
||||||
|
registerIntentionBasedProcessing(RemoveUnnecessaryParenthesesIntention()) { applyTo(it) }
|
||||||
|
|
||||||
registerDiagnosticBasedProcessing<KtBinaryExpressionWithTypeRHS>(Errors.USELESS_CAST) { element, diagnostic ->
|
registerDiagnosticBasedProcessing<KtBinaryExpressionWithTypeRHS>(Errors.USELESS_CAST) { element, diagnostic ->
|
||||||
val expression = RemoveRightPartOfBinaryExpressionFix(element, "").invoke()
|
val expression = RemoveRightPartOfBinaryExpressionFix(element, "").invoke()
|
||||||
|
|||||||
@@ -63,10 +63,14 @@ class CodeConverter(
|
|||||||
public fun convertExpressions(expressions: List<PsiExpression>): List<Expression>
|
public fun convertExpressions(expressions: List<PsiExpression>): List<Expression>
|
||||||
= expressions.map { convertExpression(it) }
|
= 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
|
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 {
|
public fun convertLocalVariable(variable: PsiLocalVariable): LocalVariable {
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
val isExtension = property.isExtensionDeclaration()
|
val isExtension = property.isExtensionDeclaration()
|
||||||
val propertyAccess = if (isTopLevel) {
|
val propertyAccess = if (isTopLevel) {
|
||||||
if (isExtension)
|
if (isExtension)
|
||||||
QualifiedExpression(codeConverter.convertExpression(arguments.firstOrNull()), propertyName).assignNoPrototype()
|
QualifiedExpression(codeConverter.convertExpression(arguments.firstOrNull(), true), propertyName).assignNoPrototype()
|
||||||
else
|
else
|
||||||
propertyName
|
propertyName
|
||||||
}
|
}
|
||||||
@@ -293,7 +293,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
else if (origin is KtFunction) {
|
else if (origin is KtFunction) {
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
result = if (origin.isExtensionDeclaration()) {
|
result = if (origin.isExtensionDeclaration()) {
|
||||||
val qualifier = codeConverter.convertExpression(arguments.firstOrNull())
|
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), true)
|
||||||
MethodCallExpression.build(qualifier,
|
MethodCallExpression.build(qualifier,
|
||||||
origin.name!!,
|
origin.name!!,
|
||||||
convertArguments(expression, isExtension = true),
|
convertArguments(expression, isExtension = true),
|
||||||
@@ -314,7 +314,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
val resolvedQualifier = (methodExpr.qualifier as? PsiReferenceExpression)?.resolve()
|
val resolvedQualifier = (methodExpr.qualifier as? PsiReferenceExpression)?.resolve()
|
||||||
if (isFacadeClassFromLibrary(resolvedQualifier)) {
|
if (isFacadeClassFromLibrary(resolvedQualifier)) {
|
||||||
result = if (target.isKotlinExtensionFunction()) {
|
result = if (target.isKotlinExtensionFunction()) {
|
||||||
val qualifier = codeConverter.convertExpression(arguments.firstOrNull())
|
val qualifier = codeConverter.convertExpression(arguments.firstOrNull(), true)
|
||||||
MethodCallExpression.build(qualifier,
|
MethodCallExpression.build(qualifier,
|
||||||
methodExpr.referenceName!!,
|
methodExpr.referenceName!!,
|
||||||
convertArguments(expression, isExtension = true),
|
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? {
|
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
|
||||||
if (arguments.size < 2) return null // incorrect call
|
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? {
|
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
|
||||||
if (arguments.isEmpty()) return null // incorrect call
|
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) {
|
STRING_VALUE_OF(JAVA_LANG_STRING, "valueOf", 1) {
|
||||||
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
|
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) {
|
SYSTEM_OUT_PRINTLN(PrintStream::class.java.name, "println", null) {
|
||||||
@@ -412,7 +412,7 @@ private fun convertSystemOutMethodCall(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun CodeConverter.convertToRegex(expression: PsiExpression?): Expression
|
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(
|
private fun addIgnoreCaseArgument(
|
||||||
qualifier: PsiExpression?,
|
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
|
// !specifyLocalVariableTypeByDefault: true
|
||||||
fun foo(b: Boolean) {
|
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
|
//expression
|
||||||
(1 + 2)
|
(1 + 2).foo()
|
||||||
@@ -1 +1 @@
|
|||||||
(1 + 2)
|
(1 + 2).foo()
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
//expression
|
//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);
|
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")
|
@TestMetadata("simpleCall.java")
|
||||||
public void testSimpleCall() throws Exception {
|
public void testSimpleCall() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/simpleCall.java");
|
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/simpleCall.java");
|
||||||
|
|||||||
@@ -3091,6 +3091,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("simpleCall.java")
|
||||||
public void testSimpleCall() throws Exception {
|
public void testSimpleCall() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/simpleCall.java");
|
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/methodCallExpression/simpleCall.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user