RedundantUnitExpressionInspection: support lambdas
#KT-39772 Fixed
This commit is contained in:
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
|||||||
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.previousStatement
|
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.previousStatement
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
|
import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
||||||
@@ -48,16 +47,14 @@ class RedundantUnitExpressionInspection : AbstractKotlinInspection(), CleanupLoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parent is KtBlockExpression) {
|
if (parent is KtBlockExpression) {
|
||||||
// Do not report just 'Unit' in function literals (return@label Unit is OK even in literals)
|
|
||||||
if (parent.getParentOfType<KtFunctionLiteral>(strict = true) != null) return false
|
|
||||||
|
|
||||||
if (referenceExpression == parent.lastBlockStatementOrThis()) {
|
if (referenceExpression == parent.lastBlockStatementOrThis()) {
|
||||||
val prev = referenceExpression.previousStatement() ?: return true
|
val prev = referenceExpression.previousStatement() ?: return true
|
||||||
if (prev.isUnitLiteral()) return true
|
if (prev.isUnitLiteral()) return true
|
||||||
val prevType = prev.resolveToCall(BodyResolveMode.FULL)?.resultingDescriptor?.returnType
|
val prevType = prev.analyze(BodyResolveMode.PARTIAL).getType(prev)
|
||||||
if (prevType != null) {
|
if (prevType != null) {
|
||||||
return prevType.isUnit()
|
return prevType.isUnit()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev !is KtDeclaration) return false
|
if (prev !is KtDeclaration) return false
|
||||||
if (prev !is KtFunction) return true
|
if (prev !is KtFunction) return true
|
||||||
return parent.getParentOfTypesAndPredicate(
|
return parent.getParentOfTypesAndPredicate(
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// PROBLEM: none
|
|
||||||
fun test(b: Boolean): Unit = if (b) {
|
fun test(b: Boolean): Unit = if (b) {
|
||||||
fun a() = 1
|
fun a() = 1
|
||||||
<caret>Unit
|
<caret>Unit
|
||||||
|
|||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun test(b: Boolean): Unit = if (b) {
|
||||||
|
fun a() = 1
|
||||||
|
} else {
|
||||||
|
}
|
||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// PROBLEM: none
|
|
||||||
fun test(b: Boolean): Unit = when (b) {
|
fun test(b: Boolean): Unit = when (b) {
|
||||||
true -> {
|
true -> {
|
||||||
fun a() {}
|
fun a() {}
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
fun test(b: Boolean): Unit = when (b) {
|
||||||
|
true -> {
|
||||||
|
fun a() {}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun nonUnit(p: Int): Int = p
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = TODO()
|
||||||
|
|
||||||
|
fun g(p: String?) {
|
||||||
|
println(1)
|
||||||
|
nonUnit(2)
|
||||||
|
|
||||||
|
p?.let {
|
||||||
|
println(3)
|
||||||
|
nonUnit(4)
|
||||||
|
Unit<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun h() {
|
||||||
|
println(5)
|
||||||
|
nonUnit(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun x() = doIt {
|
||||||
|
println(7)
|
||||||
|
nonUnit(8)
|
||||||
|
Unit
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun nonUnit(p: Int): Int = p
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = TODO()
|
||||||
|
|
||||||
|
fun g(p: String?) {
|
||||||
|
println(1)
|
||||||
|
nonUnit(2)
|
||||||
|
|
||||||
|
p?.let {
|
||||||
|
println(3)
|
||||||
|
nonUnit(4)
|
||||||
|
Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun h() {
|
||||||
|
println(5)
|
||||||
|
nonUnit(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun x() = doIt {
|
||||||
|
println(7)
|
||||||
|
nonUnit(8)
|
||||||
|
Unit<caret>
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = p()
|
||||||
|
fun Any.doDo() = Unit
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract fun a()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override fun a() = doIt {
|
||||||
|
null?.doDo()
|
||||||
|
Unit<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = p()
|
||||||
|
fun Any.doDo() = Unit
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract fun a()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override fun a() = doIt {
|
||||||
|
1.let { it.let { it.let { it.let { null?.doDo() } } } }
|
||||||
|
Unit<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = TODO()
|
||||||
|
|
||||||
|
fun g(p: String?) {
|
||||||
|
|
||||||
|
p?.let { Unit<caret> }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun h() = Unit
|
||||||
|
|
||||||
|
fun x() = doIt { Unit }
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = TODO()
|
||||||
|
|
||||||
|
fun g(p: String?) {
|
||||||
|
|
||||||
|
p?.let { <caret>}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun h() = Unit
|
||||||
|
|
||||||
|
fun x() = doIt { Unit }
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = TODO()
|
||||||
|
|
||||||
|
fun g(p: String?) {
|
||||||
|
|
||||||
|
p?.let { Unit }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun h() = Unit
|
||||||
|
|
||||||
|
fun x() = doIt { Unit<caret> }
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun <T> doIt(p: () -> T): T = TODO()
|
||||||
|
|
||||||
|
fun g(p: String?) {
|
||||||
|
|
||||||
|
p?.let { Unit }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun h() = Unit
|
||||||
|
|
||||||
|
fun x() = doIt { <caret>}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// PROBLEM: none
|
||||||
|
// not yet supported
|
||||||
|
fun <T> doIt(p: () -> T): T = TODO()
|
||||||
|
|
||||||
|
fun x() = doIt<Unit> {
|
||||||
|
4
|
||||||
|
Unit<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun <T> doIt(p: () -> T): T = p()
|
||||||
|
fun Any.doDo() = Unit
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract fun a()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override fun a() = doIt {
|
||||||
|
1.let { it.let { it.let { it.let { it.doDo() } } } }
|
||||||
|
Unit<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun <T> doIt(p: () -> T): T = p()
|
||||||
|
fun Any.doDo() = Unit
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract fun a()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override fun a() = doIt {
|
||||||
|
1.let { it.let { it.let { it.let { it.doDo() } } } }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun <T> doIt(p: () -> T): T = p()
|
||||||
|
fun Any.doDo() = Unit
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract fun a()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override fun a() = doIt {
|
||||||
|
1.let { it.let { it.let { it.let { it?.doDo() } } } }
|
||||||
|
Unit<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun <T> doIt(p: () -> T): T = p()
|
||||||
|
fun Any.doDo() = Unit
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract fun a()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override fun a() = doIt {
|
||||||
|
1.let { it.let { it.let { it.let { it?.doDo() } } } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+45
@@ -8768,6 +8768,26 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/notRedundant3.kt");
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/notRedundant3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notRedundant4.kt")
|
||||||
|
public void testNotRedundant4() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/notRedundant4.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notRedundant5.kt")
|
||||||
|
public void testNotRedundant5() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/notRedundant5.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notRedundant6.kt")
|
||||||
|
public void testNotRedundant6() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/notRedundant6.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notRedundant7.kt")
|
||||||
|
public void testNotRedundant7() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/notRedundant7.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("redundant1.kt")
|
@TestMetadata("redundant1.kt")
|
||||||
public void testRedundant1() throws Exception {
|
public void testRedundant1() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/redundant1.kt");
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/redundant1.kt");
|
||||||
@@ -8797,6 +8817,31 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
public void testReturnAsNullableUnit() throws Exception {
|
public void testReturnAsNullableUnit() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/returnAsNullableUnit.kt");
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/returnAsNullableUnit.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unitReturnType.kt")
|
||||||
|
public void testUnitReturnType() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/unitReturnType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unitReturnType2.kt")
|
||||||
|
public void testUnitReturnType2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/unitReturnType2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unitReturnType3.kt")
|
||||||
|
public void testUnitReturnType3() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/unitReturnType3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unitReturnType4.kt")
|
||||||
|
public void testUnitReturnType4() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/unitReturnType4.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unitReturnType5.kt")
|
||||||
|
public void testUnitReturnType5() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/redundantUnitExpression/unitReturnType5.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/redundantVisibilityModifier")
|
@TestMetadata("idea/testData/inspectionsLocal/redundantVisibilityModifier")
|
||||||
|
|||||||
Reference in New Issue
Block a user