Found and solved a problem which caused only one ancestor's constructor to be called. Added "super_init" method generation to InitializerVisitor. Worked on KotlinJsLib to solve this issue. This solution should evolve in the future.

This commit is contained in:
Pavel Talanov
2011-11-15 21:05:54 +04:00
parent a120125e5a
commit 17e41e627d
9 changed files with 74 additions and 8 deletions
@@ -262,4 +262,10 @@ public class AstUtil {
result.setQualifier(new JsThisRef()); result.setQualifier(new JsThisRef());
return result; return result;
} }
public static JsBlock newBlock(List<JsStatement> statements) {
JsBlock result = new JsBlock();
result.setStatements(statements);
return result;
}
} }
@@ -101,6 +101,10 @@ public final class BindingUtils {
return superClassDescriptors; return superClassDescriptors;
} }
static public boolean hasAncestor(@NotNull BindingContext context, @NotNull JetClass classDeclaration) {
return !getSuperclassDescriptors(context, classDeclaration).isEmpty();
}
static public boolean isStatement(@NotNull BindingContext context, @NotNull JetExpression expression) { static public boolean isStatement(@NotNull BindingContext context, @NotNull JetExpression expression) {
return context.get(BindingContext.STATEMENT, expression); return context.get(BindingContext.STATEMENT, expression);
} }
@@ -73,6 +73,7 @@ public final class ClassTranslator extends AbstractTranslator {
return new JsObjectLiteral(propertyList); return new JsObjectLiteral(propertyList);
} }
// TODO: names are inconsistent
@NotNull @NotNull
private JsPropertyInitializer generateInitializeMethod(@NotNull JetClass classDeclaration) { private JsPropertyInitializer generateInitializeMethod(@NotNull JetClass classDeclaration) {
JsPropertyInitializer initializer = new JsPropertyInitializer(); JsPropertyInitializer initializer = new JsPropertyInitializer();
@@ -43,10 +43,22 @@ public class InitializerVisitor extends TranslatorVisitor<List<JsStatement>> {
@NotNull @NotNull
private JsBlock generateInitializerMethodBody(@NotNull JetClass classDeclaration, private JsBlock generateInitializerMethodBody(@NotNull JetClass classDeclaration,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
List<JsStatement> initializerStatements = classDeclaration.accept(this, context);
JsBlock block = new JsBlock(); List<JsStatement> initializerStatements = generateCallToSuperMethod(classDeclaration, context);
block.setStatements(initializerStatements); initializerStatements.addAll(classDeclaration.accept(this, context));
return block; return AstUtil.newBlock(initializerStatements);
}
@NotNull
private List<JsStatement> generateCallToSuperMethod(@NotNull JetClass classDeclaration,
@NotNull TranslationContext context) {
List<JsStatement> result = new ArrayList<JsStatement>();
if (BindingUtils.hasAncestor(context.bindingContext(), classDeclaration)) {
JsName superMethodName = initializerMethodScope.declareName(Namer.SUPER_METHOD_NAME);
result.add(AstUtil.convertToStatement
(AstUtil.newInvocation(AstUtil.thisQualifiedReference(superMethodName))));
}
return result;
} }
@@ -22,6 +22,7 @@ public final class Namer {
private static final String SETTER_PREFIX = "set_"; private static final String SETTER_PREFIX = "set_";
private static final String GETTER_PREFIX = "get_"; private static final String GETTER_PREFIX = "get_";
private static final String BACKING_FIELD_PREFIX = "$"; private static final String BACKING_FIELD_PREFIX = "$";
public static final String SUPER_METHOD_NAME = "super_init";
// public static final String DEFAULT_SETTER_PARAM_NAME = "val"; // public static final String DEFAULT_SETTER_PARAM_NAME = "val";
public static String getClassObjectName() { public static String getClassObjectName() {
@@ -37,7 +37,7 @@ public final class OperatorTable {
binaryOperatorsMap.put(JetTokens.GTEQ, JsBinaryOperator.GTE); binaryOperatorsMap.put(JetTokens.GTEQ, JsBinaryOperator.GTE);
binaryOperatorsMap.put(JetTokens.LT, JsBinaryOperator.LT); binaryOperatorsMap.put(JetTokens.LT, JsBinaryOperator.LT);
binaryOperatorsMap.put(JetTokens.LTEQ, JsBinaryOperator.LTE); binaryOperatorsMap.put(JetTokens.LTEQ, JsBinaryOperator.LTE);
binaryOperatorsMap.put(JetTokens.EQEQ, JsBinaryOperator.EQ); binaryOperatorsMap.put(JetTokens.EQEQ, JsBinaryOperator.REF_EQ);
binaryOperatorsMap.put(JetTokens.ANDAND, JsBinaryOperator.AND); binaryOperatorsMap.put(JetTokens.ANDAND, JsBinaryOperator.AND);
binaryOperatorsMap.put(JetTokens.EXCLEQ, JsBinaryOperator.NEQ); binaryOperatorsMap.put(JetTokens.EXCLEQ, JsBinaryOperator.NEQ);
binaryOperatorsMap.put(JetTokens.PERC, JsBinaryOperator.MOD); binaryOperatorsMap.put(JetTokens.PERC, JsBinaryOperator.MOD);
@@ -23,6 +23,11 @@ public final class ClassInheritanceTest extends AbstractClassTest {
public void methodOverride() throws Exception { public void methodOverride() throws Exception {
testFooBoxIsTrue("methodOverride.kt"); testFooBoxIsTrue("methodOverride.kt");
} }
@Test
public void initializationOrder() throws Exception {
testFooBoxIsTrue("initializationOrder.kt");
}
} }
@@ -0,0 +1,26 @@
namespace foo
open class A() {
var order = ""
{
order = order + "A"
}
}
open class B() : A() {
{
order = order + "B"
}
}
class C() : B() {
{
order = order + "C"
}
}
fun box() : Boolean {
return (C().order == "ABC") && (B().order == "AB") && (A().order == "A")
}
+14 -3
View File
@@ -24,9 +24,7 @@ var Class = (function() {
parent = properties.shift(); parent = properties.shift();
function klass() { function klass() {
if (parent != null) { this.initializing = klass;
parent.prototype.initialize.apply(this)
}
this.initialize.apply(this, arguments); this.initialize.apply(this, arguments);
} }
@@ -40,6 +38,19 @@ var Class = (function() {
parent.subclasses.push(klass); parent.subclasses.push(klass);
} }
if (parent != null) {
klass.addMethods(
{
'super_init' : function () {
//if (this.initializing != null) {
this.initializing = this.initializing.superclass;
this.initializing.prototype.initialize.apply(this, arguments)
// }
}
});
}
for (var i = 0, length = properties.length; i < length; i++) for (var i = 0, length = properties.length; i < length; i++)
klass.addMethods(properties[i]); klass.addMethods(properties[i]);