fix 'operator' modifier inspection
#KT-9349 Fixed
This commit is contained in:
@@ -24,19 +24,20 @@ 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.CallableMemberDescriptor
|
||||
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.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver
|
||||
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
|
||||
|
||||
@@ -48,12 +49,13 @@ public class OperatorModifierInspection : AbstractKotlinInspection() {
|
||||
if (nameIdentifier != null &&
|
||||
function.isMemberOrExtension() &&
|
||||
function.isOperator() &&
|
||||
!function.hasModifier(JetTokens.OPERATOR_KEYWORD)) {
|
||||
!function.isAnnotatedAsOperator()) {
|
||||
|
||||
holder.registerProblem(nameIdentifier, "Function defines an operator but isn't annotated as such",
|
||||
AddModifierLocalQuickFix())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,15 +88,25 @@ public class OperatorModifierInspection : AbstractKotlinInspection() {
|
||||
return false
|
||||
}
|
||||
|
||||
private fun JetNamedFunction.isAnnotatedAsOperator(): Boolean {
|
||||
if (hasModifier(JetTokens.OPERATOR_KEYWORD)) return true
|
||||
val descriptor = descriptor as? CallableMemberDescriptor ?: return false
|
||||
return OverrideResolver.getOverriddenDeclarations(descriptor).any {
|
||||
(it as? FunctionDescriptor)?.isOperator == true
|
||||
}
|
||||
}
|
||||
|
||||
private fun JetNamedFunction.isMemberOrExtension(): Boolean =
|
||||
receiverTypeReference != null || getStrictParentOfType<JetClassOrObject>() != null
|
||||
|
||||
private fun JetNamedFunction.isIntReturnType(): Boolean {
|
||||
return KotlinBuiltIns.isInt(analyze(BodyResolveMode.PARTIAL).getType(this) ?: return false)
|
||||
val returnType = (descriptor as? FunctionDescriptor)?.returnType ?: return false
|
||||
return KotlinBuiltIns.isInt(returnType)
|
||||
}
|
||||
|
||||
private fun JetNamedFunction.isBooleanReturnType(): Boolean {
|
||||
return KotlinBuiltIns.isBoolean(analyze(BodyResolveMode.PARTIAL).getType(this) ?: return false)
|
||||
val returnType = (descriptor as? FunctionDescriptor)?.returnType ?: return false
|
||||
return KotlinBuiltIns.isBoolean(returnType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// "Add 'operator' modifier" "true"
|
||||
class A {
|
||||
fun <caret>contains(other: A): Boolean = true
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// "Add 'operator' modifier" "true"
|
||||
class A {
|
||||
operator fun <caret>contains(other: A): Boolean = true
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Add 'operator' modifier" "false"
|
||||
// ACTION: Convert to block body
|
||||
// ACTION: Specify return type explicitly
|
||||
open class A {
|
||||
open operator fun plus(a: A) = A()
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
override fun plu<caret>s(a: A) = A()
|
||||
}
|
||||
@@ -4195,6 +4195,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/operatorModifier"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("containsBool.kt")
|
||||
public void testContainsBool() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/operatorModifier/containsBool.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("containsInt.kt")
|
||||
public void testContainsInt() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/operatorModifier/containsInt.kt");
|
||||
@@ -4207,6 +4213,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("overridden.kt")
|
||||
public void testOverridden() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/operatorModifier/overridden.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/operatorModifier/simple.kt");
|
||||
|
||||
Reference in New Issue
Block a user