Create Function From Usage: Quick-fix for unary operations
This commit is contained in:
@@ -222,6 +222,10 @@ public class QuickFixRegistrar {
|
||||
QuickFixes.factories.put(EXPECTED_TYPE_MISMATCH, changeFunctionLiteralReturnTypeFix);
|
||||
QuickFixes.factories.put(ASSIGNMENT_TYPE_MISMATCH, changeFunctionLiteralReturnTypeFix);
|
||||
|
||||
QuickFixes.factories.put(UNRESOLVED_REFERENCE, CreateUnaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(UNRESOLVED_REFERENCE_WRONG_RECEIVER, CreateUnaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(NO_VALUE_FOR_PARAMETER, CreateUnaryOperationActionFactory.INSTANCE$);
|
||||
|
||||
QuickFixes.factories.put(UNRESOLVED_REFERENCE_WRONG_RECEIVER, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(UNRESOLVED_REFERENCE, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
QuickFixes.factories.put(NONE_APPLICABLE, CreateBinaryOperationActionFactory.INSTANCE$);
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
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.JetSimpleNameExpression
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||
import org.jetbrains.jet.lexer.JetToken
|
||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import java.util.Collections
|
||||
import org.jetbrains.jet.lang.psi.JetUnaryExpression
|
||||
|
||||
public object CreateUnaryOperationActionFactory: JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val callExpr = diagnostic.getPsiElement().getParent() as? JetUnaryExpression ?: return null
|
||||
val token = callExpr.getOperationToken() as JetToken
|
||||
val operationName = OperatorConventions.getNameForOperationSymbol(token) ?: return null
|
||||
val incDec = token in OperatorConventions.INCREMENT_OPERATIONS
|
||||
|
||||
val receiverExpr = callExpr.getBaseExpression() ?: return null
|
||||
|
||||
val receiverType = TypeInfo(receiverExpr, Variance.IN_VARIANCE)
|
||||
val returnType = if (incDec) TypeInfo.ByReceiverType(Variance.OUT_VARIANCE) else TypeInfo(callExpr, Variance.OUT_VARIANCE)
|
||||
return CreateFunctionFromUsageFix(callExpr, FunctionInfo(operationName.asString(), receiverType, returnType))
|
||||
}
|
||||
}
|
||||
+10
-8
@@ -20,20 +20,22 @@ abstract class TypeInfo(val variance: Variance) {
|
||||
JetNameSuggester.suggestNamesForExpression(expression, EmptyValidator)
|
||||
}
|
||||
|
||||
override fun getPossibleTypes(context: BindingContext): List<JetType> =
|
||||
expression.guessTypes(context).flatMap { it.getPossibleSupertypes(variance) }
|
||||
override fun getPossibleTypes(builder: FunctionBuilder): List<JetType> =
|
||||
expression.guessTypes(builder.currentFileContext).flatMap { it.getPossibleSupertypes(variance) }
|
||||
}
|
||||
|
||||
class ByType(val theType: JetType, variance: Variance, val keepUnsubstituted: Boolean = false): TypeInfo(variance) {
|
||||
override val possibleNamesFromExpression: Array<String> =
|
||||
ArrayUtil.EMPTY_STRING_ARRAY
|
||||
|
||||
override fun getPossibleTypes(context: BindingContext): List<JetType> =
|
||||
override fun getPossibleTypes(builder: FunctionBuilder): List<JetType> =
|
||||
theType.getPossibleSupertypes(variance)
|
||||
}
|
||||
|
||||
abstract val possibleNamesFromExpression: Array<String>
|
||||
abstract fun getPossibleTypes(context: BindingContext): List<JetType>
|
||||
class ByReceiverType(variance: Variance): TypeInfo(variance) {
|
||||
override fun getPossibleTypes(builder: FunctionBuilder): List<JetType> =
|
||||
builder.receiverTypeCandidate.theType.getPossibleSupertypes(variance)
|
||||
}
|
||||
|
||||
open val possibleNamesFromExpression: Array<String> get() = ArrayUtil.EMPTY_STRING_ARRAY
|
||||
abstract fun getPossibleTypes(builder: FunctionBuilder): List<JetType>
|
||||
|
||||
protected fun JetType.getPossibleSupertypes(variance: Variance): List<JetType> {
|
||||
val single = Collections.singletonList(this)
|
||||
|
||||
+2
-2
@@ -107,7 +107,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
|
||||
}
|
||||
|
||||
fun computeTypeCandidates(typeInfo: TypeInfo): List<TypeCandidate> =
|
||||
typeCandidates.getOrPut(typeInfo) { typeInfo.getPossibleTypes(currentFileContext).map { TypeCandidate(it) } }
|
||||
typeCandidates.getOrPut(typeInfo) { typeInfo.getPossibleTypes(this).map { TypeCandidate(it) } }
|
||||
|
||||
fun computeTypeCandidates(
|
||||
typeInfo: TypeInfo,
|
||||
@@ -115,7 +115,7 @@ class FunctionBuilder(val config: FunctionBuilderConfiguration) {
|
||||
scope: JetScope): List<TypeCandidate> {
|
||||
if (typeInfo is TypeInfo.ByType && typeInfo.keepUnsubstituted) return computeTypeCandidates(typeInfo)
|
||||
return typeCandidates.getOrPut(typeInfo) {
|
||||
val types = typeInfo.getPossibleTypes(currentFileContext).reverse()
|
||||
val types = typeInfo.getPossibleTypes(this).reverse()
|
||||
|
||||
val newTypes = LinkedHashSet<JetType>(types)
|
||||
for (substitution in substitutions) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Create function 'inc' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun inc(): A<T> {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
var a = A(1)
|
||||
a++
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun minus(n: Int): A<T> = throw Exception()
|
||||
fun minus(): 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)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
fun test() {
|
||||
val a = -false
|
||||
}
|
||||
fun Boolean.minus(): Any {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun minus(): Any {
|
||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a = -A(1)
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun minus(): 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)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Create function 'inc' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
var a = A(1)
|
||||
a<caret>++
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T) {
|
||||
fun minus(n: Int): A<T> = throw Exception()
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val a: A<Int> = <caret>-A(1)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
fun test() {
|
||||
val a = <caret>-false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test() {
|
||||
val a = <caret>-A(1)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Create function 'minus' from usage" "true"
|
||||
|
||||
class A<T>(val n: T)
|
||||
|
||||
fun test<U>(u: U) {
|
||||
val a: A<U> = <caret>-A(u)
|
||||
}
|
||||
@@ -618,7 +618,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/createFromUsage")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({CreateFromUsage.BinaryOperations.class, 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, CreateFromUsage.UnaryOperations.class})
|
||||
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
|
||||
public static class CreateFromUsage extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInCreateFromUsage() throws Exception {
|
||||
@@ -923,6 +923,46 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/createFromUsage/unaryOperations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
|
||||
public static class UnaryOperations extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInUnaryOperations() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/unaryOperations"), Pattern.compile("^before(\\w+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeIncOnUserType.kt")
|
||||
public void testIncOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/unaryOperations/beforeIncOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeMinusMissingArgs.kt")
|
||||
public void testMinusMissingArgs() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/unaryOperations/beforeMinusMissingArgs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeMinusOnLibType.kt")
|
||||
public void testMinusOnLibType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/unaryOperations/beforeMinusOnLibType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeMinusOnUserType.kt")
|
||||
public void testMinusOnUserType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/unaryOperations/beforeMinusOnUserType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeMinusOnUserTypeWithTypeParams.kt")
|
||||
public void testMinusOnUserTypeWithTypeParams() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/unaryOperations/beforeMinusOnUserTypeWithTypeParams.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/expressions")
|
||||
|
||||
Reference in New Issue
Block a user