Create Function From Usage: Quick-fix for binary operations
This commit is contained in:
@@ -222,6 +222,12 @@ public class QuickFixRegistrar {
|
||||
QuickFixes.factories.put(EXPECTED_TYPE_MISMATCH, changeFunctionLiteralReturnTypeFix);
|
||||
QuickFixes.factories.put(ASSIGNMENT_TYPE_MISMATCH, changeFunctionLiteralReturnTypeFix);
|
||||
|
||||
QuickFixes.factories.put(UNRESOLVED_REFERENCE_WRONG_RECEIVER, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(UNRESOLVED_REFERENCE, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(NONE_APPLICABLE, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(NO_VALUE_FOR_PARAMETER, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(TOO_MANY_ARGUMENTS, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
|
||||
QuickFixes.factories.put(TYPE_MISMATCH, new QuickFixFactoryForTypeMismatchError());
|
||||
|
||||
QuickFixes.factories.put(AUTOCAST_IMPOSSIBLE, CastExpressionFix.createFactoryForAutoCastImpossible());
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package org.jetbrains.jet.plugin.quickfix.createFromUsage.createFunction
|
||||
|
||||
import org.jetbrains.jet.plugin.quickfix.JetSingleIntentionActionFactory
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||
import org.jetbrains.jet.lexer.JetToken
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import java.util.Collections
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
|
||||
public object CreateBinaryOperationActionFactory: JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val callExpr = diagnostic.getPsiElement().getParent() as? JetBinaryExpression ?: return null
|
||||
val token = callExpr.getOperationToken() as JetToken
|
||||
val operationName = when (token) {
|
||||
JetTokens.IDENTIFIER -> callExpr.getOperationReference().getReferencedName()
|
||||
else -> OperatorConventions.getNameForOperationSymbol(token)?.asString()
|
||||
} ?: return null
|
||||
val inOperation = token in OperatorConventions.IN_OPERATIONS
|
||||
val comparisonOperation = token in OperatorConventions.COMPARISON_OPERATIONS
|
||||
|
||||
val leftExpr = callExpr.getLeft() ?: return null
|
||||
val rightExpr = callExpr.getRight() ?: return null
|
||||
|
||||
val receiverExpr = if (inOperation) rightExpr else leftExpr
|
||||
val argumentExpr = if (inOperation) leftExpr else rightExpr
|
||||
|
||||
val builtIns = KotlinBuiltIns.getInstance()
|
||||
|
||||
val receiverType = TypeInfo(receiverExpr, Variance.IN_VARIANCE)
|
||||
val returnType = when {
|
||||
inOperation -> TypeInfo.ByType(builtIns.getBooleanType(), Variance.INVARIANT, true)
|
||||
comparisonOperation -> TypeInfo.ByType(builtIns.getIntType(), Variance.INVARIANT, true)
|
||||
else -> TypeInfo(callExpr, Variance.OUT_VARIANCE)
|
||||
}
|
||||
val parameters = Collections.singletonList(ParameterInfo(TypeInfo(argumentExpr, Variance.IN_VARIANCE)))
|
||||
return CreateFunctionFromUsageFix(callExpr, FunctionInfo(operationName, receiverType, returnType, parameters))
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -24,7 +24,7 @@ abstract class TypeInfo(val variance: Variance) {
|
||||
expression.guessTypes(context).flatMap { it.getPossibleSupertypes(variance) }
|
||||
}
|
||||
|
||||
class ByType(val theType: JetType, variance: Variance): TypeInfo(variance) {
|
||||
class ByType(val theType: JetType, variance: Variance, val keepUnsubstituted: Boolean = false): TypeInfo(variance) {
|
||||
override val possibleNamesFromExpression: Array<String> =
|
||||
ArrayUtil.EMPTY_STRING_ARRAY
|
||||
|
||||
|
||||
+1
@@ -113,6 +113,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
|
||||
typeInfo: TypeInfo,
|
||||
substitutions: Array<JetTypeSubstitution>,
|
||||
scope: JetScope): List<TypeCandidate> {
|
||||
if (typeInfo is TypeInfo.ByType && typeInfo.keepUnsubstituted) return computeTypeCandidates(typeInfo)
|
||||
return typeCandidates.getOrPut(typeInfo) {
|
||||
val types = typeInfo.getPossibleTypes(currentFileContext).reverse()
|
||||
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Create function 'foo' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun foo(arg: T): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) foo 2
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Create function 'compareTo' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun compareTo(arg: T): Int {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(1) >= 2
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun contains(arg: T): Boolean {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
2 in A(1)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Create function 'compareTo' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun compareTo(arg: T): Int {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(1) < 2
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun contains(arg: T): Boolean {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
2 !in A(1)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Create function 'plusAssign' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plusAssign(arg: T): Unit {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
A(1) += 2
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plus(): A<T> = throw Exception()
|
||||
fun plus(arg: T): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) + 2
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plus(arg: T): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
var a = A(1)
|
||||
a = a + 2
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plus(i: Int, s: String): A<T> = throw Exception()
|
||||
fun plus(arg: T): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) + 2
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = 2 + A(1)
|
||||
}
|
||||
fun Int.plus(A: A<Int>): A<Int> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plus(arg: T): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) + 2
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plus(i: Int): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test<U>(u: U) {
|
||||
val a: A<U> = A(u) + 2
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun contains(arg: T): Boolean {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
when {
|
||||
2 in A(1) -> {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun contains(arg: T): Boolean {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
when {
|
||||
2 !in A(1) -> {}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Create function 'foo' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) <caret>foo 2
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Create function 'compareTo' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
A(1) <caret>>= 2
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
2 <caret>in A(1)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create function 'compareTo' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
A(1) <caret>< 2
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
2 <caret>!in A(1)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create function 'plusAssign' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
A(1) <caret>+= 2
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plus(): A<T> = throw Exception()
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) + <caret>2
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
var a = A(1)
|
||||
a = a <caret>+ 2
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun plus(i: Int, s: String): A<T> = throw Exception()
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) <caret>+ 2
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = 2 <caret>+ A(1)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = A(1) <caret>+ 2
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Create function 'plus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test<U>(u: U) {
|
||||
val a: A<U> = A(u) <caret>+ 2
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
when {
|
||||
2 <caret>in A(1) -> {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Create function 'contains' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
when {
|
||||
2 <caret>!in A(1) -> {}
|
||||
}
|
||||
}
|
||||
@@ -618,13 +618,107 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/createFromUsage")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({CreateFromUsage.Component.class, CreateFromUsage.Get.class, CreateFromUsage.HasNext.class, CreateFromUsage.Iterator.class, CreateFromUsage.Next.class, CreateFromUsage.Set.class})
|
||||
@InnerTestClasses({CreateFromUsage.BinaryOperations.class, CreateFromUsage.Component.class, CreateFromUsage.Get.class, CreateFromUsage.HasNext.class, CreateFromUsage.Iterator.class, CreateFromUsage.Next.class, CreateFromUsage.Set.class})
|
||||
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
|
||||
public static class CreateFromUsage extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInCreateFromUsage() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage"), Pattern.compile("^before(\\w+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/createFromUsage/binaryOperations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
|
||||
public static class BinaryOperations extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInBinaryOperations() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/binaryOperations"), Pattern.compile("^before(\\w+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeCustomOperationOnUserType.kt")
|
||||
public void testCustomOperationOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforeCustomOperationOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeGreaterOrEqualOnUserType.kt")
|
||||
public void testGreaterOrEqualOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforeGreaterOrEqualOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeInOnUserType.kt")
|
||||
public void testInOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforeInOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeLessOnUserType.kt")
|
||||
public void testLessOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforeLessOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeNotInOnUserType.kt")
|
||||
public void testNotInOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforeNotInOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforePlusAssignOnUserType.kt")
|
||||
public void testPlusAssignOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforePlusAssignOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforePlusExtraArgs.kt")
|
||||
public void testPlusExtraArgs() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforePlusExtraArgs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforePlusForAssignmentOnUserType.kt")
|
||||
public void testPlusForAssignmentOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforePlusForAssignmentOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforePlusMissingArgs.kt")
|
||||
public void testPlusMissingArgs() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforePlusMissingArgs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforePlusOnLibType.kt")
|
||||
public void testPlusOnLibType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforePlusOnLibType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforePlusOnUserType.kt")
|
||||
public void testPlusOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforePlusOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforePlusOnUserTypeWithTypeParams.kt")
|
||||
public void testPlusOnUserTypeWithTypeParams() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforePlusOnUserTypeWithTypeParams.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeWhenInOnUserType.kt")
|
||||
public void testWhenInOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforeWhenInOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeWhenNotInOnUserType.kt")
|
||||
public void testWhenNotInOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/binaryOperations/beforeWhenNotInOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/createFromUsage/component")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user