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:
@@ -262,4 +262,10 @@ public class AstUtil {
|
||||
result.setQualifier(new JsThisRef());
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return context.get(BindingContext.STATEMENT, expression);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ public final class ClassTranslator extends AbstractTranslator {
|
||||
return new JsObjectLiteral(propertyList);
|
||||
}
|
||||
|
||||
// TODO: names are inconsistent
|
||||
@NotNull
|
||||
private JsPropertyInitializer generateInitializeMethod(@NotNull JetClass classDeclaration) {
|
||||
JsPropertyInitializer initializer = new JsPropertyInitializer();
|
||||
|
||||
@@ -43,10 +43,22 @@ public class InitializerVisitor extends TranslatorVisitor<List<JsStatement>> {
|
||||
@NotNull
|
||||
private JsBlock generateInitializerMethodBody(@NotNull JetClass classDeclaration,
|
||||
@NotNull TranslationContext context) {
|
||||
List<JsStatement> initializerStatements = classDeclaration.accept(this, context);
|
||||
JsBlock block = new JsBlock();
|
||||
block.setStatements(initializerStatements);
|
||||
return block;
|
||||
|
||||
List<JsStatement> initializerStatements = generateCallToSuperMethod(classDeclaration, context);
|
||||
initializerStatements.addAll(classDeclaration.accept(this, context));
|
||||
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 GETTER_PREFIX = "get_";
|
||||
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 String getClassObjectName() {
|
||||
|
||||
@@ -37,7 +37,7 @@ public final class OperatorTable {
|
||||
binaryOperatorsMap.put(JetTokens.GTEQ, JsBinaryOperator.GTE);
|
||||
binaryOperatorsMap.put(JetTokens.LT, JsBinaryOperator.LT);
|
||||
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.EXCLEQ, JsBinaryOperator.NEQ);
|
||||
binaryOperatorsMap.put(JetTokens.PERC, JsBinaryOperator.MOD);
|
||||
|
||||
@@ -23,6 +23,11 @@ public final class ClassInheritanceTest extends AbstractClassTest {
|
||||
public void methodOverride() throws Exception {
|
||||
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")
|
||||
}
|
||||
@@ -24,9 +24,7 @@ var Class = (function() {
|
||||
parent = properties.shift();
|
||||
|
||||
function klass() {
|
||||
if (parent != null) {
|
||||
parent.prototype.initialize.apply(this)
|
||||
}
|
||||
this.initializing = klass;
|
||||
this.initialize.apply(this, arguments);
|
||||
}
|
||||
|
||||
@@ -40,6 +38,19 @@ var Class = (function() {
|
||||
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++)
|
||||
klass.addMethods(properties[i]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user