Make CharSequence.length a function instead of property

And String.length as well.

This is done for JVM interoperability: java.lang.CharSequence is an open class
and has a function 'length()' which should be implemented in subclasses
somehow.

A minor unexpected effect of this is that String.length() is now a compile-time
constant (it wasn't such as a property because properties are not supported in
compile-time constant evaluation)

 #KT-3571 Fixed
This commit is contained in:
Alexander Udalov
2014-11-26 18:50:04 +03:00
parent 6b8da062a4
commit a7b88e9485
159 changed files with 265 additions and 313 deletions
@@ -4502,7 +4502,7 @@ package java {
public open fun insert(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.String!): java.lang.AbstractStringBuilder!
public open fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun length(): kotlin.Int
public open override /*1*/ fun length(): kotlin.Int
public open fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun replace(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!): java.lang.AbstractStringBuilder!
public open fun reverse(): java.lang.AbstractStringBuilder!
@@ -8004,7 +8004,7 @@ package java {
public open fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
private open fun lastIndexOfSupplementary(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun length(): kotlin.Int
public open override /*1*/ fun length(): kotlin.Int
public open fun matches(/*0*/ p0: kotlin.String!): kotlin.Boolean
public open fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun regionMatches(/*0*/ p0: kotlin.Boolean, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!, /*3*/ p3: kotlin.Int, /*4*/ p4: kotlin.Int): kotlin.Boolean
@@ -8113,7 +8113,7 @@ package java {
public open override /*1*/ fun insert(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.String!): java.lang.StringBuffer!
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
public open override /*1*/ fun length(): kotlin.Int
public open override /*2*/ fun length(): kotlin.Int
public open override /*1*/ fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
private open fun readObject(/*0*/ p0: java.io.ObjectInputStream!): kotlin.Unit
public open override /*1*/ fun replace(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!): java.lang.StringBuffer!
@@ -8184,7 +8184,7 @@ package java {
public open override /*1*/ fun insert(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.String!): java.lang.StringBuilder!
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
public open override /*1*/ /*fake_override*/ fun length(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun length(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
private open fun readObject(/*0*/ p0: java.io.ObjectInputStream!): kotlin.Unit
public open override /*1*/ fun replace(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!): java.lang.StringBuilder!
@@ -14,7 +14,7 @@ fun box() : String {
val test5 =
"""
${s.length}
${s.length()}
"""
if (test5 != "\n 3\n") return "Fail 5: $test5"
@@ -1,12 +1,12 @@
package qualified_expressions
fun test(s: String?) {
val <!UNUSED_VARIABLE!>a<!>: Int = <!TYPE_MISMATCH!>s?.length<!>
val b: Int? = s?.length
val <!UNUSED_VARIABLE!>c<!>: Int = s?.length ?: -11
val <!UNUSED_VARIABLE!>d<!>: Int = s?.length ?: <!TYPE_MISMATCH!>"empty"<!>
val e: String = <!TYPE_MISMATCH!>s?.length<!> ?: "empty"
val <!UNUSED_VARIABLE!>f<!>: Int = s?.length ?: b ?: 1
fun test(s: IntRange?) {
val <!UNUSED_VARIABLE!>a<!>: Int = <!TYPE_MISMATCH!>s?.start<!>
val b: Int? = s?.start
val <!UNUSED_VARIABLE!>c<!>: Int = s?.start ?: -11
val <!UNUSED_VARIABLE!>d<!>: Int = s?.start ?: <!TYPE_MISMATCH!>"empty"<!>
val e: String = <!TYPE_MISMATCH!>s?.start<!> ?: "empty"
val <!UNUSED_VARIABLE!>f<!>: Int = s?.end ?: b ?: 1
val <!UNUSED_VARIABLE!>g<!>: Boolean? = e.startsWith("s")//?.length
}
@@ -1,6 +1,6 @@
package
package qualified_expressions {
internal fun test(/*0*/ s: kotlin.String?): kotlin.Unit
internal fun test(/*0*/ s: kotlin.IntRange?): kotlin.Unit
internal fun kotlin.String.startsWith(/*0*/ s: kotlin.String): kotlin.Boolean
}
@@ -14,9 +14,9 @@ internal final class JSub : java.lang.CharSequence {
internal final class Sub : kotlin.CharSequence {
public constructor Sub()
public abstract override /*1*/ /*fake_override*/ val length: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public abstract override /*1*/ /*fake_override*/ fun length(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -1,6 +1,6 @@
fun illegalWhenBlock(a: Any): Int {
when(a) {
is Int -> return <!DEBUG_INFO_SMARTCAST!>a<!>
is String -> return <!DEBUG_INFO_SMARTCAST!>a<!>.length
is String -> return <!DEBUG_INFO_SMARTCAST!>a<!>.length()
}
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
@@ -6,11 +6,10 @@ fun test(x: Any) {
if (y !is String) return
class Local {
{
<!DEBUG_INFO_SMARTCAST!>x<!>.length
<!DEBUG_INFO_SMARTCAST!>y<!>.length
<!DEBUG_INFO_SMARTCAST!>x<!>.length()
<!DEBUG_INFO_SMARTCAST!>y<!>.length()
}
}
}
}
}
@@ -2,11 +2,11 @@ fun test(x: Any?) {
if (x !is String) return
class C {
val v = <!DEBUG_INFO_SMARTCAST!>x<!>.length
val v = <!DEBUG_INFO_SMARTCAST!>x<!>.length()
val vGet: Int
get() = <!DEBUG_INFO_SMARTCAST!>x<!>.length
get() = <!DEBUG_INFO_SMARTCAST!>x<!>.length()
val s: String = <!DEBUG_INFO_SMARTCAST!>x<!>
}
}
}
@@ -1,9 +1,9 @@
fun foo(x: Any?) {
if (x is String) {
object : Base(<!DEBUG_INFO_SMARTCAST!>x<!>) {
fun bar() = <!DEBUG_INFO_SMARTCAST!>x<!>.length
fun bar() = <!DEBUG_INFO_SMARTCAST!>x<!>.length()
}
}
}
open class Base(s: String)
open class Base(s: String)
@@ -4,9 +4,8 @@ fun test(x: Any) {
class LocalOuter {
inner class Local {
{
<!DEBUG_INFO_SMARTCAST!>x<!>.length
<!DEBUG_INFO_SMARTCAST!>x<!>.length()
}
}
}
}
@@ -3,7 +3,7 @@
fun testWhen(t: String?, x: String?): Int {
return when {
t == null -> 0
x == null -> <!DEBUG_INFO_SMARTCAST!>t<!>.length // Wrong error report here. t can be inferred as not-null. (And it actually does if you replace when with if/else if)
else -> (<!DEBUG_INFO_SMARTCAST!>t<!> + x).length
x == null -> <!DEBUG_INFO_SMARTCAST!>t<!>.length() // Wrong error report here. t can be inferred as not-null. (And it actually does if you replace when with if/else if)
else -> (<!DEBUG_INFO_SMARTCAST!>t<!> + x).length()
}
}
}
@@ -3,7 +3,7 @@ package n
import java.util.*
fun test() {
val foo = arrayList("").map { it -> it.length }.fold(0, { x, y -> Math.max(x, y) })
val foo = arrayList("").map { it -> it.length() }.fold(0, { x, y -> Math.max(x, y) })
foo : Int
<!TYPE_MISMATCH!>foo<!> : String
}
@@ -8,15 +8,15 @@ fun <T> Array<T>.forEach(operation: (T) -> Unit) : Unit { for (element in this)
fun bar(operation: (String) -> Unit) = operation("")
fun main(args: Array<String>) {
args.forEach { (a : String) : Unit -> a.length } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { (a) : Unit -> a.length } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { (a : String) -> a.length } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { a -> a.length } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { it.length } // This works!
args.forEach { (a : String) : Unit -> a.length() } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { (a) : Unit -> a.length() } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { (a : String) -> a.length() } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { a -> a.length() } // Type mismatch: (String) -> Unit required, (String) -> Int found
args.forEach { it.length() } // This works!
bar { (a: String) : Unit -> a.length }
bar { (a) : Unit -> a.length }
bar { (a: String) -> a.length }
bar { a -> a.length }
bar { it.length }
bar { (a: String) : Unit -> a.length() }
bar { (a) : Unit -> a.length() }
bar { (a: String) -> a.length() }
bar { a -> a.length() }
bar { it.length() }
}
@@ -7,8 +7,8 @@ import java.util.*
fun foo(lines: List<String>) {
val w = max(lines, comparator {o1, o2 ->
val l1 : Int = o1.length // Types of o1 and o2 are ERROR
val l2 = o2.length
val l1 : Int = o1.length() // Types of o1 and o2 are ERROR
val l2 = o2.length()
l1 - l2
}).sure()
w : String
@@ -2,11 +2,11 @@
inline fun foo(bar1: (String.() -> Int) -> Int, bar2: (()->Int) -> Int) {
bar1 @label {
this@label.length
this@label.length()
}
bar1 {
this.length
this.length()
}
//unmute after KT-4247 fix
//bar1 {
@@ -15,7 +15,6 @@ public class Y extends X<String> {
// FILE: test.kt
fun main() {
Y().foo().length
Y().foo().length()
Y().bar(null)
}
+2 -2
View File
@@ -1,3 +1,3 @@
fun f(c: String): Int {
return c.<!FUNCTION_EXPECTED!>length<!>()
fun f(c: LongRange): Int {
return c.<!FUNCTION_EXPECTED!>start<!>()
}
@@ -1,3 +1,3 @@
package
internal fun f(/*0*/ c: kotlin.String): kotlin.Int
internal fun f(/*0*/ c: kotlin.LongRange): kotlin.Int
@@ -2,10 +2,10 @@
fun foo(bar1: (String.() -> Int) -> Int) {
bar1 {
this.length
this.length()
}
bar1 {
this@bar1.length
this@bar1.length()
}
}
@@ -5,18 +5,18 @@ package kt244
fun f(s: String?) {
if (s != null) {
<!DEBUG_INFO_SMARTCAST!>s<!>.length //ok
var <!UNUSED_VARIABLE!>i<!> = <!DEBUG_INFO_SMARTCAST!>s<!>.length //error: Only safe calls are allowed on a nullable receiver
System.out.println(<!DEBUG_INFO_SMARTCAST!>s<!>.length) //error
<!DEBUG_INFO_SMARTCAST!>s<!>.length() //ok
var <!UNUSED_VARIABLE!>i<!> = <!DEBUG_INFO_SMARTCAST!>s<!>.length() //error: Only safe calls are allowed on a nullable receiver
System.out.println(<!DEBUG_INFO_SMARTCAST!>s<!>.length()) //error
}
}
// more tests
class A(a: String?) {
val b = if (a != null) <!DEBUG_INFO_SMARTCAST!>a<!>.length else 1
val b = if (a != null) <!DEBUG_INFO_SMARTCAST!>a<!>.length() else 1
{
if (a != null) {
val <!UNUSED_VARIABLE!>c<!> = <!DEBUG_INFO_SMARTCAST!>a<!>.length
val <!UNUSED_VARIABLE!>c<!> = <!DEBUG_INFO_SMARTCAST!>a<!>.length()
}
}
@@ -24,7 +24,7 @@ class A(a: String?) {
{
if (a is String) {
i = <!DEBUG_INFO_SMARTCAST!>a<!>.length
i = <!DEBUG_INFO_SMARTCAST!>a<!>.length()
}
else {
i = 3
@@ -19,8 +19,8 @@ fun test(j: J) {
j.j()!!.j()
val ann = j.foo<String>()
ann!!.length
ann.length
ann!!.length()
ann.length()
val a = j.foo<J>()
a!!.j()
@@ -12,5 +12,5 @@ public class J {
import p.*
fun test(j: J) {
j.s()?.length ?: ""
}
j.s()?.length() ?: ""
}
@@ -4,6 +4,6 @@ fun foo() {
val list = ArrayList<String?>()
for (s in list) {
s<!UNSAFE_CALL!>.<!>length
s<!UNSAFE_CALL!>.<!>length()
}
}
@@ -11,5 +11,5 @@ public class J {
import p.*
fun test(j: J) {
j.s()?.length.checkType { it : _<Int?> }
}
j.s()?.length().checkType { it : _<Int?> }
}
@@ -1,4 +1,3 @@
import java.util.*
import java.io.*
@@ -10,7 +9,7 @@ fun takeFirst(expr: StringBuilder): Char {
}
fun evaluateArg(expr: CharSequence, numbers: ArrayList<Int>): Int {
if (expr.length == 0) throw Exception("Syntax error: Character expected");
if (expr.length() == 0) throw Exception("Syntax error: Character expected");
val c = takeFirst(<!TYPE_MISMATCH!>expr<!>)
if (c >= '0' && c <= '9') {
val n = c - '0'
@@ -3,7 +3,7 @@ package jet121
fun box() : String {
val answer = apply("OK") { String.() : Int ->
get(0)
length
length()
}
return if (answer == 2) "OK" else "FAIL"
@@ -11,7 +11,7 @@ package demo
}
fun main(args : Array<String>) {
for (a in filter(args, {it.length > 1})) {
for (a in filter(args, {it.length() > 1})) {
System.out.println("Hello, ${a}!")
}
}
@@ -11,9 +11,9 @@ fun main() {
val diffs = ArrayList<Int>()
for (i in vals.indices) {
for (j in i..vals.lastIndex()) // Type inference failed
diffs.add(vals[i].length - vals[j].length)
diffs.add(vals[i].length() - vals[j].length())
for (j in i..vals.lastIndex) // Type inference failed
diffs.add(vals[i].length - vals[j].length)
diffs.add(vals[i].length() - vals[j].length())
}
}
@@ -5,5 +5,5 @@
fun foo(i: Int) {}
fun test(s: String?) {
foo(<!TYPE_MISMATCH!>s?.length<!>)
}
foo(<!TYPE_MISMATCH!>s?.length()<!>)
}
@@ -1,19 +1,18 @@
package kt939
//KT-939 CommonSupertypes erases scopes associated to types
fun compare(o1 : String?, o2 : String?) : Int {
val l1 = o1?.length ?: 0
val l2 = o2?.length ?: 0
val l1 = o1?.length() ?: 0
val l2 = o2?.length() ?: 0
return l1 - l2 // '-' is unresolved, because the type of l1 is Int with an empty member scope
}
//KT-1117 Unresolved reference to multiply sign
fun test() {
(System.getProperty("path.separator")?.length ?: 4) * 55 + 5
(System.getProperty("path.separator")?.length() ?: 4) * 55 + 5
val x = System.getProperty("path.separator")?.length ?: 4
val x = System.getProperty("path.separator")?.length() ?: 4
x * 55 + 5
}
@@ -4507,7 +4507,7 @@ package java {
public open fun insert(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.String!): java.lang.AbstractStringBuilder!
public open fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun length(): kotlin.Int
public open override /*1*/ fun length(): kotlin.Int
public open fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun replace(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!): java.lang.AbstractStringBuilder!
public open fun reverse(): java.lang.AbstractStringBuilder!
@@ -8009,7 +8009,7 @@ package java {
public open fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
private open fun lastIndexOfSupplementary(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun length(): kotlin.Int
public open override /*1*/ fun length(): kotlin.Int
public open fun matches(/*0*/ p0: kotlin.String!): kotlin.Boolean
public open fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
public open fun regionMatches(/*0*/ p0: kotlin.Boolean, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!, /*3*/ p3: kotlin.Int, /*4*/ p4: kotlin.Int): kotlin.Boolean
@@ -8118,7 +8118,7 @@ package java {
public open override /*1*/ fun insert(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.String!): java.lang.StringBuffer!
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
public open override /*1*/ fun length(): kotlin.Int
public open override /*2*/ fun length(): kotlin.Int
public open override /*1*/ fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
private open fun readObject(/*0*/ p0: java.io.ObjectInputStream!): kotlin.Unit
public open override /*1*/ fun replace(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!): java.lang.StringBuffer!
@@ -8189,7 +8189,7 @@ package java {
public open override /*1*/ fun insert(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.String!): java.lang.StringBuilder!
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!): kotlin.Int
public open override /*1*/ fun lastIndexOf(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int): kotlin.Int
public open override /*1*/ /*fake_override*/ fun length(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun length(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun offsetByCodePoints(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int
private open fun readObject(/*0*/ p0: java.io.ObjectInputStream!): kotlin.Unit
public open override /*1*/ fun replace(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int, /*2*/ p2: kotlin.String!): java.lang.StringBuilder!
@@ -3,7 +3,7 @@ package foo
fun dispatch(request: Request) {
val <!UNUSED_VARIABLE!>url<!> = request.getRequestURI() as String
if (request.getMethod()?.length != 0) {
if (request.getMethod()?.length() != 0) {
}
}
@@ -5,6 +5,6 @@
fun foo(p1: String?, p2: String?) {
if (p2 != null) {
val v = p1 ?: <!DEBUG_INFO_SMARTCAST!>p2<!>
val size = v.length
val size = v.length()
}
}
@@ -1,7 +1,7 @@
//KT-5455 Need warning about redundant type cast
fun foo(o: Any): Int {
if (o is String) {
return (o <!USELESS_CAST_STATIC_ASSERT_IS_FINE!>as<!> String).length
return (o <!USELESS_CAST_STATIC_ASSERT_IS_FINE!>as<!> String).length()
}
return -1
}