quickfix for usages of operators that don't have the proper annotation

This commit is contained in:
Dmitry Jemerov
2015-09-25 19:31:30 +02:00
parent 8b0ccce4f1
commit 3d0e91065a
15 changed files with 132 additions and 9 deletions
+1 -2
View File
@@ -1204,8 +1204,7 @@
groupName="Kotlin"
language="jet"
enabledByDefault="true"
level="WARNING"
cleanupTool="true"/>
level="WARNING"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ConflictingExtensionPropertyInspection"
displayName="Extension property conflicts with synthetic one"
@@ -91,7 +91,8 @@ public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspe
Errors.DEPRECATED_SYMBOL_WITH_MESSAGE,
Errors.ACCESS_TO_PRIVATE_TOP_LEVEL_FROM_ANOTHER_FILE,
Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION,
Errors.BACKING_FIELD_SYNTAX_DEPRECATED
Errors.BACKING_FIELD_SYNTAX_DEPRECATED,
Errors.OPERATOR_MODIFIER_REQUIRED
)
private fun Diagnostic.isObsoleteLabel(): Boolean {
@@ -16,23 +16,31 @@
package org.jetbrains.kotlin.idea.inspections
import com.intellij.codeInspection.*
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInspection.LocalInspectionToolSession
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElementVisitor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters2
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
import org.jetbrains.kotlin.idea.quickfix.CleanupFix
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.psi.JetModifierListOwner
import org.jetbrains.kotlin.psi.JetNamedFunction
import org.jetbrains.kotlin.psi.JetVisitorVoid
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.types.expressions.OperatorConventions
public class OperatorModifierInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool {
public class OperatorModifierInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
return object : JetVisitorVoid() {
override fun visitNamedFunction(function: JetNamedFunction) {
@@ -99,3 +107,11 @@ private class AddModifierLocalQuickFix() : LocalQuickFix {
modifierListOwner?.addModifier(JetTokens.OPERATOR_KEYWORD)
}
}
object OperatorModifierFixFactory : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val param = (diagnostic as? DiagnosticWithParameters2<*, *, *>)?.a as? FunctionDescriptor ?: return null
val target = (param.source as? PsiSourceElement)?.psi as? JetDeclaration ?: return null
return object : AddModifierFix(target, JetTokens.OPERATOR_KEYWORD), CleanupFix {}
}
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
import org.jetbrains.kotlin.idea.inspections.AddReflectionQuickFix
import org.jetbrains.kotlin.idea.inspections.OperatorModifierFixFactory
import org.jetbrains.kotlin.idea.intentions.IntroduceBackingPropertyFix
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.*
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClassFromCallWithConstructorCalleeActionFactory
@@ -326,5 +327,7 @@ public class QuickFixRegistrar : QuickFixContributor {
BACKING_FIELD_SYNTAX_DEPRECATED.registerFactory(MigrateBackingFieldSyntaxFix)
BACKING_FIELD_USAGE_DEPRECATED.registerFactory(MigrateBackingFieldUsageFix)
BACKING_FIELD_USAGE_DEPRECATED.registerFactory(IntroduceBackingPropertyFix)
OPERATOR_MODIFIER_REQUIRED.registerFactory(OperatorModifierFixFactory)
}
}
+10
View File
@@ -47,3 +47,13 @@ class Foo {
get = $x
set(value) { $x = value }
}
class B {
fun plus(a: A): A = A()
}
fun foo() {
B() + B()
B() + B()
B() + B()
}
+10
View File
@@ -46,3 +46,13 @@ class Foo {
get = field
set(value) { field = value }
}
class B {
operator fun plus(a: A): A = A()
}
fun foo() {
B() + B()
B() + B()
B() + B()
}
+8
View File
@@ -0,0 +1,8 @@
// "Add 'operator' modifier" "true"
class A {
fun plus(a: A): A = A()
}
fun foo() {
A() <caret>+ A()
}
@@ -0,0 +1,8 @@
// "Add 'operator' modifier" "true"
class A {
operator fun plus(a: A): A = A()
}
fun foo() {
A() <caret>+ A()
}
@@ -0,0 +1,6 @@
// "Add 'operator' modifier" "true"
class A {
fun contains(x: Any): Boolean = false
}
fun foo() = 0 i<caret>n A()
@@ -0,0 +1,6 @@
// "Add 'operator' modifier" "true"
class A {
operator fun contains(x: Any): Boolean = false
}
fun foo() = 0 in A()
@@ -0,0 +1,10 @@
// "Add 'operator' modifier" "true"
class A {
fun component1(): Int = 0
fun component2(): Int = 1
}
fun foo() {
val (<caret>zero, one) = A()
}
@@ -0,0 +1,10 @@
// "Add 'operator' modifier" "true"
class A {
operator fun component1(): Int = 0
fun component2(): Int = 1
}
fun foo() {
val (zero, one) = A()
}
@@ -0,0 +1,6 @@
// "Add 'operator' modifier" "true"
class A {
fun get(i: Int): String = ""
}
fun foo() = A()<caret>[0]
@@ -0,0 +1,6 @@
// "Add 'operator' modifier" "true"
class A {
operator fun get(i: Int): String = ""
}
fun foo() = A()[0]
@@ -4316,6 +4316,30 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName);
}
@TestMetadata("operatorModifier.kt")
public void testOperatorModifier() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/modifiers/operatorModifier.kt");
doTest(fileName);
}
@TestMetadata("operatorModifierCollection.kt")
public void testOperatorModifierCollection() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/modifiers/operatorModifierCollection.kt");
doTest(fileName);
}
@TestMetadata("operatorModifierComponent.kt")
public void testOperatorModifierComponent() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/modifiers/operatorModifierComponent.kt");
doTest(fileName);
}
@TestMetadata("operatorModifierGet.kt")
public void testOperatorModifierGet() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/modifiers/operatorModifierGet.kt");
doTest(fileName);
}
@TestMetadata("packageMemberCannotBeProtected.kt")
public void testPackageMemberCannotBeProtected() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/modifiers/packageMemberCannotBeProtected.kt");