Report warning on unary plus()/minus()

This commit is contained in:
Yan Zhulanow
2015-10-12 18:37:28 +03:00
parent 58cbf09232
commit b2470a6aad
16 changed files with 75 additions and 36 deletions
@@ -29,6 +29,11 @@ import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.OperatorNameConventions.PLUS
import org.jetbrains.kotlin.util.OperatorNameConventions.MINUS
import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_PLUS
import org.jetbrains.kotlin.util.OperatorNameConventions.UNARY_MINUS
public class OperatorValidator : SymbolUsageValidator {
@@ -61,10 +66,24 @@ public class OperatorValidator : SymbolUsageValidator {
return
}
if (isConventionOperator() || isArrayAccessExpression()) {
val isConventionOperator = isConventionOperator()
if (isConventionOperator || isArrayAccessExpression()) {
if (!functionDescriptor.isOperator) {
report(jetElement, functionDescriptor, trace)
}
if (isConventionOperator && call != null) {
checkDeprecatedUnaryConventions(call, functionDescriptor, trace)
}
}
}
private fun checkDeprecatedUnaryConventions(call: Call, functionDescriptor: FunctionDescriptor, sink: DiagnosticSink) {
(call.callElement as? JetPrefixExpression)?.let { expr ->
val functionName = functionDescriptor.name
if (functionName == PLUS || functionName == MINUS) {
val newName = if (functionName == PLUS) UNARY_PLUS else UNARY_MINUS
sink.report(Errors.DEPRECATED_UNARY_PLUS_MINUS.on(expr, functionDescriptor, newName.asString()))
}
}
}
+1 -1
View File
@@ -93,7 +93,7 @@ abstract class Tag(val name : String) : Element() {
}
abstract class TagWithText(name : String) : Tag(name) {
operator fun String.plus() {
operator fun String.unaryPlus() {
children.add(TextElement(this))
}
}
+12 -12
View File
@@ -24,7 +24,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class B : html.BodyTag {
@@ -43,7 +43,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class Body : html.BodyTag {
@@ -62,7 +62,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public abstract class BodyTag : html.TagWithText {
@@ -81,7 +81,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public abstract class Element {
@@ -108,7 +108,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class HTML : html.TagWithText {
@@ -124,7 +124,7 @@ package html {
public open override /*1*/ /*fake_override*/ fun render(/*0*/ builder: java.lang.StringBuilder, /*1*/ indent: kotlin.String): kotlin.Unit
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class Head : html.TagWithText {
@@ -139,7 +139,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public final fun title(/*0*/ init: html.Title.() -> kotlin.Unit): html.Title
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class LI : html.BodyTag {
@@ -158,7 +158,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class P : html.BodyTag {
@@ -177,7 +177,7 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public abstract class Tag : html.Element {
@@ -204,7 +204,7 @@ package html {
public open override /*1*/ /*fake_override*/ fun render(/*0*/ builder: java.lang.StringBuilder, /*1*/ indent: kotlin.String): kotlin.Unit
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final operator fun kotlin.String.plus(): kotlin.Unit
public final operator fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class TextElement : html.Element {
@@ -227,7 +227,7 @@ package html {
public open override /*1*/ /*fake_override*/ fun render(/*0*/ builder: java.lang.StringBuilder, /*1*/ indent: kotlin.String): kotlin.Unit
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
public final class UL : html.BodyTag {
@@ -247,6 +247,6 @@ package html {
invisible_fake final override /*1*/ /*fake_override*/ fun renderAttributes(): kotlin.String?
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final override /*1*/ /*fake_override*/ fun ul(/*0*/ init: html.UL.() -> kotlin.Unit): html.UL
public final override /*1*/ /*fake_override*/ fun kotlin.String.plus(): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun kotlin.String.unaryPlus(): kotlin.Unit
}
}
@@ -15,8 +15,18 @@ operator fun String.unaryPlus(): Int = 0
fun test() {
requireInt(+ "")
requireInt(+ Example())
requireString(+ ExampleDeprecated())
requireString(<!DEPRECATED_UNARY_PLUS_MINUS!>+ ExampleDeprecated()<!>)
}
fun requireInt(n: Int) {}
fun requireString(s: String) {}
fun requireString(s: String) {}
class Example2 {
operator fun plus() = this
operator fun minus() = this
fun test() {
<!DEPRECATED_UNARY_PLUS_MINUS!>+this<!>
<!DEPRECATED_UNARY_PLUS_MINUS!>-this<!>
}
}
@@ -15,6 +15,16 @@ public final class Example {
public final operator fun unaryPlus(): kotlin.Int
}
public final class Example2 {
public constructor Example2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun minus(): Example2
public final operator fun plus(): Example2
public final fun test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class ExampleDeprecated {
public constructor ExampleDeprecated()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -33,7 +33,7 @@ class MyProperty<R, T> {
}
}
operator fun <R, T> MyProperty<R, T>.plus() = MyProperty<R, T>()
operator fun <R, T> MyProperty<R, T>.unaryPlus() = MyProperty<R, T>()
operator fun <R, T> MyProperty<R, T>.minus(<!UNUSED_PARAMETER!>i<!>: Int) = MyProperty<R, T>()
object O {
@@ -6,7 +6,7 @@ package baz {
public fun </*0*/ A, /*1*/ B> getMyProperty(): baz.MyProperty<A, B>
public fun println(/*0*/ a: kotlin.Any?): kotlin.Any?
public operator fun </*0*/ R, /*1*/ T> baz.MyProperty<R, T>.minus(/*0*/ i: kotlin.Int): baz.MyProperty<R, T>
public operator fun </*0*/ R, /*1*/ T> baz.MyProperty<R, T>.plus(): baz.MyProperty<R, T>
public operator fun </*0*/ R, /*1*/ T> baz.MyProperty<R, T>.unaryPlus(): baz.MyProperty<R, T>
public final class A {
public constructor A(/*0*/ outer: baz.Outer)
@@ -1,12 +1,12 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -VAL_REASSIGNMENT -UNUSED_CHANGED_VALUE -VARIABLE_EXPECTED
inline operator fun <T, V> Function1<T, V>.plus() = <!USAGE_IS_NOT_INLINABLE!>this<!>
operator fun <T, V> Function1<T, V>.minus() = this
inline operator fun <T, V> Function1<T, V>.unaryPlus() = <!USAGE_IS_NOT_INLINABLE!>this<!>
operator fun <T, V> Function1<T, V>.unaryMinus() = this
inline operator fun <T, V> Function1<T, V>.inc() = <!USAGE_IS_NOT_INLINABLE!>this<!>
operator fun <T, V> Function1<T, V>.dec() = this
inline operator fun <T, V> @Extension Function2<T, T, V>.plus(){}
operator fun <T, V> @Extension Function2<T, T, V>.minus(){}
inline operator fun <T, V> @Extension Function2<T, T, V>.unaryPlus(){}
operator fun <T, V> @Extension Function2<T, T, V>.unaryMinus(){}
inline operator fun <T, V> @Extension Function2<T, T, V>.inc() = <!USAGE_IS_NOT_INLINABLE!>this<!>
operator fun <T, V> @Extension Function2<T, T, V>.dec() = this
@@ -6,7 +6,7 @@ public operator fun </*0*/ T, /*1*/ V> (T.(T) -> V).dec(): T.(T) -> V
@kotlin.inline() public operator fun </*0*/ T, /*1*/ V> ((T) -> V).inc(): (T) -> V
@kotlin.inline() public operator fun </*0*/ T, /*1*/ V> (T.(T) -> V).inc(): T.(T) -> V
@kotlin.inline() public fun </*0*/ T, /*1*/ V> ((T) -> V).inlineFunWithInvoke(): kotlin.Unit
public operator fun </*0*/ T, /*1*/ V> ((T) -> V).minus(): (T) -> V
public operator fun </*0*/ T, /*1*/ V> (T.(T) -> V).minus(): kotlin.Unit
@kotlin.inline() public operator fun </*0*/ T, /*1*/ V> ((T) -> V).plus(): (T) -> V
@kotlin.inline() public operator fun </*0*/ T, /*1*/ V> (T.(T) -> V).plus(): kotlin.Unit
public operator fun </*0*/ T, /*1*/ V> ((T) -> V).unaryMinus(): (T) -> V
public operator fun </*0*/ T, /*1*/ V> (T.(T) -> V).unaryMinus(): kotlin.Unit
@kotlin.inline() public operator fun </*0*/ T, /*1*/ V> ((T) -> V).unaryPlus(): (T) -> V
@kotlin.inline() public operator fun </*0*/ T, /*1*/ V> (T.(T) -> V).unaryPlus(): kotlin.Unit
@@ -1,6 +1,6 @@
class A() {
operator infix fun plus(<!UNUSED_PARAMETER!>i<!> : Int) {}
operator fun minus() {}
operator fun unaryMinus() {}
operator infix fun contains(<!UNUSED_PARAMETER!>a<!> : Any?) : Boolean = true
}
@@ -20,8 +20,8 @@ fun test(x : Int?, a : A?) {
a <!UNSAFE_INFIX_CALL!>plus<!> 1
a <!UNSAFE_INFIX_CALL!>+<!> 1
<!UNSAFE_CALL!>-<!>a
a<!UNSAFE_CALL!>.<!>minus()
a?.minus()
a<!UNSAFE_CALL!>.<!>unaryMinus()
a?.unaryMinus()
a<!UNSAFE_CALL!>.<!>div(1)
a <!UNSAFE_INFIX_CALL!>/<!> 1
@@ -9,7 +9,7 @@ public final class A {
public final operator infix fun contains(/*0*/ a: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun minus(): kotlin.Unit
public final operator infix fun plus(/*0*/ i: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final operator fun unaryMinus(): kotlin.Unit
}
@@ -3,7 +3,7 @@
public class A {
public operator fun get(vararg attrs : Pair<String, String>) : A = this
}
operator fun String.plus() : A = A()
operator fun String.unaryPlus() : A = A()
operator fun A.div(s : String) : A = A()
fun test() {
@@ -3,8 +3,8 @@ package
public val x: B
public fun test(): kotlin.Unit
public operator fun A.div(/*0*/ s: kotlin.String): A
public operator fun kotlin.String.plus(): A
public infix fun </*0*/ A, /*1*/ B> A.to(/*0*/ that: B): Pair<A, B>
public operator fun kotlin.String.unaryPlus(): A
public final class A {
public constructor A()
@@ -27,7 +27,7 @@ fun dynamic.test() {
<!DEBUG_INFO_DYNAMIC!>this<!>()
C() + C()
<!NO_VALUE_FOR_PARAMETER!>+<!>C()
<!DEPRECATED_UNARY_PLUS_MINUS!><!NO_VALUE_FOR_PARAMETER!>+<!>C()<!>
this <!DEBUG_INFO_DYNAMIC!>+<!> C()
+1 -1
View File
@@ -24,7 +24,7 @@ import java.util.*
}
abstract class TagWithText(name : String) : Tag(name) {
operator fun String.plus() {
operator fun String.unaryPlus() {
children.add(TextElement(this))
}
}
+2 -2
View File
@@ -7,7 +7,7 @@ class MyClass {
@Deprecated("Use A instead") operator fun MyClass.times(i: MyClass) { i.i }
@Deprecated("Use A instead") operator fun MyClass.not() { }
@Deprecated("Use A instead") operator fun MyClass.plus() { }
@Deprecated("Use A instead") operator fun MyClass.unaryPlus() { }
@Deprecated("Use A instead") operator fun MyClass.contains(i: MyClass): Boolean { i.i; return false }
@@ -24,7 +24,7 @@ fun test() {
x1 <warning descr="[DEPRECATION] 'times(MyClass): Unit' is deprecated. Use A instead">*</warning> x2
<warning descr="[DEPRECATION] 'not(): Unit' is deprecated. Use A instead">!</warning>x1
<warning descr="[DEPRECATION] 'plus(): Unit' is deprecated. Use A instead">+</warning>x1
<warning descr="[DEPRECATION] 'unaryPlus(): Unit' is deprecated. Use A instead">+</warning>x1
x1 <warning descr="[DEPRECATION] 'contains(MyClass): Boolean' is deprecated. Use A instead">in</warning> x2
x1 <warning descr="[DEPRECATION] 'contains(MyClass): Boolean' is deprecated. Use A instead">!in</warning> x2