[FIR-TEST] Add new testdata generated after changes in previous commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
fun calc(x: List<String>?, y: Int?): Int {
|
||||
x?.get(y!! - 1)
|
||||
// y!! above should not provide smart cast here
|
||||
val yy: Int = y
|
||||
return yy + (x?.size ?: 0)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun calc(x: List<String>?): Int {
|
||||
// After KT-5840 fix !! assertion should become unnecessary here
|
||||
x?.get(x!!.size - 1)
|
||||
// x?. or x!! above should not provide smart cast here
|
||||
return x.<!INAPPLICABLE_CANDIDATE!>size<!>
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun calc(x: List<String>?): Int {
|
||||
// x should be non-null in arguments list, despite of a chain
|
||||
x?.subList(0, 1)?.get(x.size)
|
||||
// But not here!
|
||||
return x!!.size
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun calc(x: List<String>?, y: List<Int>?) {
|
||||
// x and y should be non-null in arguments list, despite of a chains
|
||||
x?.subList(y?.subList(1, 2)?.get(y.size) ?: 0,
|
||||
y?.get(0) ?: 1) // But safe call is NECESSARY here for y
|
||||
?.get(x.size)
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun calc(x: List<String>?): Int {
|
||||
// x is not-null only inside subList
|
||||
x?.subList(0, x.size - 1).<!INAPPLICABLE_CANDIDATE!>get<!>(x.<!INAPPLICABLE_CANDIDATE!>size<!>)
|
||||
return x!!.size
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun calc(x: List<String>?): Int {
|
||||
// x should be non-null in arguments list, including inner call
|
||||
x?.get(x.get(x.size - 1).length)
|
||||
// but not also here!
|
||||
return x.<!INAPPLICABLE_CANDIDATE!>size<!>
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun String.foo(arg: Int) = this[arg]
|
||||
|
||||
fun calc(x: String?) {
|
||||
// x should be non-null in arguments list
|
||||
x?.foo(x.length - 1)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun String.bar(s: String) = s
|
||||
|
||||
fun foo(s: String?) {
|
||||
s?.bar(s)
|
||||
s?.get(s.length)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo(y: Int) = y
|
||||
|
||||
fun calc(x: List<String>?): Int {
|
||||
foo(x!!.size)
|
||||
// Here we should have smart cast because of x!!, despite of KT-7204 fixed
|
||||
return x.size
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fun calc(x: List<String>?, y: Int?) {
|
||||
// Smart cast should work here despite of KT-7204 fixed
|
||||
x?.subList(0, y!!)?.get(y)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fun String.foo(y: Int) = y
|
||||
|
||||
fun calc(x: List<String>?): Int {
|
||||
"abc".foo(x!!.size)
|
||||
// Here we should have smart cast because of x!!, despite of KT-7204 fixed
|
||||
return x.size
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
fun calc(x: List<String>?, y: Int?): Int {
|
||||
x?.subList(y!! - 1, y)
|
||||
// y!! above should not provide smart cast here
|
||||
return y
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(x: String): String? = x
|
||||
|
||||
fun calc(x: String?, y: String?): Int {
|
||||
// Smart cast because of y!! in receiver
|
||||
x?.subSequence(y!!.subSequence(0, 1).length, y.length)
|
||||
// No smart cast possible
|
||||
return y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(y: Int): Int {
|
||||
return y + 1
|
||||
}
|
||||
|
||||
fun calc(x: List<String>?): Int {
|
||||
// x should be non-null in arguments list
|
||||
return foo(x?.get(x.size - 1)!!.length)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// See KT-11007: Wrong smart cast to not-null type after safe calls in if / when expression
|
||||
|
||||
val String.copy: String
|
||||
get() = this
|
||||
|
||||
fun foo() {
|
||||
val s: String? = null
|
||||
val ss = if (true) {
|
||||
s?.length
|
||||
} else {
|
||||
s?.length
|
||||
}
|
||||
ss.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() // Smart-cast to Int, should be unsafe call
|
||||
val sss = if (true) {
|
||||
s?.copy
|
||||
}
|
||||
else {
|
||||
s?.copy
|
||||
}
|
||||
sss.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
class My {
|
||||
val String.copy2: String
|
||||
get() = this
|
||||
|
||||
fun foo() {
|
||||
val s: String? = null
|
||||
val ss = if (true) {
|
||||
s?.length
|
||||
} else {
|
||||
s?.length
|
||||
}
|
||||
ss.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
val sss = if (true) {
|
||||
s?.copy2
|
||||
}
|
||||
else {
|
||||
s?.copy2
|
||||
}
|
||||
sss.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun calc(x: List<String>?) {
|
||||
// x should be non-null in arguments list, despite of a chain
|
||||
x?.subList(0, x.size)?.
|
||||
subList(0, x.size)?.
|
||||
get(x.size)
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// See KT-10056
|
||||
class Foo(val bar: String)
|
||||
|
||||
fun test(foo: Foo?) {
|
||||
foo?.bar.let {
|
||||
// Error, foo?.bar is nullable
|
||||
it.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
// Error, foo is nullable
|
||||
foo.<!INAPPLICABLE_CANDIDATE!>bar<!>.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
// Correct
|
||||
foo?.bar?.length
|
||||
}
|
||||
}
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
class Bar(val gav: String)
|
||||
|
||||
class Foo(val bar: Bar, val nbar: Bar?) {
|
||||
fun baz(s: String) = if (s != "") Bar(s) else null
|
||||
}
|
||||
|
||||
fun String?.call(f: (String?) -> String?) = f(this)
|
||||
|
||||
fun String.notNullLet(f: (String) -> Unit) = f(this)
|
||||
|
||||
fun test(foo: Foo?) {
|
||||
foo?.bar?.gav.let {
|
||||
// Error, foo?.bar?.gav is nullable
|
||||
it.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
// Error, foo is nullable
|
||||
foo.<!INAPPLICABLE_CANDIDATE!>bar<!>.<!UNRESOLVED_REFERENCE!>gav<!>.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
// Correct
|
||||
foo?.bar?.gav?.length
|
||||
}
|
||||
foo?.bar?.gav.call { it }?.notNullLet {
|
||||
foo.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
foo.<!INAPPLICABLE_CANDIDATE!>bar<!>.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun testNotNull(foo: Foo) {
|
||||
val s: String? = ""
|
||||
foo.baz(s!!)?.gav.let {
|
||||
it.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
// Ok because of foo.
|
||||
s.length.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
fun testNullable(foo: Foo?) {
|
||||
val s: String? = ""
|
||||
foo?.baz(s!!)?.gav.let {
|
||||
it.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
// Ok because of foo?.
|
||||
s?.length?.hashCode()
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
class Foo(val bar: String?)
|
||||
|
||||
fun test(foo: Foo?) {
|
||||
foo!!.bar.let {
|
||||
// Correct
|
||||
foo.bar?.length
|
||||
// Unnecessary
|
||||
foo?.bar?.length
|
||||
}
|
||||
foo.bar?.length
|
||||
}
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
// FILE: Foo.java
|
||||
public class Foo {
|
||||
public String bar;
|
||||
|
||||
private Foo(String bar) {
|
||||
this.bar = bar;
|
||||
}
|
||||
|
||||
public static Foo create(String bar) {
|
||||
return new Foo(bar);
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Test.kt
|
||||
fun test() {
|
||||
val foo = Foo.create(null)
|
||||
foo?.bar.let {
|
||||
// Error, foo?.bar is nullable
|
||||
it.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
// Foo is nullable but flexible, so call is considered safe here
|
||||
foo.bar.length
|
||||
// Correct
|
||||
foo?.bar?.length
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
data class MyClass(val x: String?)
|
||||
|
||||
fun foo(y: MyClass): Int {
|
||||
val z = y.x?.subSequence(0, y.x.length)
|
||||
return z?.length ?: -1
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// See KT-7290
|
||||
class MyClass(val x: String?)
|
||||
fun foo(y: MyClass?): Int {
|
||||
// x here is smartcast but y is not
|
||||
val z = y?.x?.subSequence(0, y.x.length)
|
||||
// !! is necessary here
|
||||
y!!.x
|
||||
return z?.length ?: -1
|
||||
}
|
||||
fun bar(y: MyClass?) {
|
||||
y?.x!!.length
|
||||
// !! is NOT necessary here, because y?.x != null
|
||||
y!!.x
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(x: String): String? = x
|
||||
|
||||
fun calc(x: String?): Int {
|
||||
// Smart cast because of x!! in receiver
|
||||
foo(x!!)?.subSequence(0, x.length)
|
||||
// Smart cast because of x!! in receiver
|
||||
return x.length
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fun foo(x: String): String? = x
|
||||
|
||||
fun calc(x: String?): Int {
|
||||
// Smart cast because of x!! in receiver
|
||||
foo(x!!)?.subSequence(0, x.length)?.length
|
||||
// Smart cast because of x!! in receiver
|
||||
return x.length
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
fun foo(x: String): String? = x
|
||||
|
||||
fun calc(x: String?, y: Int?): Int {
|
||||
// Smart cast because of x!! in receiver
|
||||
foo(x!!)?.subSequence(y!!, x.length)?.length
|
||||
// No smart cast possible
|
||||
return y
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !LANGUAGE: -SafeCastCheckBoundSmartCasts -BooleanElvisBoundSmartCasts
|
||||
// A set of examples for
|
||||
// "If the result of a safe call is not null, understand that its receiver is not null"
|
||||
// and some other improvements for nullability detection
|
||||
|
||||
fun kt6840_1(s: String?) {
|
||||
val hash = s?.hashCode()
|
||||
if (hash != null) {
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun kt6840_2(s: String?) {
|
||||
if (s?.hashCode() != null) {
|
||||
s.length
|
||||
}
|
||||
}
|
||||
|
||||
fun kt1635(s: String?) {
|
||||
s?.hashCode()!!
|
||||
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
|
||||
fun kt2127() {
|
||||
val s: String? = ""
|
||||
if (s?.length != null) {
|
||||
s.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
fun kt3356(s: String?): Int {
|
||||
if (s?.length != 1) return 0
|
||||
return s.length
|
||||
}
|
||||
|
||||
open class SomeClass(val data: Any)
|
||||
|
||||
class SubClass(val extra: Any, data: Any) : SomeClass(data)
|
||||
|
||||
fun kt4565_1(a: SomeClass?) {
|
||||
val data = a?.data
|
||||
if (data != null) {
|
||||
data.hashCode()
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
a.<!INAPPLICABLE_CANDIDATE!>data<!>.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
}
|
||||
if (a?.data != null) {
|
||||
// To be supported (?!)
|
||||
data.hashCode()
|
||||
a.hashCode()
|
||||
a.data.hashCode()
|
||||
}
|
||||
if (a?.data is String) {
|
||||
a.<!INAPPLICABLE_CANDIDATE!>data<!>.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
data.length
|
||||
}
|
||||
}
|
||||
|
||||
fun kt4565_2(a: SomeClass?) {
|
||||
// To be supported
|
||||
if (a as? SubClass != null) {
|
||||
a.extra.hashCode()
|
||||
}
|
||||
val extra = (a as? SubClass)?.extra
|
||||
if (extra != null) {
|
||||
a.<!UNRESOLVED_REFERENCE!>extra<!>.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
}
|
||||
}
|
||||
|
||||
class A(val y: Int)
|
||||
|
||||
fun kt7491_1() {
|
||||
val x: A? = A(42)
|
||||
val z = x?.y ?: return
|
||||
x.y
|
||||
}
|
||||
|
||||
fun getA(): A? = null
|
||||
fun useA(a: A): Int = a.hashCode()
|
||||
|
||||
fun kt7491_2() {
|
||||
val a = getA()
|
||||
(a?.let { useA(a) } ?: a.<!INAPPLICABLE_CANDIDATE!>y<!> ).toString()
|
||||
}
|
||||
|
||||
fun String.correct() = true
|
||||
|
||||
fun kt8492(s: String?) {
|
||||
if (s?.correct() ?: false) {
|
||||
// To be supported
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
fun kt11085(prop: String?) {
|
||||
when (prop?.hashCode()) {
|
||||
1 -> prop.length
|
||||
}
|
||||
}
|
||||
|
||||
class HttpExchange(val code: String)
|
||||
|
||||
fun kt11313(arg: HttpExchange?) {
|
||||
when (arg?.code) {
|
||||
"GET" -> handleGet(arg)
|
||||
"POST" -> handlePost(arg)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleGet(arg: HttpExchange) = arg
|
||||
|
||||
fun handlePost(arg: HttpExchange) = arg
|
||||
|
||||
class Wrapper {
|
||||
fun unwrap(): String? = "Something not consistent"
|
||||
}
|
||||
|
||||
fun falsePositive(w: Wrapper) {
|
||||
if (w.unwrap() != null) {
|
||||
// Here we should NOT have smart cast
|
||||
w.unwrap().<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
}
|
||||
|
||||
class Invokable(val x: String) {
|
||||
operator fun invoke() = x
|
||||
}
|
||||
|
||||
class InvokableProperty(val i: Invokable)
|
||||
|
||||
fun checkInvokable(ip: InvokableProperty?) {
|
||||
if (ip?.i() == "Hello") {
|
||||
ip.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun calc(x: List<String>?): Int {
|
||||
// x should be non-null in arguments list
|
||||
x?.get(x.size - 1)
|
||||
// but not also here!
|
||||
return x.<!INAPPLICABLE_CANDIDATE!>size<!>
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
fun Any?.foo(my: My) = my === this
|
||||
|
||||
class My(val x: Any)
|
||||
|
||||
// my is nullable in brackets because Any?.foo has nullable receiver
|
||||
fun foo(my: My?) = my?.x.foo(my)
|
||||
@@ -0,0 +1,6 @@
|
||||
fun calc(x: List<String>?): Int {
|
||||
// x should be non-null in arguments list
|
||||
x?.subList(x.size - 1, x.size)
|
||||
// but not also here!
|
||||
return x.<!INAPPLICABLE_CANDIDATE!>size<!>
|
||||
}
|
||||
Reference in New Issue
Block a user