diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/OperatorModifierInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/OperatorModifierInspection.kt index fb90cae42b0..451c6d3b535 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/OperatorModifierInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/OperatorModifierInspection.kt @@ -23,97 +23,36 @@ 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.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.resolveToDescriptor import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde 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.JetModifierKeywordToken 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.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.types.expressions.OperatorConventions -import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.util.OperatorChecks public class OperatorModifierInspection : AbstractKotlinInspection() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { return object : JetVisitorVoid() { override fun visitNamedFunction(function: JetNamedFunction) { - val nameIdentifier = function.nameIdentifier - if (nameIdentifier != null && - function.isMemberOrExtension() && - function.isOperator() && - !function.isAnnotatedAsOperator()) { - + val nameIdentifier = function.nameIdentifier ?: return + val functionDescriptor = function.resolveToDescriptor() as? FunctionDescriptor ?: return + if (!functionDescriptor.isOperator && OperatorChecks.canBeOperator(functionDescriptor)) { holder.registerProblem(nameIdentifier, "Function defines an operator but isn't annotated as such", - AddModifierLocalQuickFix()) + AddModifierLocalQuickFix()) } } } } - - private fun JetNamedFunction.isOperator(): Boolean { - val name = nameAsName ?: return false - val arity = valueParameters.size() - if (arity == 0 && - (name in OperatorConventions.UNARY_OPERATION_NAMES.values() || - name == OperatorNameConventions.PLUS || name == OperatorNameConventions.MINUS || // temporary - name == OperatorNameConventions.ITERATOR || - isComponentLike(name) || - name == OperatorNameConventions.NEXT || - (name == OperatorNameConventions.HAS_NEXT && isBooleanReturnType()))) { - return true - } - if (arity == 1 && (name in OperatorConventions.BINARY_OPERATION_NAMES.values() || - name in OperatorConventions.ASSIGNMENT_OPERATIONS.values () || - (name == OperatorNameConventions.CONTAINS && isBooleanReturnType()) || - (name == OperatorNameConventions.COMPARE_TO && isIntReturnType()))) { - return true - } - if (name == OperatorNameConventions.INVOKE) { - return true - } - if (arity >= 1 && name == OperatorNameConventions.GET) { - return true - } - if (arity >= 2 && name == OperatorNameConventions.SET) { - return true - } - 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() != null - - private fun JetNamedFunction.isIntReturnType(): Boolean { - val returnType = (descriptor as? FunctionDescriptor)?.returnType ?: return false - return KotlinBuiltIns.isInt(returnType) - } - - private fun JetNamedFunction.isBooleanReturnType(): Boolean { - val returnType = (descriptor as? FunctionDescriptor)?.returnType ?: return false - return KotlinBuiltIns.isBoolean(returnType) - } } private class AddModifierLocalQuickFix() : LocalQuickFix {