Created quickfix for KT-9805

This commit is contained in:
Valentin Kipyatkov
2015-11-10 20:19:52 +03:00
parent 80a788cf53
commit 4f9866f62f
8 changed files with 128 additions and 4 deletions
@@ -96,7 +96,8 @@ public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspe
Errors.INFIX_MODIFIER_REQUIRED,
Errors.CALLABLE_REFERENCE_TO_MEMBER_OR_EXTENSION_WITH_EMPTY_LHS,
Errors.DEPRECATED_TYPE_PARAMETER_SYNTAX,
Errors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS
Errors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS,
Errors.INVOKE_ON_EXTENSION_FUNCTION_WITH_EXPLICIT_DISPATCH_RECEIVER
)
private fun Diagnostic.isObsoleteLabel(): Boolean {
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClas
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateLocalVariableActionFactory
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateParameterByNamedArgumentActionFactory
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateParameterByRefActionFactory
import org.jetbrains.kotlin.idea.quickfix.migration.InvokeOnExtensionFunctionWithExplicitReceiverFix
import org.jetbrains.kotlin.idea.quickfix.migration.MigrateTypeParameterListFix
import org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageFix
import org.jetbrains.kotlin.idea.quickfix.replaceWith.DeprecatedSymbolUsageInWholeProjectFix
@@ -343,5 +344,7 @@ public class QuickFixRegistrar : QuickFixContributor {
DELEGATE_RESOLVED_TO_DEPRECATED_CONVENTION.registerFactory(DeprecatedFunctionConventionFix)
DEPRECATED_UNARY_PLUS_MINUS.registerFactory(DeprecatedFunctionConventionFix)
INVOKE_ON_EXTENSION_FUNCTION_WITH_EXPLICIT_DISPATCH_RECEIVER.registerFactory(InvokeOnExtensionFunctionWithExplicitReceiverFix)
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.quickfix.migration
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.quickfix.CleanupFix
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
class InvokeOnExtensionFunctionWithExplicitReceiverFix(qualifiedExpression: KtDotQualifiedExpression) : KotlinQuickFixAction<KtDotQualifiedExpression>(qualifiedExpression), CleanupFix {
override fun getFamilyName() = "Fix extension function value call"
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val callExpression = element.selectorExpression as KtCallExpression
val pattern = if (element is KtSafeQualifiedExpression)"($0?.$1)" else "($0.$1)"
val newCallee = KtPsiFactory(file).createExpressionByPattern(pattern, element.receiverExpression, callExpression.calleeExpression!!)
val newCallExpression = element.replaced(callExpression)
newCallExpression.calleeExpression!!.replace(newCallee)
}
companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val callee = Errors.INVOKE_ON_EXTENSION_FUNCTION_WITH_EXPLICIT_DISPATCH_RECEIVER.cast(diagnostic).a as? KtNameReferenceExpression ?: return null
val callExpression = callee.parent as? KtCallExpression ?: return null
val qualifiedExpression = callExpression.getQualifiedExpressionForSelector() as? KtDotQualifiedExpression ?: return null
return InvokeOnExtensionFunctionWithExplicitReceiverFix(qualifiedExpression)
}
}
}
+13 -1
View File
@@ -70,4 +70,16 @@ fun typed<T>() {
fun <T : Cloneable> withTypeParameters() where T : Comparable<T> {
}
C() willBeInfix 1
val x = C() willBeInfix 1
class AAA {
val foo: BBB.() -> Unit get() = null!!
}
class BBB
fun test(a: AAA, b: BBB) {
with(b) {
a.foo()
}
}
+14 -2
View File
@@ -61,7 +61,7 @@ class C {
fun bar() = C::foo
fun willBeInfix(i: Int) {}
infix fun willBeInfix(i: Int) {}
}
fun <T> typed() {
@@ -70,4 +70,16 @@ fun <T> typed() {
fun <T> withTypeParameters() where T : Cloneable, T : Comparable<T> {
}
C() willBeInfix 1
val x = C() willBeInfix 1
class AAA {
val foo: BBB.() -> Unit get() = null!!
}
class BBB
fun test(a: AAA, b: BBB) {
with(b) {
(a.foo)()
}
}
@@ -0,0 +1,15 @@
// "Fix extension function value call" "true"
class A {
val foo: B.() -> Unit get() = null!!
}
class B
fun test(a: A, b: B) {
with(b) {
a.<caret>foo()
}
}
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
@@ -0,0 +1,15 @@
// "Fix extension function value call" "true"
class A {
val foo: B.() -> Unit get() = null!!
}
class B
fun test(a: A, b: B) {
with(b) {
(a.foo)()
}
}
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
@@ -4361,6 +4361,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
}
@TestMetadata("idea/testData/quickfix/migration/invokeOnExtensionFunctionWithExplicitReceiverFix")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class InvokeOnExtensionFunctionWithExplicitReceiverFix extends AbstractQuickFixTest {
public void testAllFilesPresentInInvokeOnExtensionFunctionWithExplicitReceiverFix() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/invokeOnExtensionFunctionWithExplicitReceiverFix"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/migration/invokeOnExtensionFunctionWithExplicitReceiverFix/simple.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/migration/missingConstructorKeyword")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)