Minor improvments in ClassTranslator after conversion

This commit is contained in:
Zalim Bashorov
2015-05-27 19:28:49 +03:00
parent c589026a47
commit 6e7be78b98
@@ -20,105 +20,105 @@ import com.google.dart.compiler.backend.js.ast.*
import com.intellij.util.SmartList import com.intellij.util.SmartList
import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.common.bridges.Bridge import org.jetbrains.kotlin.backend.common.bridges.Bridge
import org.jetbrains.kotlin.backend.common.bridges.* import org.jetbrains.kotlin.backend.common.bridges.generateBridgesForFunctionDescriptor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.js.translate.context.DefinitionPlace import org.jetbrains.kotlin.js.translate.context.DefinitionPlace
import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.declaration.propertyTranslator.* import org.jetbrains.kotlin.js.translate.declaration.propertyTranslator.translateAccessors
import org.jetbrains.kotlin.js.translate.expression.* import org.jetbrains.kotlin.js.translate.expression.withCapturedParameters
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.*
import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.psi.JetObjectDeclaration
import org.jetbrains.kotlin.psi.JetParameter
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeConstructor
import java.util.*
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator.translateAsFQReference import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator.translateAsFQReference
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter
import org.jetbrains.kotlin.js.translate.utils.ID
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForDeclaration import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForDeclaration
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
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.UtilsPackage.generateDelegateCall import org.jetbrains.kotlin.js.translate.utils.generateDelegateCall
import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.psi.JetObjectDeclaration
import org.jetbrains.kotlin.resolve.DescriptorUtils.* import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeUtils.topologicallySortSuperclassesAndRecordAllInstances import org.jetbrains.kotlin.types.TypeUtils.topologicallySortSuperclassesAndRecordAllInstances
import java.util.ArrayList
import java.util.HashMap
import java.util.HashSet
import kotlin.platform.platformStatic
/** /**
* Generates a definition of a single class. * Generates a definition of a single class.
*/ */
public class ClassTranslator private (private val classDeclaration: JetClassOrObject, context: TranslationContext) : AbstractTranslator(context) { public class ClassTranslator private constructor(
private val classDeclaration: JetClassOrObject,
context: TranslationContext
) : AbstractTranslator(context) {
private val descriptor: ClassDescriptor private val descriptor = getClassDescriptor(context.bindingContext(), classDeclaration)
init {
this.descriptor = getClassDescriptor(context.bindingContext(), classDeclaration)
}
private fun translateObjectLiteralExpression(): JsExpression { private fun translateObjectLiteralExpression(): JsExpression {
val containingClass = getContainingClass(descriptor) ?: return translate(context()) getContainingClass(descriptor) ?: return translate(context())
return translateObjectInsideClass(context()) return translateObjectInsideClass(context())
} }
overloads public fun translate(declarationContext: TranslationContext = context()): JsInvocation { public fun translate(declarationContext: TranslationContext = context()): JsInvocation {
return JsInvocation(context().namer().classCreateInvocation(descriptor), getClassCreateInvocationArguments(declarationContext)) return JsInvocation(context().namer().classCreateInvocation(descriptor), getClassCreateInvocationArguments(declarationContext))
} }
private fun isTrait(): Boolean { private fun isTrait(): Boolean = descriptor.getKind() == ClassKind.INTERFACE
return descriptor.getKind() == ClassKind.INTERFACE
}
private fun getClassCreateInvocationArguments(declarationContext: TranslationContext): List<JsExpression> { private fun getClassCreateInvocationArguments(declarationContext: TranslationContext): List<JsExpression> {
var declarationContext = declarationContext var context = declarationContext
val invocationArguments = ArrayList<JsExpression>() val invocationArguments = ArrayList<JsExpression>()
val properties = SmartList<JsPropertyInitializer>() val properties = SmartList<JsPropertyInitializer>()
val staticProperties = SmartList<JsPropertyInitializer>() val staticProperties = SmartList<JsPropertyInitializer>()
val isTopLevelDeclaration = context() == declarationContext val isTopLevelDeclaration = context() == context
var qualifiedReference: JsNameRef? = null var qualifiedReference: JsNameRef? = null
if (isTopLevelDeclaration) { if (isTopLevelDeclaration) {
var definitionPlace: DefinitionPlace? = null var definitionPlace: DefinitionPlace? = null
if (!descriptor.getKind().isSingleton() && !isAnonymousObject(descriptor)) { if (!descriptor.getKind().isSingleton() && !isAnonymousObject(descriptor)) {
qualifiedReference = declarationContext.getQualifiedReference(descriptor) qualifiedReference = context.getQualifiedReference(descriptor)
val scope = context().getScopeForDescriptor(descriptor) val scope = context().getScopeForDescriptor(descriptor)
definitionPlace = DefinitionPlace(scope as JsObjectScope, qualifiedReference, staticProperties) definitionPlace = DefinitionPlace(scope as JsObjectScope, qualifiedReference, staticProperties)
} }
declarationContext = declarationContext.newDeclaration(descriptor, definitionPlace) context = context.newDeclaration(descriptor, definitionPlace)
} }
declarationContext = fixContextForCompanionObjectAccessing(declarationContext) context = fixContextForCompanionObjectAccessing(context)
invocationArguments.add(getSuperclassReferences(declarationContext)) invocationArguments.add(getSuperclassReferences(context))
val delegationTranslator = DelegationTranslator(classDeclaration, context()) val delegationTranslator = DelegationTranslator(classDeclaration, context())
if (!isTrait()) { if (!isTrait()) {
val initializer = ClassInitializerTranslator(classDeclaration, declarationContext).generateInitializeMethod(delegationTranslator) val initializer = ClassInitializerTranslator(classDeclaration, context).generateInitializeMethod(delegationTranslator)
invocationArguments.add(if (initializer.getBody().getStatements().isEmpty()) JsLiteral.NULL else initializer) invocationArguments.add(if (initializer.getBody().getStatements().isEmpty()) JsLiteral.NULL else initializer)
} }
translatePropertiesAsConstructorParameters(declarationContext, properties) translatePropertiesAsConstructorParameters(context, properties)
val bodyVisitor = DeclarationBodyVisitor(properties, staticProperties) val bodyVisitor = DeclarationBodyVisitor(properties, staticProperties)
bodyVisitor.traverseContainer(classDeclaration, declarationContext) bodyVisitor.traverseContainer(classDeclaration, context)
delegationTranslator.generateDelegated(properties) delegationTranslator.generateDelegated(properties)
if (KotlinBuiltIns.isData(descriptor)) { if (KotlinBuiltIns.isData(descriptor)) {
JsDataClassGenerator(classDeclaration, declarationContext, properties).generate() JsDataClassGenerator(classDeclaration, context, properties).generate()
} }
if (isEnumClass(descriptor)) { if (isEnumClass(descriptor)) {
val enumEntries = JsObjectLiteral(bodyVisitor.getEnumEntryList(), true) val enumEntries = JsObjectLiteral(bodyVisitor.getEnumEntryList(), true)
val function = simpleReturnFunction(declarationContext.getScopeForDescriptor(descriptor), enumEntries) val function = simpleReturnFunction(context.getScopeForDescriptor(descriptor), enumEntries)
invocationArguments.add(function) invocationArguments.add(function)
} }
@@ -145,25 +145,24 @@ public class ClassTranslator private (private val classDeclaration: JetClassOrOb
return invocationArguments return invocationArguments
} }
private fun fixContextForCompanionObjectAccessing(declarationContext: TranslationContext): TranslationContext { private fun fixContextForCompanionObjectAccessing(context: TranslationContext): TranslationContext {
var declarationContext = declarationContext
// In Kotlin we can access to companion object members without qualifier just by name, but we should translate it to access with FQ name. // In Kotlin we can access to companion object members without qualifier just by name, but we should translate it to access with FQ name.
// So create alias for companion object receiver parameter. // So create alias for companion object receiver parameter.
val companionObjectDescriptor = descriptor.getCompanionObjectDescriptor() val companionObjectDescriptor = descriptor.getCompanionObjectDescriptor()
if (companionObjectDescriptor != null) { if (companionObjectDescriptor != null) {
val referenceToClass = translateAsFQReference(companionObjectDescriptor.getContainingDeclaration(), declarationContext) val referenceToClass = translateAsFQReference(companionObjectDescriptor.getContainingDeclaration(), context)
val companionObjectAccessor = Namer.getCompanionObjectAccessor(referenceToClass) val companionObjectAccessor = Namer.getCompanionObjectAccessor(referenceToClass)
val companionObjectReceiver = getReceiverParameterForDeclaration(companionObjectDescriptor) val companionObjectReceiver = getReceiverParameterForDeclaration(companionObjectDescriptor)
declarationContext.aliasingContext().registerAlias(companionObjectReceiver, companionObjectAccessor) context.aliasingContext().registerAlias(companionObjectReceiver, companionObjectAccessor)
} }
// Overlap alias of companion object receiver for accessing from containing class(see previous if block), // Overlap alias of companion object receiver for accessing from containing class(see previous if block),
// because inside companion object we should use simple name for access. // because inside companion object we should use simple name for access.
if (isCompanionObject(descriptor)) { if (isCompanionObject(descriptor)) {
declarationContext = declarationContext.innerContextWithAliased(descriptor.getThisAsReceiverParameter(), JsLiteral.THIS) return context.innerContextWithAliased(descriptor.getThisAsReceiverParameter(), JsLiteral.THIS)
} }
return declarationContext return context
} }
private fun getSuperclassReferences(declarationContext: TranslationContext): JsExpression { private fun getSuperclassReferences(declarationContext: TranslationContext): JsExpression {
@@ -216,12 +215,12 @@ public class ClassTranslator private (private val classDeclaration: JetClassOrOb
} }
private fun translateObjectInsideClass(outerClassContext: TranslationContext): JsExpression { private fun translateObjectInsideClass(outerClassContext: TranslationContext): JsExpression {
val `fun` = JsFunction(outerClassContext.scope(), JsBlock(), "initializer for " + descriptor.getName().asString()) val function = JsFunction(outerClassContext.scope(), JsBlock(), "initializer for " + descriptor.getName().asString())
val funContext = outerClassContext.newFunctionBodyWithUsageTracker(`fun`, descriptor) val funContext = outerClassContext.newFunctionBodyWithUsageTracker(function, descriptor)
`fun`.getBody().getStatements().add(JsReturn(translate(funContext))) function.getBody().getStatements().add(JsReturn(translate(funContext)))
return `fun`.withCapturedParameters(funContext, outerClassContext, descriptor) return function.withCapturedParameters(funContext, outerClassContext, descriptor)
} }
private fun generatedBridgeMethods(properties: MutableList<JsPropertyInitializer>) { private fun generatedBridgeMethods(properties: MutableList<JsPropertyInitializer>) {
@@ -270,11 +269,12 @@ public class ClassTranslator private (private val classDeclaration: JetClassOrOb
} }
companion object { companion object {
platformStatic
public fun generateClassCreation(classDeclaration: JetClassOrObject, context: TranslationContext): JsInvocation { public fun generateClassCreation(classDeclaration: JetClassOrObject, context: TranslationContext): JsInvocation {
return ClassTranslator(classDeclaration, context).translate() return ClassTranslator(classDeclaration, context).translate()
} }
platformStatic
public fun generateObjectLiteral(objectDeclaration: JetObjectDeclaration, context: TranslationContext): JsExpression { public fun generateObjectLiteral(objectDeclaration: JetObjectDeclaration, context: TranslationContext): JsExpression {
return ClassTranslator(objectDeclaration, context).translateObjectLiteralExpression() return ClassTranslator(objectDeclaration, context).translateObjectLiteralExpression()
} }