teach 'create from usage' to add 'operator' modifier when necessary

This commit is contained in:
Dmitry Jemerov
2015-09-24 16:28:03 +02:00
parent bda0bd1de1
commit 3dbb74bf0c
35 changed files with 54 additions and 47 deletions
@@ -25,6 +25,7 @@ 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.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.types.expressions.OperatorConventions
public class OperatorModifierInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool {
@@ -41,25 +42,27 @@ public class OperatorModifierInspection : AbstractKotlinInspection(), CleanupLoc
}
private fun JetNamedFunction.isOperator(): Boolean {
val name = nameAsName ?: return false
val arity = valueParameters.size()
if (arity == 0 &&
(nameAsName in OperatorConventions.UNARY_OPERATION_NAMES.values() ||
nameAsName == OperatorConventions.ITERATOR)) {
(name in OperatorConventions.UNARY_OPERATION_NAMES.values() ||
name == OperatorConventions.ITERATOR ||
isComponentLike(name))) {
return true
}
if (arity == 1 && (nameAsName in OperatorConventions.BINARY_OPERATION_NAMES.values() ||
nameAsName in OperatorConventions.ASSIGNMENT_OPERATIONS.values () ||
nameAsName == OperatorConventions.CONTAINS ||
nameAsName == OperatorConventions.COMPARE_TO)) {
if (arity == 1 && (name in OperatorConventions.BINARY_OPERATION_NAMES.values() ||
name in OperatorConventions.ASSIGNMENT_OPERATIONS.values () ||
name == OperatorConventions.CONTAINS ||
name == OperatorConventions.COMPARE_TO)) {
return true
}
if (nameAsName == OperatorConventions.INVOKE) {
if (name == OperatorConventions.INVOKE) {
return true
}
if (arity >= 1 && nameAsName == OperatorConventions.GET) {
if (arity >= 1 && name == OperatorConventions.GET) {
return true
}
if (arity >= 2 && nameAsName == OperatorConventions.SET) {
if (arity >= 2 && name == OperatorConventions.SET) {
return true
}
return false
@@ -467,8 +467,9 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
containingElement is JetClass && containingElement.isInterface() && !config.isExtension -> ""
else -> "{}"
}
if (callableInfo.kind == CallableKind.FUNCTION) {
psiFactory.createFunction("${modifiers}fun<> $header $body")
if (callableInfo is FunctionInfo) {
val operatorModifier = if (callableInfo.isOperator) "operator " else ""
psiFactory.createFunction("${modifiers}${operatorModifier}fun<> $header $body")
}
else {
psiFactory.createSecondaryConstructor("${modifiers}constructor$paramList $body")
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.supertypes
import java.util.Collections
import java.util.*
/**
* Represents a concrete type or a set of types yet to be inferred from an expression.
@@ -143,7 +143,8 @@ class FunctionInfo(name: String,
returnTypeInfo: TypeInfo,
possibleContainers: List<JetElement> = Collections.emptyList(),
override val parameterInfos: List<ParameterInfo> = Collections.emptyList(),
typeParameterInfos: List<TypeInfo> = Collections.emptyList()
typeParameterInfos: List<TypeInfo> = Collections.emptyList(),
val isOperator: Boolean = false
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos) {
override val kind: CallableKind get() = CallableKind.FUNCTION
}
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetBinaryExpression
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import java.util.Collections
import java.util.*
public object CreateBinaryOperationActionFactory: CreateCallableMemberFromUsageFactory<JetBinaryExpression>() {
override fun getElementOfInterest(diagnostic: Diagnostic): JetBinaryExpression? {
@@ -54,6 +54,7 @@ public object CreateBinaryOperationActionFactory: CreateCallableMemberFromUsageF
else -> TypeInfo(element, Variance.OUT_VARIANCE)
}
val parameters = Collections.singletonList(ParameterInfo(TypeInfo(argumentExpr, Variance.IN_VARIANCE)))
return FunctionInfo(operationName, receiverType, returnType, Collections.emptyList(), parameters)
return FunctionInfo(operationName, receiverType, returnType, parameterInfos = parameters,
isOperator = token != JetTokens.IDENTIFIER)
}
}
@@ -49,6 +49,6 @@ object CreateComponentFunctionActionFactory : CreateCallableMemberFromUsageFacto
val entry = entries[componentNumber]
val returnType = TypeInfo(entry, Variance.OUT_VARIANCE)
return FunctionInfo(name.identifier, ownerType, returnType)
return FunctionInfo(name.identifier, ownerType, returnType, isOperator = true)
}
}
@@ -47,6 +47,6 @@ object CreateInvokeFunctionActionFactory : CreateCallableMemberFromUsageFactory<
}
val returnType = TypeInfo(element, Variance.OUT_VARIANCE)
return FunctionInfo(OperatorConventions.INVOKE.asString(), receiverType, returnType, emptyList(), parameters)
return FunctionInfo(OperatorConventions.INVOKE.asString(), receiverType, returnType, parameterInfos = parameters, isOperator = true)
}
}
@@ -30,7 +30,8 @@ import org.jetbrains.kotlin.psi.JetForExpression
import org.jetbrains.kotlin.types.JetTypeImpl
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.Variance
import java.util.Collections
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import java.util.*
object CreateIteratorFunctionActionFactory : CreateCallableMemberFromUsageFactory<JetForExpression>() {
override fun getElementOfInterest(diagnostic: Diagnostic): JetForExpression? {
@@ -56,6 +57,6 @@ object CreateIteratorFunctionActionFactory : CreateCallableMemberFromUsageFactor
returnJetTypeArguments,
returnJetType.memberScope)
val returnType = TypeInfo(newReturnJetType, Variance.OUT_VARIANCE)
return FunctionInfo("iterator", iterableType, returnType)
return FunctionInfo(OperatorConventions.ITERATOR.asString(), iterableType, returnType, isOperator = true)
}
}
@@ -39,6 +39,6 @@ public object CreateUnaryOperationActionFactory: CreateCallableMemberFromUsageFa
val receiverType = TypeInfo(receiverExpr, Variance.IN_VARIANCE)
val returnType = if (incDec) TypeInfo.ByReceiverType(Variance.OUT_VARIANCE) else TypeInfo(element, Variance.OUT_VARIANCE)
return FunctionInfo(operationName.asString(), receiverType, returnType)
return FunctionInfo(operationName.asString(), receiverType, returnType, isOperator = true)
}
}
@@ -1,7 +1,7 @@
// "Create member function 'compareTo'" "true"
class A<T>(val n: T) {
fun compareTo(t: T): Int {
operator fun compareTo(t: T): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'contains'" "true"
class A<T>(val n: T) {
fun contains(t: T): Boolean {
operator fun contains(t: T): Boolean {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'compareTo'" "true"
class A<T>(val n: T) {
fun compareTo(t: T): Int {
operator fun compareTo(t: T): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'contains'" "true"
class A<T>(val n: T) {
fun contains(t: T): Boolean {
operator fun contains(t: T): Boolean {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'plusAssign'" "true"
class A<T>(val n: T) {
fun plusAssign(t: T) {
operator fun plusAssign(t: T) {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -3,7 +3,7 @@
class A<T>(val n: T) {
fun plus(): A<T> = throw Exception()
fun plus(t: T): A<T> {
operator fun plus(t: T): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'plus'" "true"
class A<T>(val n: T) {
fun plus(t: T): A<T> {
operator fun plus(t: T): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -3,7 +3,7 @@
class A<T>(val n: T) {
fun plus(i: Int, s: String): A<T> = throw Exception()
fun plus(t: T): A<T> {
operator fun plus(t: T): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -6,6 +6,6 @@ fun test() {
val a: A<Int> = 2 + A(1)
}
fun Int.plus(a: A<Int>): A<Int> {
operator fun Int.plus(a: A<Int>): A<Int> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,7 +1,7 @@
// "Create member function 'plus'" "true"
class A<T>(val n: T) {
fun plus(t: T): A<T> {
operator fun plus(t: T): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'plus'" "true"
class A<T>(val n: T) {
fun plus(i: Int): A<T> {
operator fun plus(i: Int): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'contains'" "true"
class A<T>(val n: T) {
fun contains(t: T): Boolean {
operator fun contains(t: T): Boolean {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'contains'" "true"
class A<T>(val n: T) {
fun contains(t: T): Boolean {
operator fun contains(t: T): Boolean {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -3,7 +3,7 @@ class Foo<T> {
fun component1(): Int { return 0 }
fun component2(): Int { return 0 }
fun component3(): Any {
operator fun component3(): Any {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -3,7 +3,7 @@ class Foo<T> {
fun component1(): Int { return 0 }
fun component2(): Int { return 0 }
fun component3(): String {
operator fun component3(): String {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -17,6 +17,6 @@ fun foo() {
for ((i: Int, j: Int) in Foo<Int>()) { }
}
fun Any.component2(): Int {
operator fun Any.component2(): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -6,6 +6,6 @@ fun test(): A<String> {
return 1(2, "2")
}
fun Int.invoke(i: Int, s: String): A<String> {
operator fun Int.invoke(i: Int, s: String): A<String> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,7 +1,7 @@
// "Create member function 'invoke'" "true"
class A<T>(val n: T) {
fun invoke(t: T, s: String): B<String> {
operator fun invoke(t: T, s: String): B<String> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'invoke'" "true"
class A<T>(val n: T) {
fun <V> invoke(u: T, s: String): B<V> {
operator fun <V> invoke(u: T, s: String): B<V> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'invoke'" "true"
class A<T>(val n: T) {
fun invoke(abc: T, ghi: A<T>, def: String): A<T> {
operator fun invoke(abc: T, ghi: A<T>, def: String): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,6 +1,6 @@
// "Create member function 'iterator'" "true"
class Foo<T> {
fun iterator(): Iterator<T> {
operator fun iterator(): Iterator<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,6 +1,6 @@
// "Create member function 'iterator'" "true"
class Foo<T> {
fun iterator(): Iterator<String> {
operator fun iterator(): Iterator<String> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'inc'" "true"
class A<T>(val n: T) {
fun inc(): A<T> {
operator fun inc(): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -3,7 +3,7 @@
class A<T>(val n: T) {
fun minus(n: Int): A<T> = throw Exception()
fun minus(): A<T> {
operator fun minus(): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -4,6 +4,6 @@ fun test() {
val a = -false
}
fun Boolean.minus(): Any {
operator fun Boolean.minus(): Any {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,7 +1,7 @@
// "Create member function 'minus'" "true"
class A<T>(val n: T) {
fun minus(): Any {
operator fun minus(): Any {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
@@ -1,7 +1,7 @@
// "Create member function 'minus'" "true"
class A<T>(val n: T) {
fun minus(): A<T> {
operator fun minus(): A<T> {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}