JS: fix some minor issues in new flat translator

This commit is contained in:
Alexey Andreev
2016-10-19 15:52:09 +03:00
parent 06476402a2
commit bb57eaef96
9 changed files with 39 additions and 23 deletions
@@ -62,8 +62,7 @@ enum class TypeCheck {
INSTANCEOF, INSTANCEOF,
OR_NULL, OR_NULL,
IS_ANY, IS_ANY,
AND_PREDICATE, AND_PREDICATE
SAME_AS
} }
enum class SideEffectKind { enum class SideEffectKind {
@@ -25,8 +25,10 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForReceiver import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForReceiver
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.* import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
@@ -144,6 +146,14 @@ private fun TranslationContext.createCallInfo(
} }
} }
} }
if (dispatchReceiver == null) {
val container = resolvedCall.resultingDescriptor.containingDeclaration
if (DescriptorUtils.isObject(container)) {
dispatchReceiver = ReferenceTranslator.translateAsValueReference(container, this)
}
}
return object : AbstractCallInfo(), CallInfo { return object : AbstractCallInfo(), CallInfo {
override val context: TranslationContext = this@createCallInfo override val context: TranslationContext = this@createCallInfo
override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall
@@ -320,11 +320,6 @@ public final class Namer {
return invokeFunctionAndSetTypeCheckMetadata("isInstanceOf", type, TypeCheck.INSTANCEOF); return invokeFunctionAndSetTypeCheckMetadata("isInstanceOf", type, TypeCheck.INSTANCEOF);
} }
@NotNull
public JsExpression isInstanceOfObject(@NotNull JsExpression type) {
return invokeFunctionAndSetTypeCheckMetadata("isInstanceOf", type, TypeCheck.SAME_AS);
}
@NotNull @NotNull
public JsExpression orNull(@NotNull JsExpression callable) { public JsExpression orNull(@NotNull JsExpression callable) {
return invokeFunctionAndSetTypeCheckMetadata("orNull", callable, TypeCheck.OR_NULL); return invokeFunctionAndSetTypeCheckMetadata("orNull", callable, TypeCheck.OR_NULL);
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt; import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.utils.DFS;
import java.util.*; import java.util.*;
@@ -752,10 +753,16 @@ public final class StaticContext {
} }
private void addInterfaceDefaultMethods() { private void addInterfaceDefaultMethods() {
for (ClassDescriptor classDescriptor : classes) { List<ClassDescriptor> orderedClasses = DFS.topologicalOrder(classes, new DFS.Neighbors<ClassDescriptor>() {
if (classDescriptor.getKind() != ClassKind.INTERFACE) { @NotNull
ClassTranslator.addInterfaceDefaultMembers(classDescriptor, this); @Override
public Iterable<? extends ClassDescriptor> getNeighbors(ClassDescriptor current) {
return DescriptorUtils.getSuperclassDescriptors(current);
} }
});
Collections.reverse(orderedClasses);
for (ClassDescriptor classDescriptor : orderedClasses) {
ClassTranslator.addInterfaceDefaultMembers(classDescriptor, this);
} }
} }
@@ -180,6 +180,12 @@ class ClassTranslator private constructor(
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("type"), typeRef) metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("type"), typeRef)
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("classIndex"), typeIndex) metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("classIndex"), typeIndex)
val simpleName = descriptor.name
if (!simpleName.isSpecial) {
val simpleNameProp = JsPropertyInitializer(JsNameRef("simpleName"), program().getStringLiteral(simpleName.identifier))
metadataLiteral.propertyInitializers += simpleNameProp
}
} }
private fun generateSecondaryConstructor(classContext: TranslationContext, constructor: KtSecondaryConstructor) { private fun generateSecondaryConstructor(classContext: TranslationContext, constructor: KtSecondaryConstructor) {
@@ -506,12 +512,16 @@ class ClassTranslator private constructor(
DescriptorUtils.isInterface(it.containingDeclaration) } DescriptorUtils.isInterface(it.containingDeclaration) }
.firstOrNull() ?: continue .firstOrNull() ?: continue
if (overriddenFunction.modality == Modality.ABSTRACT) continue
val interfaceDescriptor = overriddenFunction.containingDeclaration as ClassDescriptor val interfaceDescriptor = overriddenFunction.containingDeclaration as ClassDescriptor
if (interfaceDescriptor.kind != ClassKind.INTERFACE) continue if (interfaceDescriptor.kind != ClassKind.INTERFACE) continue
val directContainer = member.overriddenDescriptors.first().containingDeclaration as ClassDescriptor
when (member) { when (member) {
is FunctionDescriptor -> addDefaultMethodFromInterface(member, interfaceDescriptor, descriptor, context) is FunctionDescriptor -> addDefaultMethodFromInterface(member, directContainer, descriptor, context)
is PropertyDescriptor -> addDefaultPropertyFromInterface(member, interfaceDescriptor, descriptor, context) is PropertyDescriptor -> addDefaultPropertyFromInterface(member, directContainer, descriptor, context)
} }
} }
} }
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import java.util.*
class DeclarationBodyVisitor( class DeclarationBodyVisitor(
private val containingClass: ClassDescriptor, private val containingClass: ClassDescriptor,
@@ -78,6 +77,8 @@ class DeclarationBodyVisitor(
enumInstanceFunction.body.statements += JsReturn(enumInstanceName.makeRef()) enumInstanceFunction.body.statements += JsReturn(enumInstanceName.makeRef())
} }
context.export(descriptor)
enumEntryOrdinal++ enumEntryOrdinal++
} }
@@ -171,7 +171,7 @@ public final class PatternTranslator extends AbstractTranslator {
ClassDescriptor referencedClass = DescriptorUtils.getClassDescriptorForType(type); ClassDescriptor referencedClass = DescriptorUtils.getClassDescriptorForType(type);
JsExpression typeName = ReferenceTranslator.translateAsTypeReference(referencedClass, context()); JsExpression typeName = ReferenceTranslator.translateAsTypeReference(referencedClass, context());
return referencedClass.getKind() != ClassKind.OBJECT ? namer().isInstanceOf(typeName) : namer().isInstanceOfObject(typeName); return namer().isInstanceOf(typeName);
} }
@Nullable @Nullable
@@ -86,12 +86,6 @@ private class TypeCheckRewritingVisitor(private val context: TranslationContext)
if (calleeArguments.size == 1) context.namer().isInstanceOf(argument, calleeArguments[0]) else null if (calleeArguments.size == 1) context.namer().isInstanceOf(argument, calleeArguments[0]) else null
} }
TypeCheck.SAME_AS -> {
// `Kotlin.isInstanceOf(calleeArgument)(argument)` -> `argument === calleeArgument`
// when it's known at compile time that `argument` represents an object type
if (calleeArguments.size == 1) JsAstUtils.equality(argument, calleeArguments[0]) else null
}
TypeCheck.OR_NULL -> { TypeCheck.OR_NULL -> {
// `Kotlin.orNull(calleeArgument)(argument)` -> `(tmp = argument) == null || calleeArgument(tmp)` // `Kotlin.orNull(calleeArgument)(argument)` -> `(tmp = argument) == null || calleeArgument(tmp)`
if (calleeArguments.size == 1) getReplacementForOrNull(argument, calleeArguments[0]) else null if (calleeArguments.size == 1) getReplacementForOrNull(argument, calleeArguments[0]) else null
+3 -3
View File
@@ -5,10 +5,10 @@ fun testWithInstance() {
assertEquals("B", B().jsClass.name) assertEquals("B", B().jsClass.name)
assertEquals("O", O.jsClass.name) assertEquals("O", O.jsClass.name)
assertEquals("E", E.X.jsClass.name) assertEquals("E", E.X.jsClass.name)
assertEquals("Y", E.Y.jsClass.name) assertEquals("E\$Y", E.Y.jsClass.name)
// TODO uncomment after KT-13338 is fixed // TODO uncomment after KT-13338 is fixed
// assertEquals("E", E.Z.jsClass.name) // assertEquals("E", E.Z.jsClass.name)
assertEquals("Q", R().jsClass.name) assertEquals("R", R().jsClass.name)
} }
fun testWithClassReference() { fun testWithClassReference() {
@@ -17,7 +17,7 @@ fun testWithClassReference() {
assertEquals("O", jsClass<O>().name) assertEquals("O", jsClass<O>().name)
assertEquals("I", jsClass<I>().name) assertEquals("I", jsClass<I>().name)
assertEquals("E", jsClass<E>().name) assertEquals("E", jsClass<E>().name)
assertEquals("Q", jsClass<R>().name) assertEquals("R", jsClass<R>().name)
} }
fun box(): String { fun box(): String {