JS: fix behaviour of char-returning functions with multiple inheritance
See KT-19772
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
open class A {
|
||||
fun get(index: Int): Char = '*'
|
||||
}
|
||||
|
||||
abstract class <!WRONG_MULTIPLE_INHERITANCE!>B<!> : A(), CharSequence
|
||||
|
||||
interface I {
|
||||
fun nextChar(): Char
|
||||
}
|
||||
|
||||
abstract class <!WRONG_MULTIPLE_INHERITANCE!>C<!> : CharIterator(), I {
|
||||
override fun nextChar(): Char = '*'
|
||||
}
|
||||
|
||||
class <!WRONG_MULTIPLE_INHERITANCE!>CC(val s: CharSequence)<!> : CharSequence by s, MyCharSequence {}
|
||||
|
||||
interface MyCharSequence {
|
||||
val length: Int
|
||||
|
||||
operator fun get(index: Int): Char
|
||||
|
||||
fun subSequence(startIndex: Int, endIndex: Int): CharSequence
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package
|
||||
|
||||
public open class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun get(/*0*/ index: kotlin.Int): kotlin.Char
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public abstract class B : A, kotlin.CharSequence {
|
||||
public constructor B()
|
||||
public abstract override /*1*/ /*fake_override*/ val length: kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*2*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract override /*1*/ /*fake_override*/ fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): kotlin.CharSequence
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public abstract class C : kotlin.collections.CharIterator, I {
|
||||
public constructor C()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun next(): kotlin.Char
|
||||
public open override /*2*/ fun nextChar(): kotlin.Char
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class CC : kotlin.CharSequence, MyCharSequence {
|
||||
public constructor CC(/*0*/ s: kotlin.CharSequence)
|
||||
public open override /*2*/ /*delegation*/ val length: kotlin.Int
|
||||
public final val s: kotlin.CharSequence
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ /*delegation*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*delegation*/ fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): kotlin.CharSequence
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface I {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract fun nextChar(): kotlin.Char
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface MyCharSequence {
|
||||
public abstract val length: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract operator fun get(/*0*/ index: kotlin.Int): kotlin.Char
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): kotlin.CharSequence
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -66,6 +66,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("wrongMultipleInheritance.kt")
|
||||
public void testWrongMultipleInheritance() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/wrongMultipleInheritance.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -35,7 +35,7 @@ object JsPlatformConfigurator : PlatformConfigurator(
|
||||
additionalDeclarationCheckers = listOf(
|
||||
NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(),
|
||||
JsNameChecker, JsModuleChecker, JsExternalFileChecker,
|
||||
JsExternalChecker, JsInheritanceChecker,
|
||||
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker,
|
||||
ExpectedActualDeclarationChecker
|
||||
|
||||
+4
@@ -104,6 +104,10 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
put(ErrorsJs.EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "External class constructor cannot have a property parameter")
|
||||
put(ErrorsJs.CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION, "This property can only be used from external declarations")
|
||||
|
||||
put(ErrorsJs.WRONG_MULTIPLE_INHERITANCE,
|
||||
"Can't apply multiple inheritance here, since it's impossible to generate bridge for system function {0}",
|
||||
Renderers.DECLARATION_NAME_WITH_KIND)
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.*;
|
||||
@@ -109,6 +110,9 @@ public interface ErrorsJs {
|
||||
DiagnosticFactory0<KtParameter> EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<PsiElement, CallableMemberDescriptor> WRONG_MULTIPLE_INHERITANCE =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
|
||||
object JsMultipleInheritanceChecker : SimpleDeclarationChecker {
|
||||
private val fqNames = listOf(
|
||||
FqNameUnsafe("kotlin.CharSequence.get"),
|
||||
FqNameUnsafe("kotlin.collections.CharIterator.nextChar")
|
||||
)
|
||||
private val simpleNames = fqNames.mapTo(mutableSetOf()) { it.shortName() }
|
||||
|
||||
override fun check(
|
||||
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
|
||||
) {
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
|
||||
for (callable in descriptor.unsubstitutedMemberScope.getContributedDescriptors { it in simpleNames }
|
||||
.filterIsInstance<CallableMemberDescriptor>()) {
|
||||
if (callable.overriddenDescriptors.size > 1 && callable.overriddenDescriptors.any { it.fqNameUnsafe in fqNames }) {
|
||||
diagnosticHolder.report(ErrorsJs.WRONG_MULTIPLE_INHERITANCE.on(declaration, callable))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -445,6 +445,18 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/char/charUnaryOperations.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelCallables.kt")
|
||||
public void testTopLevelCallables() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/char/topLevelCallables.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("unboxedCharSpecials.kt")
|
||||
public void testUnboxedCharSpecials() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/char/unboxedCharSpecials.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/classObject")
|
||||
@@ -803,6 +815,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/coercion"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bridgeChar.kt")
|
||||
public void testBridgeChar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/bridgeChar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classProperty.kt")
|
||||
public void testClassProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/classProperty.kt");
|
||||
@@ -857,6 +875,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyBridgeChar.kt")
|
||||
public void testPropertyBridgeChar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/propertyBridgeChar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("receiverSmartCast.kt")
|
||||
public void testReceiverSmartCast() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/coercion/receiverSmartCast.kt");
|
||||
|
||||
+3
-1
@@ -65,7 +65,9 @@ object CallTranslator {
|
||||
value: JsExpression,
|
||||
extensionOrDispatchReceiver: JsExpression? = null
|
||||
): JsExpression {
|
||||
val variableAccessInfo = VariableAccessInfo(context.getCallInfo(resolvedCall, extensionOrDispatchReceiver), value)
|
||||
val type = TranslationUtils.getReturnTypeForCoercion(resolvedCall.resultingDescriptor)
|
||||
val coerceValue = TranslationUtils.coerce(context, value, type)
|
||||
val variableAccessInfo = VariableAccessInfo(context.getCallInfo(resolvedCall, extensionOrDispatchReceiver), coerceValue)
|
||||
val result = variableAccessInfo.translateVariableAccess().source(resolvedCall.call.callElement)
|
||||
result.type = context.currentModule.builtIns.unitType
|
||||
return result
|
||||
|
||||
+4
@@ -51,6 +51,10 @@ public final class InitializerVisitor extends TranslatorVisitor<Void> {
|
||||
KtExpression delegate = property.getDelegateExpression();
|
||||
if (initializer != null) {
|
||||
assert value != null;
|
||||
KotlinType type = TranslationUtils.isReferenceToSyntheticBackingField(descriptor) ?
|
||||
descriptor.getType() :
|
||||
TranslationUtils.getReturnTypeForCoercion(descriptor);
|
||||
value = TranslationUtils.coerce(context, value, type);
|
||||
statement = generateInitializerForProperty(context, descriptor, value);
|
||||
}
|
||||
else if (delegate != null) {
|
||||
|
||||
+5
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression;
|
||||
@@ -84,6 +85,10 @@ public final class ReferenceTranslator {
|
||||
if (parameter.getContainingDeclaration() instanceof AnonymousFunctionDescriptor) {
|
||||
return DescriptorUtils.getContainingModule(descriptor).getBuiltIns().getAnyType();
|
||||
}
|
||||
if (parameter.getContainingDeclaration() instanceof PropertySetterDescriptor) {
|
||||
PropertySetterDescriptor setter = (PropertySetterDescriptor) parameter.getContainingDeclaration();
|
||||
return TranslationUtils.getReturnTypeForCoercion(setter.getCorrespondingProperty(), false);
|
||||
}
|
||||
}
|
||||
return ((CallableDescriptor) descriptor).getReturnType();
|
||||
}
|
||||
|
||||
+48
-11
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.js.translate.general.Translation;
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -58,6 +59,13 @@ import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCallableDe
|
||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*;
|
||||
|
||||
public final class TranslationUtils {
|
||||
private static final Set<FqNameUnsafe> CLASSES_WITH_NON_BOXED_CHARS = new HashSet<>(Arrays.asList(
|
||||
new FqNameUnsafe("kotlin.collections.CharIterator"),
|
||||
new FqNameUnsafe("kotlin.ranges.CharProgression"),
|
||||
new FqNameUnsafe("kotlin.js.internal.CharCompanionObject"),
|
||||
new FqNameUnsafe("kotlin.Char.Companion"),
|
||||
KotlinBuiltIns.FQ_NAMES.charSequence, KotlinBuiltIns.FQ_NAMES.number
|
||||
));
|
||||
|
||||
private TranslationUtils() {
|
||||
}
|
||||
@@ -172,17 +180,21 @@ public final class TranslationUtils {
|
||||
|
||||
@NotNull
|
||||
public static JsName getNameForBackingField(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) {
|
||||
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
||||
|
||||
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor) && !(containingDescriptor instanceof PackageFragmentDescriptor)) {
|
||||
if (isReferenceToSyntheticBackingField(descriptor)) {
|
||||
return context.getNameForBackingField(descriptor);
|
||||
}
|
||||
|
||||
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
||||
return containingDescriptor instanceof PackageFragmentDescriptor ?
|
||||
context.getInnerNameForDescriptor(descriptor) :
|
||||
context.getNameForDescriptor(descriptor);
|
||||
}
|
||||
|
||||
public static boolean isReferenceToSyntheticBackingField(@NotNull PropertyDescriptor descriptor) {
|
||||
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
||||
return !JsDescriptorUtils.isSimpleFinalProperty(descriptor) && !(containingDescriptor instanceof PackageFragmentDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsNameRef backingFieldReference(@NotNull TranslationContext context, @NotNull PropertyDescriptor descriptor) {
|
||||
DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
|
||||
@@ -196,7 +208,7 @@ public final class TranslationUtils {
|
||||
}
|
||||
|
||||
JsNameRef result = new JsNameRef(getNameForBackingField(context, descriptor), receiver);
|
||||
MetadataProperties.setType(result, getReturnTypeForCoercion(descriptor));
|
||||
MetadataProperties.setType(result, getReturnTypeForCoercion(descriptor, true));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -396,25 +408,50 @@ public final class TranslationUtils {
|
||||
|
||||
@NotNull
|
||||
public static KotlinType getReturnTypeForCoercion(@NotNull CallableDescriptor descriptor) {
|
||||
return getReturnTypeForCoercion(descriptor, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static KotlinType getReturnTypeForCoercion(@NotNull CallableDescriptor descriptor, boolean forcePrivate) {
|
||||
descriptor = descriptor.getOriginal();
|
||||
|
||||
if (FunctionTypesKt.getFunctionalClassKind(descriptor) != null || descriptor instanceof AnonymousFunctionDescriptor) {
|
||||
return DescriptorUtils.getContainingModule(descriptor).getBuiltIns().getAnyType();
|
||||
return getAnyTypeFromSameModule(descriptor);
|
||||
}
|
||||
|
||||
Collection<? extends CallableDescriptor> overridden = descriptor.getOverriddenDescriptors();
|
||||
if (overridden.isEmpty()) {
|
||||
return descriptor.getReturnType() != null ?
|
||||
descriptor.getReturnType() :
|
||||
DescriptorUtils.getContainingModule(descriptor).getBuiltIns().getAnyType();
|
||||
KotlinType returnType = descriptor.getReturnType();
|
||||
if (returnType == null) {
|
||||
return getAnyTypeFromSameModule(descriptor);
|
||||
}
|
||||
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
boolean isPublic = descriptor.getVisibility().effectiveVisibility(descriptor, true).getPublicApi() && !forcePrivate;
|
||||
if (KotlinBuiltIns.isCharOrNullableChar(returnType) && container instanceof ClassDescriptor && isPublic) {
|
||||
ClassDescriptor containingClass = (ClassDescriptor) container;
|
||||
FqNameUnsafe containingClassName = DescriptorUtilsKt.getFqNameUnsafe(containingClass);
|
||||
if (!CLASSES_WITH_NON_BOXED_CHARS.contains(containingClassName) &&
|
||||
!KotlinBuiltIns.isPrimitiveType(containingClass.getDefaultType()) &&
|
||||
!KotlinBuiltIns.isPrimitiveArray(containingClassName)
|
||||
) {
|
||||
return getAnyTypeFromSameModule(descriptor);
|
||||
}
|
||||
}
|
||||
return returnType;
|
||||
}
|
||||
|
||||
Set<KotlinType> typesFromOverriddenCallables = overridden.stream()
|
||||
.map(TranslationUtils::getReturnTypeForCoercion)
|
||||
.map(o -> getReturnTypeForCoercion(o, forcePrivate))
|
||||
.collect(Collectors.toSet());
|
||||
return typesFromOverriddenCallables.size() == 1
|
||||
? typesFromOverriddenCallables.iterator().next()
|
||||
: DescriptorUtils.getContainingModule(descriptor).getBuiltIns().getAnyType();
|
||||
: getAnyTypeFromSameModule(descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static KotlinType getAnyTypeFromSameModule(@NotNull DeclarationDescriptor descriptor) {
|
||||
return DescriptorUtils.getContainingModule(descriptor).getBuiltIns().getAnyType();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -435,7 +472,7 @@ public final class TranslationUtils {
|
||||
.collect(Collectors.toSet());
|
||||
return typesFromOverriddenCallables.size() == 1
|
||||
? typesFromOverriddenCallables.iterator().next()
|
||||
: DescriptorUtils.getContainingModule(descriptor).getBuiltIns().getAnyType();
|
||||
: getAnyTypeFromSameModule(descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// SKIP_MINIFICATION
|
||||
fun foo(): Char = '1'
|
||||
|
||||
val p1: Char = '2'
|
||||
|
||||
var p2: Char = '3'
|
||||
|
||||
var p3: Char = '4'
|
||||
get() = field + 1
|
||||
set(value) {
|
||||
field = value + 1
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var root = eval("_")
|
||||
|
||||
var r = typeOf(root.foo())
|
||||
if (r !== "number") return "fail1: $r"
|
||||
|
||||
r = typeOf(root.p1)
|
||||
if (r !== "number") return "fail2: $r"
|
||||
|
||||
r = typeOf(root.p2)
|
||||
if (r !== "number") return "fail3: $r"
|
||||
|
||||
r = typeOf(root.p3)
|
||||
if (r !== "number") return "fail4: $r"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun typeOf(x: dynamic): String = js("typeof x")
|
||||
@@ -0,0 +1,24 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1099
|
||||
private inline fun typeOf(x: dynamic): String = js("typeof x").unsafeCast<String>()
|
||||
|
||||
fun box(): String {
|
||||
val arr = charArrayOf('A')
|
||||
|
||||
var r = typeOf(arr.iterator().asDynamic().nextChar())
|
||||
if (r != "number") return "fail1: $r"
|
||||
r = typeOf(arr.iterator().asDynamic().next())
|
||||
if (r != "object") return "fail1a: $r"
|
||||
|
||||
var progression = 'A'..'Z'
|
||||
r = typeOf(progression.asDynamic().first)
|
||||
if (r != "number") return "fail2: $r"
|
||||
r = typeOf(progression.asDynamic().last)
|
||||
if (r != "number") return "fail3: $r"
|
||||
|
||||
r = typeOf(Char.asDynamic().MIN_HIGH_SURROGATE)
|
||||
if (r != "number") return "fail4: $r"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun getInt() = 65
|
||||
@@ -0,0 +1,41 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1039
|
||||
open class A {
|
||||
fun foo(): Char = 'X'
|
||||
}
|
||||
|
||||
interface I {
|
||||
fun foo(): Any
|
||||
}
|
||||
|
||||
class B : A(), I
|
||||
|
||||
fun typeOf(x: dynamic): String = js("typeof x")
|
||||
|
||||
fun box(): String {
|
||||
val b = B()
|
||||
val i: I = B()
|
||||
val a: A = B()
|
||||
|
||||
val r1 = typeOf(b.asDynamic().foo())
|
||||
if (r1 != "object") return "fail1: $r1"
|
||||
|
||||
val r2 = typeOf(i.asDynamic().foo())
|
||||
if (r2 != "object") return "fail2: $r2"
|
||||
|
||||
val r3 = typeOf(a.asDynamic().foo())
|
||||
if (r3 != "object") return "fail3: $r3"
|
||||
|
||||
val x4 = b.foo()
|
||||
val r4 = typeOf(x4)
|
||||
if (r4 != "number") return "fail4: $r4"
|
||||
|
||||
val x5 = i.foo()
|
||||
val r5 = typeOf(x5)
|
||||
if (r5 != "object") return "fail5: $r5"
|
||||
|
||||
val x6 = a.foo()
|
||||
val r6 = typeOf(x6)
|
||||
if (r6 != "number") return "fail6: $r6"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1039
|
||||
open class A {
|
||||
val foo: Char
|
||||
get() = 'X'
|
||||
|
||||
var bar: Char = 'Y'
|
||||
|
||||
val baz: Char = 'Q'
|
||||
|
||||
var mutable: Char = 'W'
|
||||
get() {
|
||||
typeOfMutable += typeOf(field.asDynamic()) + ";"
|
||||
return field + 1
|
||||
}
|
||||
set(value) {
|
||||
typeOfMutable += typeOf(js("value")) + ";" + typeOf(value)
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
interface I {
|
||||
val foo: Any
|
||||
|
||||
val bar: Any
|
||||
|
||||
val baz: Any
|
||||
|
||||
val mutable: Any
|
||||
}
|
||||
|
||||
class B : A(), I
|
||||
|
||||
fun typeOf(x: dynamic): String = js("typeof x")
|
||||
|
||||
var typeOfMutable = ""
|
||||
|
||||
fun box(): String {
|
||||
val a = B()
|
||||
val b: I = B()
|
||||
|
||||
val r1 = typeOf(a.foo)
|
||||
if (r1 != "number") return "fail1: $r1"
|
||||
|
||||
val r2 = typeOf(b.foo)
|
||||
if (r2 != "object") return "fail2: $r2"
|
||||
|
||||
val r3 = typeOf(a.asDynamic().foo)
|
||||
if (r3 != "object") return "fail3: $r3"
|
||||
|
||||
val r4 = typeOf(a.asDynamic().bar)
|
||||
if (r4 != "object") return "fail4: $r4"
|
||||
|
||||
val r5 = typeOf(a.asDynamic().baz)
|
||||
if (r5 != "object") return "fail5: $r5"
|
||||
|
||||
a.bar++
|
||||
val r6 = typeOf(a.asDynamic().bar)
|
||||
if (r6 != "object") return "fail6: $r6"
|
||||
|
||||
val r7 = typeOf(a.asDynamic().mutable)
|
||||
if (r7 != "object") return "fail7: $r7"
|
||||
|
||||
a.mutable = 'E'
|
||||
if (typeOfMutable != "number;object;number") return "fail8: $typeOfMutable"
|
||||
|
||||
val r9 = typeOf(a.mutable)
|
||||
if (r9 != "number") return "fail9: $r9"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -6,7 +6,8 @@ class CC(val s: CharSequence) : CharSequence by s, MyCharSequence {}
|
||||
interface MyCharSequence {
|
||||
val length: Int
|
||||
|
||||
operator fun get(index: Int): Char
|
||||
// TODO: uncomment when it's possible to implement bridges for get/charCodeAt
|
||||
//operator fun get(index: Int): Char
|
||||
|
||||
fun subSequence(startIndex: Int, endIndex: Int): CharSequence
|
||||
}
|
||||
@@ -25,17 +26,17 @@ fun box(): String {
|
||||
val cc: CharSequence = CC(kotlin)
|
||||
if (cc.length != 6) return "Fail 3: ${cc.length}"
|
||||
if (cc.subSequence(0, 3) != kot) return "Fail 4"
|
||||
if (cc[2] != 't') return "Fail 5: ${cc[2]}"
|
||||
//if (cc[2] != 't') return "Fail 5: ${cc[2]}"
|
||||
|
||||
val mcc: MyCharSequence = CC(kotlin)
|
||||
if (mcc.length != 6) return "Fail 6: ${mcc.length}"
|
||||
if (mcc.subSequence(0, 3) != kot) return "Fail 7"
|
||||
if (mcc[2] != 't') return "Fail 8: ${mcc[2]}"
|
||||
//if (mcc[2] != 't') return "Fail 8: ${mcc[2]}"
|
||||
|
||||
val ccc = CC(cc)
|
||||
if (ccc.length != 6) return "Fail 6: ${ccc.length}"
|
||||
if (ccc.subSequence(0, 3) != kot) return "Fail 7"
|
||||
if (ccc[2] != 't') return "Fail 8: ${ccc[2]}"
|
||||
//if (ccc[2] != 't') return "Fail 8: ${ccc[2]}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user