KT-7525 Don't suggest to replace 'get' call with index operator for static method calls (inspection & intention)
KT-5322 super.get issues a "Replace 'get' call with index operator" inspection #KT-7525 Fixed #KT-5322 Fixed
This commit is contained in:
@@ -121,3 +121,10 @@ fun JetExpression.isExitStatement(): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
// returns false for call of super, static method or method from package
|
||||
fun JetQualifiedExpression.isReceiverExpressionWithValue(): Boolean {
|
||||
val receiver = getReceiverExpression()
|
||||
if (receiver is JetSuperExpression) return false
|
||||
return analyze().getType(receiver) != null
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.idea.intentions.conventionNameCalls
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.calleeName
|
||||
import org.jetbrains.kotlin.idea.intentions.toResolvedCall
|
||||
import org.jetbrains.kotlin.idea.intentions.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.JetDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
@@ -32,11 +29,15 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
public class ReplaceCallWithBinaryOperatorIntention : JetSelfTargetingRangeIntention<JetDotQualifiedExpression>(javaClass(), "Replace call with binary operator") {
|
||||
override fun applicabilityRange(element: JetDotQualifiedExpression): TextRange? {
|
||||
val operation = operation(element.calleeName) ?: return null
|
||||
|
||||
val resolvedCall = element.toResolvedCall() ?: return null
|
||||
if (!resolvedCall.getStatus().isSuccess()) return null
|
||||
if (resolvedCall.getCall().getTypeArgumentList() != null) return null
|
||||
val argument = resolvedCall.getCall().getValueArguments().singleOrNull() ?: return null
|
||||
if ((resolvedCall.getArgumentMapping(argument) as ArgumentMatch).valueParameter.getIndex() != 0) return null
|
||||
|
||||
if (!element.isReceiverExpressionWithValue()) return null
|
||||
|
||||
setText("Replace with '$operation' operator")
|
||||
return element.callExpression!!.getCalleeExpression()!!.getTextRange()
|
||||
}
|
||||
|
||||
+5
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.calleeName
|
||||
import org.jetbrains.kotlin.idea.intentions.isReceiverExpressionWithValue
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.JetDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
@@ -30,9 +31,13 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
public class ReplaceCallWithUnaryOperatorIntention : JetSelfTargetingRangeIntention<JetDotQualifiedExpression>(javaClass(), "Replace call with unary operator") {
|
||||
override fun applicabilityRange(element: JetDotQualifiedExpression): TextRange? {
|
||||
val operation = operation(element.calleeName) ?: return null
|
||||
|
||||
val call = element.callExpression ?: return null
|
||||
if (call.getTypeArgumentList() != null) return null
|
||||
if (!call.getValueArguments().isEmpty()) return null
|
||||
|
||||
if (!element.isReceiverExpressionWithValue()) return null
|
||||
|
||||
setText("Replace with '$operation' operator")
|
||||
return call.getCalleeExpression()!!.getTextRange()
|
||||
}
|
||||
|
||||
+5
-4
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.idea.intentions.conventionNameCalls
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.calleeName
|
||||
import org.jetbrains.kotlin.idea.intentions.toResolvedCall
|
||||
import org.jetbrains.kotlin.idea.intentions.*
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
@@ -31,6 +28,7 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
public class ReplaceContainsIntention : JetSelfTargetingRangeIntention<JetDotQualifiedExpression>(javaClass(), "Replace 'contains' call with 'in' operator") {
|
||||
override fun applicabilityRange(element: JetDotQualifiedExpression): TextRange? {
|
||||
if (element.calleeName != OperatorConventions.CONTAINS.asString()) return null
|
||||
|
||||
val resolvedCall = element.toResolvedCall() ?: return null
|
||||
if (!resolvedCall.getStatus().isSuccess()) return null
|
||||
val argument = resolvedCall.getCall().getValueArguments().singleOrNull() ?: return null
|
||||
@@ -39,6 +37,9 @@ public class ReplaceContainsIntention : JetSelfTargetingRangeIntention<JetDotQua
|
||||
val target = resolvedCall.getResultingDescriptor()
|
||||
val returnType = target.getReturnType() ?: return null
|
||||
if (!target.builtIns.isBooleanOrSubtype(returnType)) return null
|
||||
|
||||
if (!element.isReceiverExpressionWithValue()) return null
|
||||
|
||||
return element.callExpression!!.getCalleeExpression()!!.getTextRange()
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.calleeName
|
||||
import org.jetbrains.kotlin.idea.intentions.isReceiverExpressionWithValue
|
||||
import org.jetbrains.kotlin.psi.JetDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
import org.jetbrains.kotlin.psi.buildExpression
|
||||
@@ -33,9 +34,13 @@ public class ReplaceGetIntention : JetSelfTargetingRangeIntention<JetDotQualifie
|
||||
if (element.calleeName != "get") return null
|
||||
val call = element.callExpression ?: return null
|
||||
if (call.getTypeArgumentList() != null) return null
|
||||
|
||||
val arguments = call.getValueArguments()
|
||||
if (arguments.isEmpty()) return null
|
||||
if (arguments.any { it.isNamed() }) return null
|
||||
|
||||
if (!element.isReceiverExpressionWithValue()) return null
|
||||
|
||||
return call.getCalleeExpression()!!.getTextRange()
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun plus(s: String): C = C()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
C.<caret>plus("x")
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun plus(s: String): C = C()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
C + "x"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
open class Base {
|
||||
open fun plus(s: String) = ""
|
||||
}
|
||||
|
||||
class C : Base() {
|
||||
override fun plus(s: String): String {
|
||||
return super.<caret>plus(s)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun minus(): C = C()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
C.<caret>minus()
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun minus(): C = C()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
-C
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
open class Base {
|
||||
open fun minus() = this
|
||||
}
|
||||
|
||||
class C : Base() {
|
||||
override fun minus(): Base {
|
||||
return super.<caret>minus()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun contains(s: String) = true
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
C.<caret>contains("x")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun contains(s: String) = true
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
"x" in C
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
open class Base {
|
||||
open fun contains(s: String) = true
|
||||
}
|
||||
|
||||
class C : Base() {
|
||||
override fun contains(s: String): Boolean {
|
||||
return super.<caret>contains(s)
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -52,4 +52,13 @@
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Explicit 'get'</problem_class>
|
||||
<description>Replace 'get' call with index operator</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
<problem>
|
||||
<file>qualifier.kt</file>
|
||||
<line>8</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/qualifier.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Explicit 'get'</problem_class>
|
||||
<description>Replace 'get' call with index operator</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun get(s: String): C = C()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
C.<caret>get("x")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
companion object {
|
||||
fun get(s: String): C = C()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
C["x"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class JavaClass {
|
||||
public static String get(String s) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun foo() {
|
||||
JavaClass.<caret>get("x")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
open class Base {
|
||||
open fun get(s: String) = ""
|
||||
}
|
||||
|
||||
class C : Base() {
|
||||
override fun get(s: String): String {
|
||||
return super.<caret>get(s)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// IS_APPLICABLE: false
|
||||
package p
|
||||
|
||||
fun get(s: String) = s
|
||||
|
||||
fun foo() {
|
||||
p.<caret>get("x")
|
||||
}
|
||||
@@ -2237,12 +2237,24 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("qualifier.kt")
|
||||
public void testQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/qualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("rangeToSanityTest.kt")
|
||||
public void testRangeToSanityTest() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/rangeToSanityTest.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("super.kt")
|
||||
public void testSuper() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/super.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("timesSanityTest.kt")
|
||||
public void testTimesSanityTest() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithBinaryOperator/timesSanityTest.kt");
|
||||
@@ -2342,6 +2354,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("qualifier.kt")
|
||||
public void testQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/qualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("super.kt")
|
||||
public void testSuper() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/super.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeArguments.kt")
|
||||
public void testTypeArguments() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceCallWithUnaryOperator/typeArguments.kt");
|
||||
@@ -2453,12 +2477,24 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("qualifier.kt")
|
||||
public void testQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceContains/qualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleArgument.kt")
|
||||
public void testSimpleArgument() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceContains/simpleArgument.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("super.kt")
|
||||
public void testSuper() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceContains/super.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeArguments.kt")
|
||||
public void testTypeArguments() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceContains/typeArguments.kt");
|
||||
@@ -2546,6 +2582,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("qualifier.kt")
|
||||
public void testQualifier() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceGet/qualifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("sanityCheck.kt")
|
||||
public void testSanityCheck() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceGet/sanityCheck.kt");
|
||||
@@ -2558,6 +2600,24 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("staticMethod.kt")
|
||||
public void testStaticMethod() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceGet/staticMethod.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("super.kt")
|
||||
public void testSuper() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceGet/super.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelFun.kt")
|
||||
public void testTopLevelFun() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceGet/topLevelFun.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("unacceptableVararg.kt")
|
||||
public void testUnacceptableVararg() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/conventionNameCalls/replaceGet/unacceptableVararg.kt");
|
||||
|
||||
Reference in New Issue
Block a user