JS backend: use jet.Iterable and jet.Any as "fake" classes.

This commit is contained in:
Zalim Bashorov
2013-11-01 19:22:30 +04:00
parent 060d7c5345
commit 5c6cfce8ab
5 changed files with 75 additions and 13 deletions
@@ -75,6 +75,9 @@ public final class ClassInheritanceTest extends SingleFileTranslationTest {
public void testKt3499() throws Exception { public void testKt3499() throws Exception {
fooBoxTest(); fooBoxTest();
} }
public void testFromFakeClasses() throws Exception {
checkFooBoxIsOk();
}
} }
@@ -44,6 +44,7 @@ import static org.jetbrains.k2js.translate.initializer.InitializerUtils.createCl
import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter; import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContainingClass; import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContainingClass;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getPrimaryConstructorParameters; import static org.jetbrains.k2js.translate.utils.PsiUtils.getPrimaryConstructorParameters;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.simpleReturnFunction; import static org.jetbrains.k2js.translate.utils.TranslationUtils.simpleReturnFunction;
@@ -220,16 +221,13 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull @NotNull
private List<JsExpression> getSupertypesNameReferences() { private List<JsExpression> getSupertypesNameReferences() {
Collection<JetType> supertypes = descriptor.getTypeConstructor().getSupertypes(); List<JetType> supertypes = getSupertypesWithoutFakes(descriptor);
if (supertypes.isEmpty()) { if (supertypes.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
if (supertypes.size() == 1) { if (supertypes.size() == 1) {
JetType type = supertypes.iterator().next(); JetType type = supertypes.get(0);
ClassDescriptor supertypeDescriptor = getClassDescriptorForType(type); ClassDescriptor supertypeDescriptor = getClassDescriptorForType(type);
if (isAny(supertypeDescriptor)) {
return Collections.emptyList();
}
return Collections.<JsExpression>singletonList(getClassReference(supertypeDescriptor)); return Collections.<JsExpression>singletonList(getClassReference(supertypeDescriptor));
} }
@@ -244,9 +242,7 @@ public final class ClassTranslator extends AbstractTranslator {
for (TypeConstructor typeConstructor : sortedAllSuperTypes) { for (TypeConstructor typeConstructor : sortedAllSuperTypes) {
if (supertypeConstructors.contains(typeConstructor)) { if (supertypeConstructors.contains(typeConstructor)) {
ClassDescriptor supertypeDescriptor = getClassDescriptorForTypeConstructor(typeConstructor); ClassDescriptor supertypeDescriptor = getClassDescriptorForTypeConstructor(typeConstructor);
if (!isAny(supertypeDescriptor)) { supertypesRefs.add(getClassReference(supertypeDescriptor));
supertypesRefs.add(getClassReference(supertypeDescriptor));
}
} }
} }
return supertypesRefs; return supertypesRefs;
@@ -35,12 +35,12 @@ import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils;
import java.util.Collection;
import java.util.List; import java.util.List;
import static org.jetbrains.k2js.translate.initializer.InitializerUtils.createClassObjectInitializer; import static org.jetbrains.k2js.translate.initializer.InitializerUtils.createClassObjectInitializer;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes;
public class DeclarationBodyVisitor extends TranslatorVisitor<Void> { public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
@KotlinSignature("val result: MutableList<JsPropertyInitializer>") @KotlinSignature("val result: MutableList<JsPropertyInitializer>")
@@ -75,12 +75,12 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
public Void visitEnumEntry(@NotNull JetEnumEntry enumEntry, TranslationContext data) { public Void visitEnumEntry(@NotNull JetEnumEntry enumEntry, TranslationContext data) {
JsExpression jsEnumEntryCreation; JsExpression jsEnumEntryCreation;
ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry); ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
Collection<JetType> supertypes = descriptor.getTypeConstructor().getSupertypes(); List<JetType> supertypes = getSupertypesWithoutFakes(descriptor);
if (enumEntry.getBody() != null || supertypes.size() > 1) { if (enumEntry.getBody() != null || supertypes.size() > 1) {
jsEnumEntryCreation = ClassTranslator.generateClassCreation(enumEntry, descriptor, data); jsEnumEntryCreation = ClassTranslator.generateClassCreation(enumEntry, descriptor, data);
} else { } else {
assert supertypes.size() == 1 : "Simple Enum entry must have one supertype"; assert supertypes.size() == 1 : "Simple Enum entry must have one supertype";
jsEnumEntryCreation = new ClassInitializerTranslator(enumEntry, data).generateEnumEntryInstanceCreation(supertypes.iterator().next()); jsEnumEntryCreation = new ClassInitializerTranslator(enumEntry, data).generateEnumEntryInstanceCreation(supertypes.get(0));
} }
enumEntryList.add(new JsPropertyInitializer(data.getNameForDescriptor(descriptor).makeRef(), jsEnumEntryCreation)); enumEntryList.add(new JsPropertyInitializer(data.getNameForDescriptor(descriptor).makeRef(), jsEnumEntryCreation));
return null; return null;
@@ -16,6 +16,8 @@
package org.jetbrains.k2js.translate.utils; package org.jetbrains.k2js.translate.utils;
import com.intellij.openapi.util.Condition;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -29,13 +31,19 @@ import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getSuperclassDescriptors; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFQName;
public final class JsDescriptorUtils { public final class JsDescriptorUtils {
// TODO: maybe we should use external annotations or something else.
private static final Set<String> FAKE_CLASSES = ContainerUtil.immutableSet(
getFQName(KotlinBuiltIns.getInstance().getAny()).toSafe().asString(),
"jet.Iterable"
);
private JsDescriptorUtils() { private JsDescriptorUtils() {
} }
@@ -67,6 +75,18 @@ public final class JsDescriptorUtils {
return findAncestorClass(getSuperclassDescriptors(classDescriptor)); return findAncestorClass(getSuperclassDescriptors(classDescriptor));
} }
@NotNull
public static List<JetType> getSupertypesWithoutFakes(ClassDescriptor descriptor) {
Collection<JetType> supertypes = descriptor.getTypeConstructor().getSupertypes();
return ContainerUtil.filter(supertypes, new Condition<JetType>() {
@Override
public boolean value(JetType type) {
ClassDescriptor classDescriptor = getClassDescriptorForType(type);
return !FAKE_CLASSES.contains(getFQName(classDescriptor).toSafe().asString());
}
});
}
@NotNull @NotNull
public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) { public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containing = descriptor.getContainingDeclaration(); DeclarationDescriptor containing = descriptor.getContainingDeclaration();
@@ -0,0 +1,43 @@
package foo
class FromAny: Any()
class FromItrable(val n: Int): Iterable<Int> {
override fun iterator() = object: Iterator<Int> {
var i = 0
override fun next() = i++
override fun hasNext() = i < n
}
}
fun <T> Iterable<T>.stringify(): String {
var s = ""
for (i in this) s += i
return s
}
fun box(): String {
val a = FromAny()
val it = FromItrable(3)
val s = it.stringify()
if (s != "012") return "s /*$s*/ != 012"
var ao = object : Any() {}
var ito = object : Iterable<Int> {
override public fun iterator() = object: Iterator<Int> {
var i = 0
override fun next(): Int {
var r = i
i += 2
return r
}
override fun hasNext() = i < 9
}
}
val so = ito.stringify()
if (so != "02468") return "so /*$so*/ != 02468"
return "OK"
}