diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 65d1d4f7051..4dcc10055b9 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -113,7 +113,6 @@ public class IntrinsicMethods { declareIntrinsicFunction("Boolean", "not", 0, new Not()); declareIntrinsicFunction("String", "plus", 1, new Concat()); - declareIntrinsicFunction("CharSequence", "get", 1, new StringGetChar()); declareIntrinsicFunction("String", "get", 1, new StringGetChar()); declareIntrinsicFunction("Cloneable", "clone", 0, CLONE); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.kt b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.kt index 39373e1c5f6..3edd258ef39 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.kt +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.kt @@ -23,20 +23,21 @@ import org.jetbrains.jet.codegen.StackValue import org.jetbrains.jet.lang.psi.JetExpression public class StringGetChar : LazyIntrinsicMethod() { - override fun generateImpl(codegen: ExpressionCodegen, - returnType: Type, - element: PsiElement?, - arguments: List, - receiver: StackValue): StackValue { - + override fun generateImpl( + codegen: ExpressionCodegen, + returnType: Type, + element: PsiElement?, + arguments: List, + receiver: StackValue + ): StackValue { return StackValue.operation(Type.CHAR_TYPE) { if (receiver != StackValue.none()) { receiver.put(receiver.type, it) } if (!arguments.isEmpty()) { - codegen.gen(arguments.get(0)).put(Type.INT_TYPE, it) + codegen.gen(arguments.first()).put(Type.INT_TYPE, it) } - it.invokeinterface("java/lang/CharSequence", "charAt", "(I)C") + it.invokevirtual("java/lang/String", "charAt", "(I)C", false) } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/OperationsMapGenerated.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/OperationsMapGenerated.kt index 34b93508e49..9cb2226b71d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/OperationsMapGenerated.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/OperationsMapGenerated.kt @@ -419,6 +419,7 @@ private val binaryOperations: HashMap, Pair a.times(b) }, { a, b -> a.multiply(b) }), binaryOperation(SHORT, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), binaryOperation(SHORT, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), + binaryOperation(STRING, INT, "charAt", { a, b -> a.charAt(b) }, emptyBinaryFun), binaryOperation(STRING, STRING, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), binaryOperation(STRING, INT, "get", { a, b -> a.get(b) }, emptyBinaryFun), binaryOperation(STRING, ANY, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), diff --git a/compiler/testData/builtin-classes.txt b/compiler/testData/builtin-classes.txt index 713118325db..b5cfc7dcb97 100644 --- a/compiler/testData/builtin-classes.txt +++ b/compiler/testData/builtin-classes.txt @@ -294,7 +294,7 @@ public final class CharRange : kotlin.Range, kotlin.Progression, kotlin.Progression, kotlin.CharSequence { /*primary*/ public constructor String() + public open override /*1*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open override /*1*/ fun compareTo(/*0*/ other: kotlin.String): kotlin.Int - public open override /*1*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char + public final fun get(/*0*/ index: kotlin.Int): kotlin.Char public open override /*1*/ fun length(): kotlin.Int public final fun plus(/*0*/ other: kotlin.Any?): kotlin.String } diff --git a/compiler/testData/codegen/boxWithStdlib/strings/kt5389_stringBuilderGet.kt b/compiler/testData/codegen/boxWithStdlib/strings/kt5389_stringBuilderGet.kt new file mode 100644 index 00000000000..c6547b517a4 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/strings/kt5389_stringBuilderGet.kt @@ -0,0 +1,4 @@ +fun box(): String { + val sb = StringBuilder("OK") + return "${sb.get(0)}${sb[1]}" +} diff --git a/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt b/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt index 6f48297e8f5..c3d226eec9e 100644 --- a/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt +++ b/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt @@ -4473,7 +4473,7 @@ package java { public open fun append(/*0*/ p0: kotlin.String!): java.lang.AbstractStringBuilder! public open fun appendCodePoint(/*0*/ p0: kotlin.Int): java.lang.AbstractStringBuilder! public open fun capacity(): kotlin.Int - public open fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*1*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int @@ -7971,7 +7971,7 @@ package java { private final var hash: kotlin.Int private final var hash32: kotlin.Int private final val value: kotlin.CharArray! - public open fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*1*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int @@ -8084,7 +8084,7 @@ package java { public open override /*1*/ fun append(/*0*/ p0: kotlin.String!): java.lang.StringBuffer! public open override /*1*/ fun appendCodePoint(/*0*/ p0: kotlin.Int): java.lang.StringBuffer! public open override /*1*/ fun capacity(): kotlin.Int - public open override /*1*/ fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*2*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open override /*1*/ fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int @@ -8155,7 +8155,7 @@ package java { public open override /*1*/ fun append(/*0*/ p0: kotlin.String!): java.lang.StringBuilder! public open override /*1*/ fun appendCodePoint(/*0*/ p0: kotlin.Int): java.lang.StringBuilder! public open override /*1*/ /*fake_override*/ fun capacity(): kotlin.Int - public open override /*1*/ /*fake_override*/ fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*2*/ /*fake_override*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open override /*1*/ /*fake_override*/ fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ /*fake_override*/ fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ /*fake_override*/ fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/cast/neverSucceeds/MappedSubtypes.txt b/compiler/testData/diagnostics/tests/cast/neverSucceeds/MappedSubtypes.txt index 9372c67b568..152b4a92a48 100644 --- a/compiler/testData/diagnostics/tests/cast/neverSucceeds/MappedSubtypes.txt +++ b/compiler/testData/diagnostics/tests/cast/neverSucceeds/MappedSubtypes.txt @@ -14,8 +14,8 @@ internal final class JSub : java.lang.CharSequence { internal final class Sub : kotlin.CharSequence { public constructor Sub() + public abstract override /*1*/ /*fake_override*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char 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 diff --git a/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt b/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt new file mode 100644 index 00000000000..7efe604a0e4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt @@ -0,0 +1,24 @@ +// KT-1730 Method which has been implemented by Java is recognized to be abstract. + +// FILE: C.java +public class C implements java.lang.CharSequence { + @Override + public int length() { + return 3; + } + @Override + public char charAt(int index) { + return 48; + } + @Override + public CharSequence subSequence(int start, int end) { + return "ab"; + } + @Override + public String toString() { + return "abc"; + } +} + +// FILE: T.kt +class T : C() diff --git a/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.txt b/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.txt new file mode 100644 index 00000000000..4f4c904b46f --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.txt @@ -0,0 +1,21 @@ +package + +public open class C : kotlin.CharSequence { + public constructor C() + java.lang.Override() public open override /*1*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + java.lang.Override() public open override /*1*/ fun length(): kotlin.Int + java.lang.Override() public open fun subSequence(/*0*/ start: kotlin.Int, /*1*/ end: kotlin.Int): kotlin.CharSequence! + java.lang.Override() public open override /*1*/ fun toString(): kotlin.String! +} + +internal final class T : C { + public constructor T() + java.lang.Override() public open override /*1*/ /*fake_override*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + java.lang.Override() public open override /*1*/ /*fake_override*/ fun length(): kotlin.Int + java.lang.Override() public open override /*1*/ /*fake_override*/ fun subSequence(/*0*/ start: kotlin.Int, /*1*/ end: kotlin.Int): kotlin.CharSequence! + java.lang.Override() public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String! +} diff --git a/compiler/testData/diagnostics/tests/scopes/kt955.txt b/compiler/testData/diagnostics/tests/scopes/kt955.txt index 262b54fb624..663757a206f 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt955.txt +++ b/compiler/testData/diagnostics/tests/scopes/kt955.txt @@ -4478,7 +4478,7 @@ package java { public open fun append(/*0*/ p0: kotlin.String!): java.lang.AbstractStringBuilder! public open fun appendCodePoint(/*0*/ p0: kotlin.Int): java.lang.AbstractStringBuilder! public open fun capacity(): kotlin.Int - public open fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*1*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int @@ -7976,7 +7976,7 @@ package java { private final var hash: kotlin.Int private final var hash32: kotlin.Int private final val value: kotlin.CharArray! - public open fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*1*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int @@ -8089,7 +8089,7 @@ package java { public open override /*1*/ fun append(/*0*/ p0: kotlin.String!): java.lang.StringBuffer! public open override /*1*/ fun appendCodePoint(/*0*/ p0: kotlin.Int): java.lang.StringBuffer! public open override /*1*/ fun capacity(): kotlin.Int - public open override /*1*/ fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*2*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open override /*1*/ fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int @@ -8160,7 +8160,7 @@ package java { public open override /*1*/ fun append(/*0*/ p0: kotlin.String!): java.lang.StringBuilder! public open override /*1*/ fun appendCodePoint(/*0*/ p0: kotlin.Int): java.lang.StringBuilder! public open override /*1*/ /*fake_override*/ fun capacity(): kotlin.Int - public open override /*1*/ /*fake_override*/ fun charAt(/*0*/ p0: kotlin.Int): kotlin.Char + public open override /*2*/ /*fake_override*/ fun charAt(/*0*/ index: kotlin.Int): kotlin.Char public open override /*1*/ /*fake_override*/ fun codePointAt(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ /*fake_override*/ fun codePointBefore(/*0*/ p0: kotlin.Int): kotlin.Int public open override /*1*/ /*fake_override*/ fun codePointCount(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Int diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 4e3d4cc23bb..495a97da3ed 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -6294,6 +6294,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("kt1730_implementCharSequence.kt") + public void testKt1730_implementCharSequence() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/kt1730_implementCharSequence.kt"); + doTest(fileName); + } + @TestMetadata("kt2152.kt") public void testKt2152() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/kt2152.kt"); diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 7bb0504cf0c..1da88526cce 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2832,6 +2832,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("kt5389_stringBuilderGet.kt") + public void testKt5389_stringBuilderGet() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/strings/kt5389_stringBuilderGet.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("stringPlusOnlyWorksOnString.kt") public void testStringPlusOnlyWorksOnString() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/strings/stringPlusOnlyWorksOnString.kt"); diff --git a/core/builtins/native/kotlin/CharSequence.kt b/core/builtins/native/kotlin/CharSequence.kt index d61536668f7..6dd18390e0c 100644 --- a/core/builtins/native/kotlin/CharSequence.kt +++ b/core/builtins/native/kotlin/CharSequence.kt @@ -17,7 +17,7 @@ package kotlin public trait CharSequence { - public fun get(index: Int): Char - public fun length(): Int + + public fun charAt(index: Int): Char } diff --git a/core/builtins/native/kotlin/String.kt b/core/builtins/native/kotlin/String.kt index 2d77ae1f685..02f5523a203 100644 --- a/core/builtins/native/kotlin/String.kt +++ b/core/builtins/native/kotlin/String.kt @@ -19,9 +19,11 @@ package kotlin public class String : Comparable, CharSequence { public fun plus(other: Any?): String - public override fun compareTo(other: String): Int - - public override fun get(index: Int): Char + public fun get(index: Int): Char public override fun length(): Int + + public override fun charAt(index: Int): Char + + public override fun compareTo(other: String): Int } diff --git a/js/js.libraries/src/core/string.kt b/js/js.libraries/src/core/string.kt index 3e985d5136c..363a284cc3e 100644 --- a/js/js.libraries/src/core/string.kt +++ b/js/js.libraries/src/core/string.kt @@ -27,8 +27,6 @@ public fun String.split(regex: String, limit: Int): Array = noImpl native public fun String.substring(beginIndex : Int) : String = noImpl native public fun String.substring(beginIndex : Int, endIndex : Int) : String = noImpl -native public fun String.charAt(index : Int) : Char = noImpl - native public fun String.concat(str : String) : String = noImpl native public fun String.match(regex : String) : Array = noImpl diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/StringOperationFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/StringOperationFIF.java index f73f549e253..250d52f41e7 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/StringOperationFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/StringOperationFIF.java @@ -26,7 +26,9 @@ public final class StringOperationFIF extends CompositeFIF { public static final FunctionIntrinsicFactory INSTANCE = new StringOperationFIF(); private StringOperationFIF() { - add(pattern("kotlin", "CharSequence", "get").checkOverridden(), new BuiltInFunctionIntrinsic("charAt")); + add(pattern("kotlin", "String", "get"), new BuiltInFunctionIntrinsic("charAt")); + // This intrinsic is needed because charAt is a public function taking one parameter and thus its name would be mangled otherwise + add(pattern("kotlin", "CharSequence", "charAt").checkOverridden(), new BuiltInFunctionIntrinsic("charAt")); add(pattern("kotlin", "CharSequence", "length").checkOverridden(), LENGTH_PROPERTY_INTRINSIC); add(pattern("kotlin.js", "isEmpty").isExtensionOf("kotlin.CharSequence"), IS_EMPTY_INTRINSIC); } diff --git a/libraries/stdlib/src/kotlin/text/Strings.kt b/libraries/stdlib/src/kotlin/text/Strings.kt index 844b9822e0b..f83224e375a 100644 --- a/libraries/stdlib/src/kotlin/text/Strings.kt +++ b/libraries/stdlib/src/kotlin/text/Strings.kt @@ -67,6 +67,8 @@ public val String.indices: IntRange public val CharSequence.length: Int get() = length() +public fun CharSequence.get(index: Int): Char = this.charAt(index) + /** * Returns a subsequence specified by given set of indices. */ diff --git a/libraries/stdlib/src/kotlin/text/StringsJVM.kt b/libraries/stdlib/src/kotlin/text/StringsJVM.kt index b6ce97d23b7..a1298e1ca52 100644 --- a/libraries/stdlib/src/kotlin/text/StringsJVM.kt +++ b/libraries/stdlib/src/kotlin/text/StringsJVM.kt @@ -75,8 +75,6 @@ public fun String(stringBuilder: java.lang.StringBuilder): String = java.lang.St public fun String.replaceFirst(regex: String, replacement: String): String = (this as java.lang.String).replaceFirst(regex, replacement) -public fun String.charAt(index: Int): Char = (this as java.lang.String).charAt(index) - public fun String.split(regex: String, limit: Int): Array = (this as java.lang.String).split(regex, limit) public fun String.codePointAt(index: Int): Int = (this as java.lang.String).codePointAt(index) @@ -123,8 +121,6 @@ public fun String.toLowerCase(locale: java.util.Locale): String = (this as java. public fun String.toUpperCase(locale: java.util.Locale): String = (this as java.lang.String).toUpperCase(locale) -public fun CharSequence.charAt(index: Int): Char = (this as java.lang.CharSequence).charAt(index) - public fun CharSequence.subSequence(start: Int, end: Int): CharSequence? = (this as java.lang.CharSequence).subSequence(start, end) public val CharSequence.size: Int @@ -142,7 +138,6 @@ public fun String.toDouble(): Double = java.lang.Double.parseDouble(this) public fun String.toCharList(): List = toCharArray().toList() -public fun CharSequence.get(index: Int): Char = charAt(index) public fun CharSequence.get(start: Int, end: Int): CharSequence? = subSequence(start, end) public fun String.toByteArray(charset: String): ByteArray = (this as java.lang.String).getBytes(charset)