Add IDEA data-flow analysis to guess nullability
Add "if return..." folding to "return if"
This commit is contained in:
+3
-3
@@ -3,7 +3,7 @@
|
||||
internal class Library {
|
||||
fun call() {}
|
||||
|
||||
val string: String?
|
||||
val string: String
|
||||
get() = ""
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ internal class User {
|
||||
fun main() {
|
||||
val lib: Library = Library()
|
||||
lib.call()
|
||||
lib.string!!.isEmpty()
|
||||
lib.string.isEmpty()
|
||||
|
||||
Library().call()
|
||||
Library().string!!.isEmpty()
|
||||
Library().string.isEmpty()
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// ERROR: Type mismatch: inferred type is String? but Any was expected
|
||||
internal class A {
|
||||
private val s: String? = null
|
||||
|
||||
val value: Any
|
||||
val value: Any?
|
||||
get() = s
|
||||
}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
if (true) return 1 else return 0
|
||||
return if (true) 1 else 0
|
||||
+3
-3
@@ -11,9 +11,9 @@ object Test {
|
||||
return false
|
||||
}
|
||||
val result = true
|
||||
if (parent.isDirectory) {
|
||||
return true
|
||||
return if (parent.isDirectory) {
|
||||
true
|
||||
} else
|
||||
return false
|
||||
false
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -8,9 +8,7 @@ internal class Test {
|
||||
if (s1.isEmpty() && s2.isEmpty())
|
||||
return "OK"
|
||||
|
||||
if (s1.isEmpty() && s2.isEmpty() && s3.isEmpty())
|
||||
return "OOOK"
|
||||
return if (s1.isEmpty() && s2.isEmpty() && s3.isEmpty()) "OOOK" else ""
|
||||
|
||||
return ""
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
internal class C {
|
||||
fun foo(b: Boolean): String? {
|
||||
if (b) {
|
||||
return "abc"
|
||||
return if (b) {
|
||||
"abc"
|
||||
} else {
|
||||
return null
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
fun foo(s: String?, b: Boolean): Int {
|
||||
if (s == null) println("null")
|
||||
if (b) return s!!.length
|
||||
return 10
|
||||
return if (b) s!!.length else 10
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ internal class C : Base(), I {
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun zoo(o: Any?): String? {
|
||||
override fun zoo(o: Any?): String {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -1,8 +1,5 @@
|
||||
internal class A {
|
||||
fun foo(s: String?): Int {
|
||||
if (s != null) {
|
||||
return s.length
|
||||
}
|
||||
return -1
|
||||
return s?.length ?: -1
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
// ERROR: Type mismatch: inferred type is String? but String was expected
|
||||
// ERROR: Type mismatch: inferred type is Int? but Int was expected
|
||||
// ERROR: Type inference failed. Please try to specify type arguments explicitly.
|
||||
// ERROR: Using 'remove(Int): T' is an error. Use removeAt(index) instead.
|
||||
@@ -50,7 +49,7 @@ class Test {
|
||||
|
||||
}
|
||||
|
||||
fun foo2(s: String) {
|
||||
fun foo2(s: String?) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
// ERROR: Type mismatch: inferred type is String? but String was expected
|
||||
// ERROR: Type mismatch: inferred type is String? but String was expected
|
||||
class Test {
|
||||
fun nullableString(p: Int): String? {
|
||||
return if (p > 0) "response" else null
|
||||
}
|
||||
|
||||
private var nullableInitializerField: String = nullableString(3)
|
||||
private var nullableInitializerField = nullableString(3)
|
||||
private val nullableInitializerFieldFinal = nullableString(3)
|
||||
var nullableInitializerPublicField: String = nullableString(3)
|
||||
var nullableInitializerPublicField = nullableString(3)
|
||||
|
||||
fun testProperty() {
|
||||
nullableInitializerField = "aaa"
|
||||
|
||||
nullableInitializerField[0]
|
||||
nullableInitializerField!![0]
|
||||
nullableInitializerFieldFinal!![0]
|
||||
nullableInitializerPublicField[0]
|
||||
nullableInitializerPublicField!![0]
|
||||
}
|
||||
|
||||
fun testLocalVariable() {
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
fun foo(i: Int, j: Int): String {
|
||||
when (i) {
|
||||
0 -> if (j > 0) {
|
||||
return "1"
|
||||
0 -> return if (j > 0) {
|
||||
"1"
|
||||
} else {
|
||||
return "2"
|
||||
"2"
|
||||
}
|
||||
1 -> return "3"
|
||||
else -> return "4"
|
||||
|
||||
+3
-4
@@ -1,10 +1,9 @@
|
||||
fun foo(i: Int, j: Int): String {
|
||||
when (i) {
|
||||
0 -> {
|
||||
if (j > 0) {
|
||||
return "1"
|
||||
}
|
||||
return "2"
|
||||
return if (j > 0) {
|
||||
"1"
|
||||
} else "2"
|
||||
}
|
||||
1 -> return "2"
|
||||
else -> return "3"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
internal class A {
|
||||
private fun foo(o: Any?, b: Boolean): String? {
|
||||
if (b) return o as String?
|
||||
return ""
|
||||
return if (b) o as String? else ""
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
public class SomeServiceUsage {
|
||||
|
||||
public SomeService getService() {
|
||||
return SomeService.getInstanceNotNull();
|
||||
}
|
||||
|
||||
public SomeService getServiceNullable() {
|
||||
return SomeService.getInstanceNullable();
|
||||
}
|
||||
|
||||
// elvis
|
||||
public SomeService getServiceNotNullByDataFlow() {
|
||||
SomeService s = SomeService.getInstanceNullable();
|
||||
return s == null ? SomeService.getInstanceNotNull() : s;
|
||||
}
|
||||
|
||||
// nullable, bang-bang
|
||||
public String aString1() {
|
||||
return getServiceNullable().nullableString();
|
||||
}
|
||||
|
||||
// nullable
|
||||
public String aString2() {
|
||||
return getService().nullableString();
|
||||
}
|
||||
|
||||
// not nullable
|
||||
public String aString3() {
|
||||
return getService().notNullString();
|
||||
}
|
||||
|
||||
// nullable, no bang-bang
|
||||
public String aString4() {
|
||||
return getServiceNotNullByDataFlow().nullableString();
|
||||
}
|
||||
|
||||
// not nullable, no bang-bang
|
||||
public String aString5() {
|
||||
return getServiceNotNullByDataFlow().notNullString();
|
||||
}
|
||||
|
||||
// nullable, safe-call
|
||||
public String aString6() {
|
||||
SomeService s = getServiceNullable();
|
||||
if (s != null) {
|
||||
return s.nullableString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
class SomeServiceUsage {
|
||||
|
||||
val service: SomeService
|
||||
get() = SomeService.getInstanceNotNull()
|
||||
|
||||
val serviceNullable: SomeService?
|
||||
get() = SomeService.getInstanceNullable()
|
||||
|
||||
// elvis
|
||||
val serviceNotNullByDataFlow: SomeService
|
||||
get() {
|
||||
val s = SomeService.getInstanceNullable()
|
||||
return s ?: SomeService.getInstanceNotNull()
|
||||
}
|
||||
|
||||
// nullable, bang-bang
|
||||
fun aString1(): String? {
|
||||
return serviceNullable!!.nullableString()
|
||||
}
|
||||
|
||||
// nullable
|
||||
fun aString2(): String? {
|
||||
return service.nullableString()
|
||||
}
|
||||
|
||||
// not nullable
|
||||
fun aString3(): String {
|
||||
return service.notNullString()
|
||||
}
|
||||
|
||||
// nullable, no bang-bang
|
||||
fun aString4(): String? {
|
||||
return serviceNotNullByDataFlow.nullableString()
|
||||
}
|
||||
|
||||
// not nullable, no bang-bang
|
||||
fun aString5(): String {
|
||||
return serviceNotNullByDataFlow.notNullString()
|
||||
}
|
||||
|
||||
// nullable, safe-call
|
||||
fun aString6(): String? {
|
||||
val s = serviceNullable
|
||||
return s?.nullableString()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
public class SomeService {
|
||||
|
||||
public static SomeService getInstanceNotNull() {
|
||||
return new SomeService();
|
||||
}
|
||||
|
||||
public static SomeService getInstanceNullable() {
|
||||
if (Math.random() > 0.5)
|
||||
return null;
|
||||
return new SomeService();
|
||||
}
|
||||
|
||||
public String nullableString() {
|
||||
if (Math.random() < 0.5)
|
||||
return null;
|
||||
return Math.random() + "";
|
||||
}
|
||||
|
||||
public String notNullString() {
|
||||
String s = nullableString();
|
||||
if (s != null)
|
||||
return s;
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
public class SomeService {
|
||||
|
||||
public static SomeService getInstanceNotNull() {
|
||||
return new SomeService();
|
||||
}
|
||||
|
||||
public static SomeService getInstanceNullable() {
|
||||
if (Math.random() > 0.5)
|
||||
return null;
|
||||
return new SomeService();
|
||||
}
|
||||
|
||||
public String nullableString() {
|
||||
if (Math.random() < 0.5)
|
||||
return null;
|
||||
return Math.random() + "";
|
||||
}
|
||||
|
||||
public String notNullString() {
|
||||
String s = nullableString();
|
||||
if (s != null)
|
||||
return s;
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user