[FIR] Add CanBeReplacedWithOperatorAssignmentChecker

This commit is contained in:
vldf
2020-07-22 10:31:34 +03:00
committed by Mikhail Glukhikh
parent fa8c6e7fb6
commit eadd3f00f2
46 changed files with 424 additions and 8 deletions
@@ -0,0 +1,7 @@
fun goo() {
var a = 2
val b = 4
a <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> a + 1 + b
a <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> (a + 1)
a = a * b + 1
}
@@ -0,0 +1,8 @@
FILE: BasicTest.kt
public final fun goo(): R|kotlin/Unit| {
lvar a: R|kotlin/Int| = Int(2)
lval b: R|kotlin/Int| = Int(4)
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Int.plus|(R|<local>/b|)
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(1))
R|<local>/a| = R|<local>/a|.R|kotlin/Int.times|(R|<local>/b|).R|kotlin/Int.plus|(Int(1))
}
@@ -0,0 +1,4 @@
fun foo() {
var a = 0
a = (a + 1) / 2
}
@@ -0,0 +1,5 @@
FILE: ComplexExpression.kt
public final fun foo(): R|kotlin/Unit| {
lvar a: R|kotlin/Int| = Int(0)
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Int.div|(Int(2))
}
@@ -0,0 +1,4 @@
fun foo() {
var a = 0
a += 10 + a
}
@@ -0,0 +1,5 @@
FILE: OperatorAssignment.kt
public final fun foo(): R|kotlin/Unit| {
lvar a: R|kotlin/Int| = Int(0)
R|<local>/a| = R|<local>/a|.R|kotlin/Int.plus|(Int(10).R|kotlin/Int.plus|(R|<local>/a|))
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
var list1 = java.util.Collections.emptyList<String>()
val list2 = listOf("b")
list1 = list1 + list2
}
@@ -0,0 +1,6 @@
FILE: flexibleTypeBug.kt
public final fun foo(): R|kotlin/Unit| {
lvar list1: R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>!>, kotlin/collections/List<ft<kotlin/String, kotlin/String?>!>?>!| = Q|java/util/Collections|.R|java/util/Collections.emptyList|<R|ft<kotlin/String, kotlin/String?>!|>()
lval list2: R|kotlin/collections/List<kotlin/String>| = R|kotlin/collections/listOf|<R|kotlin/String|>(String(b))
R|<local>/list1| = R|<local>/list1|.R|kotlin/collections/plus|<R|ft<kotlin/String, kotlin/String?>!|>(R|<local>/list2|)
}
@@ -0,0 +1,4 @@
fun foo() {
var x = 0
x = x / 1 + 1
}
@@ -0,0 +1,5 @@
FILE: illegalMultipleOperators.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/x|.R|kotlin/Int.div|(Int(1)).R|kotlin/Int.plus|(Int(1))
}
@@ -0,0 +1,5 @@
fun foo() {
var x = 0
val y = 0
x = y / x + 0
}
@@ -0,0 +1,6 @@
FILE: illegalMultipleOperatorsMiddle.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
lval y: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/y|.R|kotlin/Int.div|(R|<local>/x|).R|kotlin/Int.plus|(Int(0))
}
@@ -0,0 +1,4 @@
fun foo() {
var x = 0
x = 1 - x
}
@@ -0,0 +1,5 @@
FILE: invalidSubtraction.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
R|<local>/x| = Int(1).R|kotlin/Int.minus|(R|<local>/x|)
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo() {
var list = listOf(1, 2, 3)
// Should not be highlighted because it's the way we use to say explicitly
// "yes, we want to re-assign this immutable list"
list = list + 4
}
@@ -0,0 +1,5 @@
FILE: list.kt
public final fun foo(): R|kotlin/Unit| {
lvar list: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(vararg(Int(1), Int(2), Int(3)))
R|<local>/list| = R|<local>/list|.R|kotlin/collections/plus|<R|kotlin/Int|>(Int(4))
}
@@ -0,0 +1,5 @@
fun foo() {
var x = 0
var y = 0
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x + y + 5
}
@@ -0,0 +1,6 @@
FILE: multipleOperators.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
lvar y: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/x|.R|kotlin/Int.plus|(R|<local>/y|).R|kotlin/Int.plus|(Int(5))
}
@@ -0,0 +1,5 @@
fun foo() {
var x = 0
var y = 0
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> y + x + 5
}
@@ -0,0 +1,6 @@
FILE: multipleOperatorsRightSideRepeat.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
lvar y: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/y|.R|kotlin/Int.plus|(R|<local>/x|).R|kotlin/Int.plus|(Int(5))
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
fun foo() {
var listVar = mutableListOf(1, 2, 3)
// now, Idea hightlights this code like error (cuz listVar
// is mutable and listVar + 4 is immutable) and like warning
// (cuz can be replaced with +=)
listVar = listVar + 4
}
@@ -0,0 +1,5 @@
FILE: mutableList.kt
public final fun foo(): R|kotlin/Unit| {
lvar listVar: R|kotlin/collections/MutableList<kotlin/Int>| = R|kotlin/collections/mutableListOf|<R|kotlin/Int|>(vararg(Int(1), Int(2), Int(3)))
R|<local>/listVar| = R|<local>/listVar|.R|kotlin/collections/plus|<R|kotlin/Int|>(Int(4))
}
@@ -0,0 +1,8 @@
fun foo() {
var x = 0
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x - 1 - 1
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x / 1
x = 1 / x
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> -1 + x
}
@@ -0,0 +1,8 @@
FILE: nonCommutativeRepeat.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/x|.R|kotlin/Int.minus|(Int(1)).R|kotlin/Int.minus|(Int(1))
R|<local>/x| = R|<local>/x|.R|kotlin/Int.div|(Int(1))
R|<local>/x| = Int(1).R|kotlin/Int.div|(R|<local>/x|)
R|<local>/x| = Int(1).R|kotlin/Int.unaryMinus|().R|kotlin/Int.plus|(R|<local>/x|)
}
@@ -0,0 +1,6 @@
fun foo() {
var x = 0
val y = 0
val z = 0
x = y + z
}
@@ -0,0 +1,7 @@
FILE: nonRepeatingAssignment.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
lval y: R|kotlin/Int| = Int(0)
lval z: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/y|.R|kotlin/Int.plus|(R|<local>/z|)
}
@@ -0,0 +1,10 @@
class A
operator fun A.plus(a: A): A = A()
operator fun A.plusAssign(a: A){}
fun foo() {
var a1 = A()
val a2 = A()
a1 = a1 + a2
}
@@ -0,0 +1,17 @@
FILE: plusAssignConflict.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
public final operator fun R|A|.plus(a: R|A|): R|A| {
^plus R|/A.A|()
}
public final operator fun R|A|.plusAssign(a: R|A|): R|kotlin/Unit| {
}
public final fun foo(): R|kotlin/Unit| {
lvar a1: R|A| = R|/A.A|()
lval a2: R|A| = R|/A.A|()
R|<local>/a1| = R|<local>/a1|.R|/plus|(R|<local>/a2|)
}
@@ -0,0 +1,4 @@
fun foo() {
var x = 0
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> 1 + x
}
@@ -0,0 +1,5 @@
FILE: rightSideRepeat.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
R|<local>/x| = Int(1).R|kotlin/Int.plus|(R|<local>/x|)
}
@@ -0,0 +1,5 @@
fun foo() {
var y = 0
val x = 0
y <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> y + x
}
@@ -0,0 +1,6 @@
FILE: simpleAssign.kt
public final fun foo(): R|kotlin/Unit| {
lvar y: R|kotlin/Int| = Int(0)
lval x: R|kotlin/Int| = Int(0)
R|<local>/y| = R|<local>/y|.R|kotlin/Int.plus|(R|<local>/x|)
}
@@ -0,0 +1,4 @@
fun foo() {
var x = 0
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x + 1
}
@@ -0,0 +1,5 @@
FILE: validAddition.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/x|.R|kotlin/Int.plus|(Int(1))
}
@@ -0,0 +1,4 @@
fun foo() {
var x = 0
x <!CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT!>=<!> x - 1
}
@@ -0,0 +1,5 @@
FILE: validSubtraction.kt
public final fun foo(): R|kotlin/Unit| {
lvar x: R|kotlin/Int| = Int(0)
R|<local>/x| = R|<local>/x|.R|kotlin/Int.minus|(Int(1))
}