KT-11030 Simplify code and refactor generation of object expressions

This commit is contained in:
Alexey Andreev
2016-03-24 18:45:04 +03:00
parent c1c57a06bb
commit e305898f84
4 changed files with 24 additions and 58 deletions
@@ -39,9 +39,7 @@ import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWi
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstructorParameters import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getPrimaryConstructorParameters
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.toInvocationWith import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.toInvocationWith
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtSecondaryConstructor import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -197,33 +195,6 @@ class ClassTranslator private constructor(
} }
} }
private fun translateObjectInsideClass(outerClassContext: TranslationContext): JsExpression {
var outerDeclaration = descriptor.containingDeclaration.containingDeclaration
if (outerDeclaration != null && outerDeclaration !is ClassDescriptor) {
outerDeclaration = DescriptorUtils.getContainingClass(outerDeclaration)
}
val scope = if (outerDeclaration != null)
outerClassContext.getScopeForDescriptor(outerDeclaration)
else
outerClassContext.rootScope
val classContext = outerClassContext.innerWithUsageTracker(scope, descriptor)
var declarationArgs = getClassCreateInvocationArguments(classContext)
val jsClass = JsInvocation(context().namer().classCreationMethodReference(), declarationArgs)
val name = outerClassContext.getNameForDescriptor(descriptor)
val constructor = outerClassContext.define(name, jsClass)
val closure = outerClassContext.getLocalClassClosure(descriptor)
var closureArgs = emptyList<JsExpression>()
if (closure != null) {
closureArgs = closure.map { context().getParameterNameRefForInvocation(it) }.toList()
}
return JsNew(constructor, closureArgs)
}
private fun generatedBridgeMethods(properties: MutableList<JsPropertyInitializer>) { private fun generatedBridgeMethods(properties: MutableList<JsPropertyInitializer>) {
if (isTrait()) return if (isTrait()) return
@@ -270,7 +241,7 @@ class ClassTranslator private constructor(
} }
companion object { companion object {
fun translate(classDeclaration: KtClass, context: TranslationContext): List<JsPropertyInitializer> { fun translate(classDeclaration: KtClassOrObject, context: TranslationContext): List<JsPropertyInitializer> {
val result = arrayListOf<JsPropertyInitializer>() val result = arrayListOf<JsPropertyInitializer>()
val classDescriptor = getClassDescriptor(context.bindingContext(), classDeclaration) val classDescriptor = getClassDescriptor(context.bindingContext(), classDeclaration)
@@ -286,14 +257,10 @@ class ClassTranslator private constructor(
return result return result
} }
@JvmStatic fun generateClassCreation(classDeclaration: KtClassOrObject, context: TranslationContext): JsInvocation { private fun generateClassCreation(classDeclaration: KtClassOrObject, context: TranslationContext): JsInvocation {
return ClassTranslator(classDeclaration, context).translate() return ClassTranslator(classDeclaration, context).translate()
} }
@JvmStatic fun generateObjectLiteral(objectDeclaration: KtObjectDeclaration, context: TranslationContext): JsExpression {
return ClassTranslator(objectDeclaration, context).translateObjectInsideClass(context)
}
private fun generateSecondaryConstructor(constructor: KtSecondaryConstructor, context: TranslationContext): JsPropertyInitializer { private fun generateSecondaryConstructor(constructor: KtSecondaryConstructor, context: TranslationContext): JsPropertyInitializer {
// Prepare // Prepare
val constructorDescriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), constructor) as ConstructorDescriptor val constructorDescriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), constructor) as ConstructorDescriptor
@@ -73,22 +73,18 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry); ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
List<KotlinType> supertypes = getSupertypesWithoutFakes(descriptor); List<KotlinType> supertypes = getSupertypesWithoutFakes(descriptor);
if (enumEntry.getBody() != null || supertypes.size() > 1) { if (enumEntry.getBody() != null || supertypes.size() > 1) {
jsEnumEntryCreation = ClassTranslator.generateClassCreation(enumEntry, data); enumEntryList.addAll(ClassTranslator.Companion.translate(enumEntry, 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.get(0)); 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;
} }
@Override @Override
public Void visitObjectDeclaration(@NotNull KtObjectDeclaration declaration, TranslationContext context) { public Void visitObjectDeclaration(@NotNull KtObjectDeclaration declaration, TranslationContext context) {
JsExpression object = ClassTranslator.generateClassCreation(declaration, context); staticResult.addAll(ClassTranslator.Companion.translate(declaration, context));
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), declaration);
JsName objName = context.getNameForDescriptor(descriptor);
staticResult.add(new JsPropertyInitializer(objName.makeRef(), object));
return null; return null;
} }
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForDelegate import org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForDelegate
import org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForProperty import org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForProperty
import org.jetbrains.kotlin.js.translate.initializer.InitializerVisitor import org.jetbrains.kotlin.js.translate.initializer.InitializerVisitor
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptor import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptor
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClass
@@ -59,10 +58,7 @@ class FileDeclarationVisitor(
context!! context!!
// TODO: avoid duplication with superclass // TODO: avoid duplication with superclass
val obj = ClassTranslator.generateClassCreation(declaration, context) result.addAll(ClassTranslator.translate(declaration, context))
val descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), declaration)
val objName = context.getNameForDescriptor(descriptor)
result.add(JsPropertyInitializer(objName.makeRef(), obj))
return null return null
} }
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.TypeUtils;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor; import static org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor;
@@ -519,17 +520,23 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@Override @Override
@NotNull @NotNull
public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) { public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) {
return ClassTranslator.generateObjectLiteral(expression.getObjectDeclaration(), context); ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), expression.getObjectDeclaration());
} JsScope scope = context.getScopeForDescriptor(descriptor);
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
@Override List<JsPropertyInitializer> properties = ClassTranslator.Companion.translate(expression.getObjectDeclaration(), classContext);
@NotNull context.getDefinitionPlace().getProperties().addAll(properties);
public JsNode visitObjectDeclaration(@NotNull KtObjectDeclaration expression,
@NotNull TranslationContext context) { JsExpression constructor = context.getQualifiedReference(descriptor);
DeclarationDescriptor descriptor = getDescriptorForElement(context.bindingContext(), expression); List<DeclarationDescriptor> closure = context.getLocalClassClosure(descriptor);
JsName name = context.getNameForDescriptor(descriptor); List<JsExpression> closureArgs = new ArrayList<JsExpression>();
JsExpression value = ClassTranslator.generateClassCreation(expression, context); if (closure != null) {
return newVar(name, value).source(expression); for (DeclarationDescriptor capturedValue : closure) {
closureArgs.add(context.getParameterNameRefForInvocation(capturedValue));
}
}
return new JsNew(constructor, closureArgs);
} }
@Override @Override
@@ -569,7 +576,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@Override @Override
public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) { public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) {
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass); ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass);
JsObjectScope scope = new JsObjectScope(context.scope(), descriptor.toString(), ""); JsScope scope = context.getScopeForDescriptor(descriptor);
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor); TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
context.getDefinitionPlace().getProperties().addAll(ClassTranslator.Companion.translate(klass, classContext)); context.getDefinitionPlace().getProperties().addAll(ClassTranslator.Companion.translate(klass, classContext));