Split ReplaceSingleLineLetInspection to SimpleRedundantLet & ComplexRedundantLet

Relates to #KT-32010
This commit is contained in:
Dmitry Gridin
2019-06-24 18:56:43 +07:00
parent 8e0bbe7d4a
commit b97aaf0f71
183 changed files with 1361 additions and 398 deletions
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.inspections.ComplexRedundantLetInspection
@@ -0,0 +1,8 @@
// PROBLEM: none
// WITH_RUNTIME
fun withAssign(arg: String?): String {
var result: String = ""
arg?.let<caret> { result = it }
return result
}
@@ -0,0 +1,5 @@
// PROBLEM: none
// WITH_RUNTIME
val x = 1
val y = x.<caret>let { it + it?.hashCode() }
@@ -0,0 +1,5 @@
// WITH_RUNTIME
fun test(list: List<Int>) {
list.filter { it > 1 }.filter { it > 2 }.let<caret> { println(it) }
}
@@ -0,0 +1,5 @@
// WITH_RUNTIME
fun test(list: List<Int>) {
println(list.filter { it > 1 }.filter { it > 2 })
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun test(list: List<Int>) {
list.filter { it > 1 }.filter { it > 2 }
.let<caret> { println(it) }
}
@@ -0,0 +1,5 @@
// WITH_RUNTIME
fun test(list: List<Int>) {
println(list.filter { it > 1 }.filter { it > 2 })
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun test(list: List<Int>) {
list.filter { it > 1 }.filter { it > 2 }.let<caret> {
println(it)
}
}
@@ -0,0 +1,5 @@
// WITH_RUNTIME
fun test(list: List<Int>) {
println(list.filter { it > 1 }.filter { it > 2 })
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
// HIGHLIGHT: INFORMATION
fun test(list: List<Int>) {
list.filter { it > 1 }
.filter { it > 2 }
.let<caret> { println(it) }
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
// HIGHLIGHT: INFORMATION
fun test(list: List<Int>) {
println(list.filter { it > 1 }
.filter { it > 2 })
}
@@ -0,0 +1,4 @@
// PROBLEM: none
// WITH_RUNTIME
fun isAlphaOrBeta(str: String) = str.let<caret> { it == "Alpha" || it == "Beta" }
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun test() {
(1 to 2).let<caret> { (i, j) -> foo() }
}
fun foo() = 0
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun test() {
foo()
}
fun foo() = 0
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun test() {
(1 to 2).let<caret> { (i, j) -> foo(1, 2) }
}
fun foo(i: Int, j: Int) = i + j
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun test() {
foo(1, 2)
}
fun foo(i: Int, j: Int) = i + j
@@ -0,0 +1,8 @@
// WITH_RUNTIME
// PROBLEM: none
fun test() {
(1 to 2).let<caret> { (i, j) -> foo(i, 3) }
}
fun foo(i: Int, j: Int) = i + j
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun test(k: Int) {
(1 to 2).let<caret> { (i, j) -> i + k }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun test() {
(1 to 2).let<caret> { (i, j) -> i.toLong() }
}
@@ -0,0 +1,6 @@
// PROBLEM: none
// WITH_RUNTIME
fun main(args: Array<String>) {
args[0].let<caret> { it.isBlank() && it.toByteOrNull() != null }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
s.let<caret> { foo("", 1) }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
<caret>foo("", 1)
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
s.let<caret> { foo(it, 1) }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
<caret>foo(s, 1)
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
s.let<caret> { foo("", it.length) }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
foo("", s.length)
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
s.let<caret> { x -> foo("", x.length) }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
foo("", s.length)
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
s.length.let<caret> { foo("", it) }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
foo("", s.length)
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
fun bar() = ""
bar().let<caret> { foo(it, 1) }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun test() {
fun bar() = ""
foo(bar(), 1)
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo(s: String, i: Int) = s.length + i
fun test() {
val s = ""
s.let<caret> { foo(it, it.length) }
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun String.baz(): Int {
return let<caret> { foo(it, 1) }
}
@@ -0,0 +1,7 @@
// WITH_RUNTIME
fun foo(s: String, i: Int) = s.length + i
fun String.baz(): Int {
return foo(this, 1)
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo(s: String, i: Int) = s.length + i
fun test() {
val nullable: String? = null
nullable?.let<caret> { foo(it, 1) }
}
@@ -0,0 +1,7 @@
// PROBLEM: none
// WITH_RUNTIME
class Foo(val bar: () -> Int)
fun bar(foo: Foo?) {
foo?.<caret>let { it.bar() }
}
@@ -0,0 +1,7 @@
// PROBLEM: none
// WITH_RUNTIME
class Foo(val bar: () -> Int)
fun bar(foo: Foo?) {
foo?.<caret>let { it.bar.invoke() }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo(list: List<Int>) {
list.filter { it.let<caret> { it in 1000..3000 } }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo(list: List<Int>) {
list.filter { it in 1000..3000 }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo(list: List<Int>) {
list.filter { it.let<caret> { value -> value in value..3000 } }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo(list: List<Int>) {
list.filter { it.let<caret> { it in IntRange(1, 10) } }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo(list: List<Int>) {
list.filter { it in IntRange(1, 10) }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo(list: List<Int>) {
list.filter { it.let<caret> { it in IntRange(it - 1, 10) } }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class A {
operator fun invoke() {}
}
fun foo(a: A) {
a.<caret>let { it() }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class A {
operator fun invoke() {}
}
fun foo(a: A) {
a()
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class A {
operator fun invoke() {}
}
fun foo(a: A) {
a.<caret>let { b -> b() }
}
@@ -0,0 +1,8 @@
// WITH_RUNTIME
class A {
operator fun invoke() {}
}
fun foo(a: A) {
a()
}
@@ -0,0 +1,9 @@
// PROBLEM: none
// WITH_RUNTIME
class A {
operator fun invoke() {}
}
fun foo(a: A) {
a.<caret>let { b -> b.invoke() }
}
@@ -0,0 +1,9 @@
// PROBLEM: none
// WITH_RUNTIME
class A {
operator fun invoke(a: A, i: Int) {}
}
fun foo(a: A) {
a.<caret>let { it(it, 1) }
}
@@ -0,0 +1,9 @@
// PROBLEM: none
// WITH_RUNTIME
class A {
operator fun invoke() {}
}
fun foo(a: A) {
(1 to a).<caret>let { (i, b) -> b() }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun baz(foo: String) {
foo.let<caret> { it.indexOfLast { c -> c == it[0] } + 1 }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun baz(foo: String) {
foo.let<caret> { it.length + "".indexOfLast { c -> c == it[0] } }
}
@@ -0,0 +1,10 @@
// PROBLEM: none
// WITH_RUNTIME
fun foo() {
val foo: String? = null
foo?.let<caret> {
it.length
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
it.length<caret>
it.length
}
}
@@ -0,0 +1,10 @@
// PROBLEM: none
// WITH_RUNTIME
fun foo() {
val foo: String = ""
foo.let<caret> {
it.length
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
text ->
"".to("")<caret>
}
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
"".to("")<caret>
}
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
it.to(it)<caret>
}
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
"".let<caret> { it.length + "".indexOf(it) }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
"".let<caret> { it.length + it.length }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
"".let<caret> { it.substring(0, 1) + it }
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
it.to(it).to("").to("")<caret>
}
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
it.to("").to(it).to("")<caret>
}
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
it.to("").to("").to(it)<caret>
}
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo() {
val foo: String? = null
foo?.let {
text ->
text.to(text)<caret>
}
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
"".let<caret> { it.length + 1 }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
"".length + 1
}
@@ -0,0 +1,10 @@
// PROBLEM: none
// WITH_RUNTIME
fun foo() {
val foo: String? = null
foo?.let<caret> {
it.to("")
}
}
@@ -0,0 +1,10 @@
// PROBLEM: none
// WITH_RUNTIME
fun foo() {
val foo: String? = null
foo?.let<caret> {
it.hashCode().hashCode()
}
}
@@ -0,0 +1,11 @@
// PROBLEM: none
// WITH_RUNTIME
fun foo() {
val foo: String? = null
foo?.let<caret> {
text ->
text.length
}
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
"".let<caret> { it + 1 }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun foo() {
"" + 1
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun Int.foo() {
let<caret> { it.dec() + 1 }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun Int.foo() {
dec() + 1
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun Int.foo() {
let<caret> { it + 1 }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
fun Int.foo() {
this + 1
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// HIGHLIGHT: INFORMATION
fun test(list: List<Int>) {
list.filter { it > 1 }.filter { it > 2 }.filter { it > 3 }.let<caret> { println(it) }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// HIGHLIGHT: INFORMATION
fun test(list: List<Int>) {
println(list.filter { it > 1 }.filter { it > 2 }.filter { it > 3 })
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun baz(foo: String) {
foo.let<caret> { it.substringAfterLast(it.capitalize()) }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun baz(foo: String) {
foo.let<caret> { it.substringAfterLast("".equals(it).toString()) }
}
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun baz(foo: String) {
foo.let<caret> { it.substring(0, it.length) }
}
@@ -0,0 +1,8 @@
// PROBLEM: none
// WITH_RUNTIME
fun foo(s: String) {
if (s.substring(1).let<caret> { it.startsWith("a") || it[1].isLowerCase() }) {
}
}
@@ -0,0 +1,8 @@
// PROBLEM: none
// WITH_RUNTIME
fun String.test(): Int {
return let<caret> {
it.length
}
}
@@ -0,0 +1,4 @@
// PROBLEM: none
// WITH_RUNTIME
fun plusNullable(arg: String?) = arg?.let<caret> { it + "#" } ?: ""
@@ -0,0 +1,6 @@
// WITH_RUNTIME
// PROBLEM: none
fun baz(foo: String) {
foo.let<caret> { it.indexOfLast { c -> c == it[0] } }
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// PROBLEM: none
// This should be reported. However, in order to avoid too complicate logic, the intention ignore this case.
import java.util.*
fun baz2(foo: List<String>) {
foo.let<caret> { it.binarySearch("", Comparator<kotlin.String> { o1, o2 -> 0 }) }
}
@@ -0,0 +1,12 @@
// PROBLEM: none
// WITH_RUNTIME
fun foo() {
val foo: String? = null
foo?.toString()?.let<caret> {
it.to("")
}?.let {
it.to("")
}
}
@@ -0,0 +1,8 @@
// PROBLEM: none
// WITH_RUNTIME
fun test(s: String?): Int? {
return s?.let<caret> {
it.length
}
}
@@ -0,0 +1,15 @@
// PROBLEM: none
// WITH_RUNTIME
interface A
interface B : A {
val bar: Any?
}
class Foo {
private val a: A = object : A {}
val isB: Boolean
get() = a.let<caret> { it is B && it.bar != null }
}
@@ -0,0 +1,7 @@
// PROBLEM: none
// WITH_RUNTIME
fun Int.foo(): Int {
return <caret>let { it.hashCode().hashCode() }
}
@@ -0,0 +1,7 @@
// PROBLEM: none
// WITH_RUNTIME
fun Int.foo(): Int {
return <caret>let { it.hashCode() }
}
@@ -0,0 +1,9 @@
// PROBLEM: none
// WITH_RUNTIME
interface Base
class A : Base
class B : Base
fun isAB(arg: Base) = arg.let<caret> { it is A || it is B }