FoldInitializerAndIfToElvisInspection: don't report when 'var' variable has no explicit type and it's used as not nullable type
#KT-38349 Fixed
This commit is contained in:
committed by
Yan Zhulanow
parent
db140b2815
commit
915dc6ce91
+14
@@ -29,14 +29,19 @@ import org.jetbrains.kotlin.idea.util.hasComments
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange
|
import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.types.isError
|
import org.jetbrains.kotlin.types.isError
|
||||||
|
import org.jetbrains.kotlin.types.isNullable
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class FoldInitializerAndIfToElvisInspection : AbstractApplicabilityBasedInspection<KtIfExpression>(KtIfExpression::class.java) {
|
class FoldInitializerAndIfToElvisInspection : AbstractApplicabilityBasedInspection<KtIfExpression>(KtIfExpression::class.java) {
|
||||||
override fun inspectionText(element: KtIfExpression): String = KotlinBundle.message("if.null.return.break.foldable.to")
|
override fun inspectionText(element: KtIfExpression): String = KotlinBundle.message("if.null.return.break.foldable.to")
|
||||||
@@ -137,6 +142,15 @@ class FoldInitializerAndIfToElvisInspection : AbstractApplicabilityBasedInspecti
|
|||||||
val checkedType = ifExpression.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, typeReference]
|
val checkedType = ifExpression.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, typeReference]
|
||||||
val variableType = (prevStatement.resolveToDescriptorIfAny() as? VariableDescriptor)?.type
|
val variableType = (prevStatement.resolveToDescriptorIfAny() as? VariableDescriptor)?.type
|
||||||
if (checkedType != null && variableType != null && !checkedType.isSubtypeOf(variableType)) return null
|
if (checkedType != null && variableType != null && !checkedType.isSubtypeOf(variableType)) return null
|
||||||
|
} else if (prevStatement.isVar && operationExpression is KtBinaryExpression) {
|
||||||
|
val ifEndOffset = ifExpression.endOffset
|
||||||
|
val context = ifExpression.analyze()
|
||||||
|
val isUsedAsNotNullable = ReferencesSearch.search(prevStatement, LocalSearchScope(prevStatement.parent)).any {
|
||||||
|
if (it.element.startOffset <= ifEndOffset) return@any false
|
||||||
|
val type = it.element.safeAs<KtExpression>()?.getType(context) ?: return@any false
|
||||||
|
!type.isNullable()
|
||||||
|
}
|
||||||
|
if (isUsedAsNotNullable) return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val statement = if (then is KtBlockExpression) then.statements.singleOrNull() else then
|
val statement = if (then is KtBlockExpression) then.statements.singleOrNull() else then
|
||||||
|
|||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
fun test(foo: Int?, bar: Int): Int {
|
||||||
|
var i = foo
|
||||||
|
<caret>if (i == null) {
|
||||||
|
return bar
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
fun test(foo: Int?, bar: Int): Int {
|
||||||
|
var i = foo
|
||||||
|
<caret>if (i == null) {
|
||||||
|
return bar
|
||||||
|
}
|
||||||
|
baz(i)
|
||||||
|
val j = i + 1
|
||||||
|
return j
|
||||||
|
}
|
||||||
|
|
||||||
|
fun baz(i: Int?) {}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
fun test(foo: Int?, bar: Int): Int? {
|
||||||
|
var i = foo
|
||||||
|
<caret>if (i == null) {
|
||||||
|
return bar
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun test(foo: Int?, bar: Int): Int? {
|
||||||
|
var i: Int? = foo ?: return bar
|
||||||
|
return i
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
fun test(foo: Int?, bar: Int): Int {
|
||||||
|
var i = foo
|
||||||
|
<caret>if (i == null) {
|
||||||
|
return bar
|
||||||
|
}
|
||||||
|
return baz(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun baz(i: Int?) = 1
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
fun test(foo: Int?, bar: Int): Int {
|
||||||
|
var i: Int? = foo ?: return bar
|
||||||
|
return baz(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun baz(i: Int?) = 1
|
||||||
+20
@@ -4923,6 +4923,26 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
public void testVar() throws Exception {
|
public void testVar() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/foldInitializerAndIfToElvis/Var.kt");
|
runTest("idea/testData/inspectionsLocal/foldInitializerAndIfToElvis/Var.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VarUsedAsNotNullable.kt")
|
||||||
|
public void testVarUsedAsNotNullable() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/foldInitializerAndIfToElvis/VarUsedAsNotNullable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VarUsedAsNotNullable2.kt")
|
||||||
|
public void testVarUsedAsNotNullable2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/foldInitializerAndIfToElvis/VarUsedAsNotNullable2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VarUsedAsNullable.kt")
|
||||||
|
public void testVarUsedAsNullable() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/foldInitializerAndIfToElvis/VarUsedAsNullable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VarUsedAsNullable2.kt")
|
||||||
|
public void testVarUsedAsNullable2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/foldInitializerAndIfToElvis/VarUsedAsNullable2.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/forEachParameterNotUsed")
|
@TestMetadata("idea/testData/inspectionsLocal/forEachParameterNotUsed")
|
||||||
|
|||||||
Reference in New Issue
Block a user