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 {
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.getPropertyDescriptorForConstructorParameter;
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.TranslationUtils.simpleReturnFunction;
@@ -220,16 +221,13 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull
private List<JsExpression> getSupertypesNameReferences() {
Collection<JetType> supertypes = descriptor.getTypeConstructor().getSupertypes();
List<JetType> supertypes = getSupertypesWithoutFakes(descriptor);
if (supertypes.isEmpty()) {
return Collections.emptyList();
}
if (supertypes.size() == 1) {
JetType type = supertypes.iterator().next();
JetType type = supertypes.get(0);
ClassDescriptor supertypeDescriptor = getClassDescriptorForType(type);
if (isAny(supertypeDescriptor)) {
return Collections.emptyList();
}
return Collections.<JsExpression>singletonList(getClassReference(supertypeDescriptor));
}
@@ -244,9 +242,7 @@ public final class ClassTranslator extends AbstractTranslator {
for (TypeConstructor typeConstructor : sortedAllSuperTypes) {
if (supertypeConstructors.contains(typeConstructor)) {
ClassDescriptor supertypeDescriptor = getClassDescriptorForTypeConstructor(typeConstructor);
if (!isAny(supertypeDescriptor)) {
supertypesRefs.add(getClassReference(supertypeDescriptor));
}
supertypesRefs.add(getClassReference(supertypeDescriptor));
}
}
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.TranslationUtils;
import java.util.Collection;
import java.util.List;
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.getFunctionDescriptor;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes;
public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
@KotlinSignature("val result: MutableList<JsPropertyInitializer>")
@@ -75,12 +75,12 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
public Void visitEnumEntry(@NotNull JetEnumEntry enumEntry, TranslationContext data) {
JsExpression jsEnumEntryCreation;
ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
Collection<JetType> supertypes = descriptor.getTypeConstructor().getSupertypes();
List<JetType> supertypes = getSupertypesWithoutFakes(descriptor);
if (enumEntry.getBody() != null || supertypes.size() > 1) {
jsEnumEntryCreation = ClassTranslator.generateClassCreation(enumEntry, descriptor, data);
} else {
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));
return null;
@@ -16,6 +16,8 @@
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.Nullable;
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.k2js.translate.context.TranslationContext;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getSuperclassDescriptors;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFQName;
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() {
}
@@ -67,6 +75,18 @@ public final class JsDescriptorUtils {
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
public static DeclarationDescriptor getContainingDeclaration(@NotNull DeclarationDescriptor descriptor) {
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"
}