JS: support enums in flat JS structure
This commit is contained in:
@@ -28,6 +28,10 @@ class Enum<T : Enum<T>> : Comparable<Enum<T>> {
|
|||||||
|
|
||||||
override fun compareTo(other: Enum<T>) = ordinal.compareTo(other.ordinal)
|
override fun compareTo(other: Enum<T>) = ordinal.compareTo(other.ordinal)
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = this === other
|
||||||
|
|
||||||
|
override fun hashCode(): Int = js("Kotlin.identityHashCode(this)")
|
||||||
|
|
||||||
override fun toString() = name
|
override fun toString() = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+54
-15
@@ -38,6 +38,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.jsAstUtils.toInvocationWith
|
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.toInvocationWith
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||||
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
|
||||||
@@ -55,7 +56,9 @@ import org.jetbrains.kotlin.utils.identity
|
|||||||
*/
|
*/
|
||||||
class ClassTranslator private constructor(
|
class ClassTranslator private constructor(
|
||||||
private val classDeclaration: KtClassOrObject,
|
private val classDeclaration: KtClassOrObject,
|
||||||
context: TranslationContext
|
context: TranslationContext,
|
||||||
|
private val enumInitializerName: JsName?,
|
||||||
|
private val ordinal: Int?
|
||||||
) : AbstractTranslator(context) {
|
) : AbstractTranslator(context) {
|
||||||
|
|
||||||
private val descriptor = getClassDescriptor(context.bindingContext(), classDeclaration)
|
private val descriptor = getClassDescriptor(context.bindingContext(), classDeclaration)
|
||||||
@@ -73,12 +76,13 @@ class ClassTranslator private constructor(
|
|||||||
val context = context().newDeclaration(descriptor)
|
val context = context().newDeclaration(descriptor)
|
||||||
|
|
||||||
val constructorFunction = context.defineTopLevelFunction(descriptor)
|
val constructorFunction = context.defineTopLevelFunction(descriptor)
|
||||||
|
val enumInitFunction = if (descriptor.kind == ClassKind.ENUM_CLASS) createEnumInitFunction() else null
|
||||||
|
|
||||||
val nonConstructorContext = context.innerWithUsageTracker(scope, descriptor)
|
val nonConstructorContext = context.innerWithUsageTracker(scope, descriptor)
|
||||||
nonConstructorContext.startDeclaration()
|
nonConstructorContext.startDeclaration()
|
||||||
val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext)
|
val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext)
|
||||||
translatePropertiesAsConstructorParameters(nonConstructorContext)
|
translatePropertiesAsConstructorParameters(nonConstructorContext)
|
||||||
val bodyVisitor = DeclarationBodyVisitor(descriptor, nonConstructorContext)
|
val bodyVisitor = DeclarationBodyVisitor(descriptor, nonConstructorContext, enumInitFunction)
|
||||||
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
|
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
|
||||||
constructorFunction.body.statements += bodyVisitor.initializerStatements
|
constructorFunction.body.statements += bodyVisitor.initializerStatements
|
||||||
delegationTranslator.generateDelegated()
|
delegationTranslator.generateDelegated()
|
||||||
@@ -104,6 +108,10 @@ class ClassTranslator private constructor(
|
|||||||
if (isObjectLike()) {
|
if (isObjectLike()) {
|
||||||
addObjectMethods()
|
addObjectMethods()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (descriptor.kind == ClassKind.ENUM_CLASS) {
|
||||||
|
generateEnumStandardMethods(bodyVisitor.enumEntries)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translatePrimaryConstructor(
|
private fun translatePrimaryConstructor(
|
||||||
@@ -116,8 +124,13 @@ class ClassTranslator private constructor(
|
|||||||
if (isObjectLike()) {
|
if (isObjectLike()) {
|
||||||
addObjectCache(constructorFunction.body.statements)
|
addObjectCache(constructorFunction.body.statements)
|
||||||
}
|
}
|
||||||
ClassInitializerTranslator(classDeclaration, constructorContext, constructorFunction)
|
ClassInitializerTranslator(classDeclaration, constructorContext, constructorFunction).apply {
|
||||||
.generateInitializeMethod(delegationTranslator)
|
if (ordinal != null) {
|
||||||
|
setOrdinal(ordinal)
|
||||||
|
}
|
||||||
|
generateInitializeMethod(delegationTranslator)
|
||||||
|
}
|
||||||
|
|
||||||
primaryConstructor = ConstructorInfo(constructorFunction, constructorContext, descriptor)
|
primaryConstructor = ConstructorInfo(constructorFunction, constructorContext, descriptor)
|
||||||
|
|
||||||
if (descriptor.kind == ClassKind.ENUM_CLASS) {
|
if (descriptor.kind == ClassKind.ENUM_CLASS) {
|
||||||
@@ -126,10 +139,19 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createEnumInitFunction(): JsFunction {
|
||||||
|
val function = context().createTopLevelAnonymousFunction(descriptor)
|
||||||
|
function.name = context().createGlobalName(StaticContext.getSuggestedName(descriptor) + "_initFields")
|
||||||
|
val emptyFunction = context().createTopLevelAnonymousFunction(descriptor)
|
||||||
|
function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction).makeStmt()
|
||||||
|
context().addDeclarationStatement(function.makeStmt())
|
||||||
|
return function
|
||||||
|
}
|
||||||
|
|
||||||
private fun addEnumClassParameters(constructorFunction: JsFunction) {
|
private fun addEnumClassParameters(constructorFunction: JsFunction) {
|
||||||
val nameParamName = constructorFunction.scope.declareFreshName("name")
|
val nameParamName = constructorFunction.scope.declareFreshName("name")
|
||||||
val ordinalParamName = constructorFunction.scope.declareFreshName("ordinal")
|
val ordinalParamName = constructorFunction.scope.declareFreshName("ordinal")
|
||||||
constructorFunction.parameters += listOf(JsParameter(nameParamName), JsParameter(ordinalParamName))
|
constructorFunction.parameters.addAll(0, listOf(JsParameter(nameParamName), JsParameter(ordinalParamName)))
|
||||||
|
|
||||||
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef())
|
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef())
|
||||||
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_ORDINAL_FIELD, ordinalParamName.makeRef())
|
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_ORDINAL_FIELD, ordinalParamName.makeRef())
|
||||||
@@ -200,6 +222,12 @@ class ClassTranslator private constructor(
|
|||||||
// Add parameter for outer instance
|
// Add parameter for outer instance
|
||||||
val leadingArgs = mutableListOf<JsExpression>()
|
val leadingArgs = mutableListOf<JsExpression>()
|
||||||
|
|
||||||
|
if (descriptor.kind == ClassKind.ENUM_CLASS) {
|
||||||
|
val nameParamName = constructorInitializer.scope.declareFreshName("name")
|
||||||
|
val ordinalParamName = constructorInitializer.scope.declareFreshName("ordinal")
|
||||||
|
constructorInitializer.parameters.addAll(0, listOf(JsParameter(nameParamName), JsParameter(ordinalParamName)))
|
||||||
|
leadingArgs += listOf(nameParamName.makeRef(), ordinalParamName.makeRef())
|
||||||
|
}
|
||||||
if (outerClassName != null) {
|
if (outerClassName != null) {
|
||||||
constructorInitializer.parameters.add(0, JsParameter(outerClassName))
|
constructorInitializer.parameters.add(0, JsParameter(outerClassName))
|
||||||
leadingArgs += outerClassName.makeRef()
|
leadingArgs += outerClassName.makeRef()
|
||||||
@@ -242,9 +270,7 @@ class ClassTranslator private constructor(
|
|||||||
|
|
||||||
secondaryConstructors += ConstructorInfo(constructorInitializer, context, constructorDescriptor, compositeSuperCallGenerator)
|
secondaryConstructors += ConstructorInfo(constructorInitializer, context, constructorDescriptor, compositeSuperCallGenerator)
|
||||||
|
|
||||||
if (DescriptorUtils.isTopLevelDeclaration(classDescriptor)) {
|
context.export(constructorDescriptor)
|
||||||
context.export(constructorDescriptor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val allConstructors: Sequence<ConstructorInfo>
|
private val allConstructors: Sequence<ConstructorInfo>
|
||||||
@@ -387,19 +413,28 @@ class ClassTranslator private constructor(
|
|||||||
val instanceFun = JsFunction(context().rootFunction.scope, JsBlock(), "Instance function: " + descriptor)
|
val instanceFun = JsFunction(context().rootFunction.scope, JsBlock(), "Instance function: " + descriptor)
|
||||||
instanceFun.name = context().getNameForObjectInstance(descriptor)
|
instanceFun.name = context().getNameForObjectInstance(descriptor)
|
||||||
|
|
||||||
val instanceCreatedCondition = JsAstUtils.equality(cachedInstanceName.makeRef(), JsLiteral.NULL)
|
if (enumInitializerName == null) {
|
||||||
val instanceCreationBlock = JsBlock()
|
val instanceCreatedCondition = JsAstUtils.equality(cachedInstanceName.makeRef(), JsLiteral.NULL)
|
||||||
val instanceCreatedGuard = JsIf(instanceCreatedCondition, instanceCreationBlock)
|
val instanceCreationBlock = JsBlock()
|
||||||
instanceFun.body.statements += instanceCreatedGuard
|
val instanceCreatedGuard = JsIf(instanceCreatedCondition, instanceCreationBlock)
|
||||||
|
instanceFun.body.statements += instanceCreatedGuard
|
||||||
|
|
||||||
val objectRef = context().getInnerReference(descriptor)
|
val objectRef = context().getInnerReference(descriptor)
|
||||||
instanceCreationBlock.statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsNew(objectRef)).makeStmt()
|
instanceCreationBlock.statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsNew(objectRef)).makeStmt()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
instanceFun.body.statements += JsInvocation(pureFqn(enumInitializerName, null)).makeStmt()
|
||||||
|
}
|
||||||
|
|
||||||
instanceFun.body.statements += JsReturn(cachedInstanceName.makeRef())
|
instanceFun.body.statements += JsReturn(cachedInstanceName.makeRef())
|
||||||
|
|
||||||
context().addDeclarationStatement(instanceFun.makeStmt())
|
context().addDeclarationStatement(instanceFun.makeStmt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateEnumStandardMethods(entries: List<ClassDescriptor>) {
|
||||||
|
EnumTranslator(context(), descriptor, entries).generateStandardMethods()
|
||||||
|
}
|
||||||
|
|
||||||
private fun generatedBridgeMethods() {
|
private fun generatedBridgeMethods() {
|
||||||
if (isAnnotation()) return
|
if (isAnnotation()) return
|
||||||
|
|
||||||
@@ -450,7 +485,11 @@ class ClassTranslator private constructor(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic fun translate(classDeclaration: KtClassOrObject, context: TranslationContext) {
|
@JvmStatic fun translate(classDeclaration: KtClassOrObject, context: TranslationContext) {
|
||||||
return ClassTranslator(classDeclaration, context).translate()
|
return ClassTranslator(classDeclaration, context, null, null).translate()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic fun translate(classDeclaration: KtEnumEntry, context: TranslationContext, enumInitializerName: JsName, ordinal: Int) {
|
||||||
|
return ClassTranslator(classDeclaration, context, enumInitializerName, ordinal).translate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun addInterfaceDefaultMembers(descriptor: ClassDescriptor, context: StaticContext) {
|
@JvmStatic fun addInterfaceDefaultMembers(descriptor: ClassDescriptor, context: StaticContext) {
|
||||||
|
|||||||
+13
-8
@@ -25,16 +25,19 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
|||||||
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator
|
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.utils.*
|
import org.jetbrains.kotlin.js.translate.utils.*
|
||||||
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.JsAstUtils.pureFqn
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class DeclarationBodyVisitor(
|
class DeclarationBodyVisitor(
|
||||||
private val containingClass: ClassDescriptor,
|
private val containingClass: ClassDescriptor,
|
||||||
private val context: TranslationContext
|
private val context: TranslationContext,
|
||||||
|
private val enumInitializer: JsFunction?
|
||||||
) : AbstractDeclarationVisitor() {
|
) : AbstractDeclarationVisitor() {
|
||||||
private var enumEntryOrdinal: Int = 0
|
private var enumEntryOrdinal: Int = 0
|
||||||
val initializerStatements = ArrayList<JsStatement>()
|
val initializerStatements = mutableListOf<JsStatement>()
|
||||||
|
val enumEntries = mutableListOf<ClassDescriptor>()
|
||||||
|
|
||||||
override fun visitClassOrObject(classOrObject: KtClassOrObject, context: TranslationContext) {
|
override fun visitClassOrObject(classOrObject: KtClassOrObject, context: TranslationContext) {
|
||||||
super.visitClassOrObject(classOrObject, context)
|
super.visitClassOrObject(classOrObject, context)
|
||||||
@@ -48,29 +51,31 @@ class DeclarationBodyVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEnumEntry(enumEntry: KtEnumEntry, context: TranslationContext) {
|
override fun visitEnumEntry(enumEntry: KtEnumEntry, context: TranslationContext) {
|
||||||
|
val enumInitializer = this.enumInitializer!!
|
||||||
val descriptor = getClassDescriptor(context.bindingContext(), enumEntry)
|
val descriptor = getClassDescriptor(context.bindingContext(), enumEntry)
|
||||||
val supertypes = getSupertypesWithoutFakes(descriptor)
|
val supertypes = getSupertypesWithoutFakes(descriptor)
|
||||||
|
enumEntries += descriptor
|
||||||
|
|
||||||
if (enumEntry.getBody() != null || supertypes.size > 1) {
|
if (enumEntry.getBody() != null || supertypes.size > 1) {
|
||||||
ClassTranslator.translate(enumEntry, context)
|
ClassTranslator.translate(enumEntry, context, enumInitializer.name, enumEntryOrdinal)
|
||||||
|
enumInitializer.body.statements += JsNew(context.getInnerReference(descriptor)).makeStmt()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Simplify by omitting _getInstance() function
|
|
||||||
val enumName = context.getInnerNameForDescriptor(descriptor)
|
val enumName = context.getInnerNameForDescriptor(descriptor)
|
||||||
val enumInstanceName = context.createGlobalName(enumName.ident + "_instance")
|
val enumInstanceName = context.createGlobalName(enumName.ident + "_instance")
|
||||||
|
|
||||||
assert(supertypes.size == 1) { "Simple Enum entry must have one supertype" }
|
assert(supertypes.size == 1) { "Simple Enum entry must have one supertype" }
|
||||||
val jsEnumEntryCreation = ClassInitializerTranslator
|
val jsEnumEntryCreation = ClassInitializerTranslator
|
||||||
.generateEnumEntryInstanceCreation(context, supertypes[0], enumEntry, enumEntryOrdinal)
|
.generateEnumEntryInstanceCreation(context, supertypes[0], enumEntry, enumEntryOrdinal)
|
||||||
context.addDeclarationStatement(JsAstUtils.newVar(enumInstanceName, jsEnumEntryCreation))
|
context.addDeclarationStatement(JsAstUtils.newVar(enumInstanceName, null))
|
||||||
val jsEnumEntryFunction = context.createTopLevelAnonymousFunction(descriptor)
|
enumInitializer.body.statements += JsAstUtils.assignment(pureFqn(enumInstanceName, null), jsEnumEntryCreation).makeStmt()
|
||||||
jsEnumEntryFunction.body.statements.add(JsReturn(jsEnumEntryCreation))
|
|
||||||
|
|
||||||
val enumInstanceFunction = context.createTopLevelAnonymousFunction(descriptor)
|
val enumInstanceFunction = context.createTopLevelAnonymousFunction(descriptor)
|
||||||
enumInstanceFunction.name = context.getNameForObjectInstance(descriptor)
|
enumInstanceFunction.name = context.getNameForObjectInstance(descriptor)
|
||||||
context.addDeclarationStatement(enumInstanceFunction.makeStmt())
|
context.addDeclarationStatement(enumInstanceFunction.makeStmt())
|
||||||
|
|
||||||
enumInstanceFunction.body.statements.add(JsReturn(enumInstanceName.makeRef()))
|
enumInstanceFunction.body.statements += JsInvocation(pureFqn(enumInitializer.name, null)).makeStmt()
|
||||||
|
enumInstanceFunction.body.statements += JsReturn(enumInstanceName.makeRef())
|
||||||
}
|
}
|
||||||
|
|
||||||
enumEntryOrdinal++
|
enumEntryOrdinal++
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.translate.declaration
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
|
||||||
|
class EnumTranslator(
|
||||||
|
context: TranslationContext,
|
||||||
|
val descriptor: ClassDescriptor,
|
||||||
|
val entries: List<ClassDescriptor>
|
||||||
|
) : AbstractTranslator(context) {
|
||||||
|
fun generateStandardMethods() {
|
||||||
|
generateValuesFunction()
|
||||||
|
generateValueOfFunction()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateValuesFunction() {
|
||||||
|
val function = createFunction(getEnumFunction(DescriptorUtils.ENUM_VALUES))
|
||||||
|
|
||||||
|
val values = entries.map { JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(it), null)) }
|
||||||
|
function.body.statements += JsReturn(JsArrayLiteral(values))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateValueOfFunction() {
|
||||||
|
val function = createFunction(getEnumFunction(DescriptorUtils.ENUM_VALUE_OF))
|
||||||
|
|
||||||
|
val nameParam = function.scope.declareFreshName("name")
|
||||||
|
function.parameters += JsParameter(nameParam)
|
||||||
|
|
||||||
|
val clauses = entries.map { entry ->
|
||||||
|
JsCase().apply {
|
||||||
|
caseExpression = context().program().getStringLiteral(entry.name.asString())
|
||||||
|
statements += JsReturn(JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(entry), null)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clauses.isNotEmpty()) {
|
||||||
|
function.body.statements += JsSwitch(nameParam.makeRef(), clauses)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createFunction(functionDescriptor: FunctionDescriptor): JsFunction {
|
||||||
|
val function = context().getFunctionObject(functionDescriptor)
|
||||||
|
function.name = context().getInnerNameForDescriptor(functionDescriptor)
|
||||||
|
context().addDeclarationStatement(function.makeStmt())
|
||||||
|
|
||||||
|
val classRef = context().getInnerReference(descriptor)
|
||||||
|
val functionRef = function.name.makeRef()
|
||||||
|
val assignment = JsAstUtils.assignment(JsNameRef(context().getNameForDescriptor(functionDescriptor), classRef), functionRef)
|
||||||
|
context().addDeclarationStatement(assignment.makeStmt())
|
||||||
|
|
||||||
|
return function
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getEnumFunction(name: Name): FunctionDescriptor {
|
||||||
|
val functions = descriptor.staticScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||||
|
return functions
|
||||||
|
.mapNotNull { (it as? FunctionDescriptor)?.original }
|
||||||
|
.first { it.name == name }
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-7
@@ -64,6 +64,8 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final ClassDescriptor classDescriptor;
|
private final ClassDescriptor classDescriptor;
|
||||||
|
|
||||||
|
private int ordinal;
|
||||||
|
|
||||||
public ClassInitializerTranslator(
|
public ClassInitializerTranslator(
|
||||||
@NotNull KtClassOrObject classDeclaration,
|
@NotNull KtClassOrObject classDeclaration,
|
||||||
@NotNull TranslationContext context,
|
@NotNull TranslationContext context,
|
||||||
@@ -78,6 +80,10 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
fillInitFunction(classDeclaration, context);
|
fillInitFunction(classDeclaration, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOrdinal(int ordinal) {
|
||||||
|
this.ordinal = ordinal;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected TranslationContext context() {
|
protected TranslationContext context() {
|
||||||
@@ -153,15 +159,27 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
) {
|
) {
|
||||||
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(context.bindingContext(), classDeclaration);
|
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(context.bindingContext(), classDeclaration);
|
||||||
|
|
||||||
|
JsExpression nameArg = context.program().getStringLiteral(classDeclaration.getName());
|
||||||
|
JsExpression ordinalArg = context.program().getNumberLiteral(ordinal);
|
||||||
|
List<JsExpression> additionalArgs = Arrays.asList(nameArg, ordinalArg);
|
||||||
|
|
||||||
if (superCall == null) {
|
if (superCall == null) {
|
||||||
ClassDescriptor classDescriptor = getClassDescriptorForType(enumClassType);
|
ClassDescriptor classDescriptor = getClassDescriptorForType(enumClassType);
|
||||||
JsNameRef reference = context.getInnerReference(classDescriptor);
|
JsNameRef reference = context.getInnerReference(classDescriptor);
|
||||||
JsExpression nameArg = context.program().getStringLiteral(classDeclaration.getName());
|
return new JsNew(reference, additionalArgs);
|
||||||
JsExpression ordinalArg = context.program().getNumberLiteral(ordinal);
|
|
||||||
return new JsNew(reference, Arrays.asList(nameArg, ordinalArg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CallTranslator.translate(context, superCall);
|
JsExpression call = CallTranslator.translate(context, superCall);
|
||||||
|
if (call instanceof JsInvocation) {
|
||||||
|
JsInvocation invocation = (JsInvocation) call;
|
||||||
|
invocation.getArguments().addAll(0, additionalArgs);
|
||||||
|
}
|
||||||
|
else if (call instanceof JsNew) {
|
||||||
|
JsNew invocation = (JsNew) call;
|
||||||
|
invocation.getArguments().addAll(0, additionalArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mayBeAddCallToSuperMethod(JsFunction initializer) {
|
private void mayBeAddCallToSuperMethod(JsFunction initializer) {
|
||||||
@@ -172,15 +190,16 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
|
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
|
||||||
if (superCall == null) {
|
if (superCall == null) {
|
||||||
if (DescriptorUtils.isEnumEntry(classDescriptor)) {
|
if (DescriptorUtils.isEnumEntry(classDescriptor)) {
|
||||||
addCallToSuperMethod(Collections.<JsExpression>emptyList(), initializer);
|
addCallToSuperMethod(getAdditionalArgumentsForEnumConstructor(), initializer);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classDeclaration instanceof KtEnumEntry) {
|
if (classDeclaration instanceof KtEnumEntry) {
|
||||||
JsExpression expression = CallTranslator.translate(context(), superCall, null);
|
JsExpression expression = CallTranslator.translate(context(), superCall, null);
|
||||||
JsExpression fixedInvocation = AstUtilsKt.toInvocationWith(expression, Collections.<JsExpression>emptyList(), 0,
|
|
||||||
JsLiteral.THIS);
|
JsExpression fixedInvocation = AstUtilsKt.toInvocationWith(
|
||||||
|
expression, getAdditionalArgumentsForEnumConstructor(), 0, JsLiteral.THIS);
|
||||||
initFunction.getBody().getStatements().add(fixedInvocation.makeStmt());
|
initFunction.getBody().getStatements().add(fixedInvocation.makeStmt());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -235,6 +254,14 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private List<JsExpression> getAdditionalArgumentsForEnumConstructor() {
|
||||||
|
List<JsExpression> additionalArguments = new ArrayList<JsExpression>();
|
||||||
|
additionalArguments.add(program().getStringLiteral(classDescriptor.getName().asString()));
|
||||||
|
additionalArguments.add(program().getNumberLiteral(ordinal));
|
||||||
|
return additionalArguments;
|
||||||
|
}
|
||||||
|
|
||||||
private void addCallToSuperMethod(@NotNull List<JsExpression> arguments, @NotNull JsFunction initializer) {
|
private void addCallToSuperMethod(@NotNull List<JsExpression> arguments, @NotNull JsFunction initializer) {
|
||||||
if (initializer.getName() == null) {
|
if (initializer.getName() == null) {
|
||||||
JsName ref = context().scope().declareName(Namer.CALLEE_NAME);
|
JsName ref = context().scope().declareName(Namer.CALLEE_NAME);
|
||||||
|
|||||||
@@ -56,7 +56,11 @@ fun JsNode.any(predicate: (JsNode) -> Boolean): Boolean {
|
|||||||
return visitor.matched
|
return visitor.matched
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsExpression.toInvocationWith(leadingExtraArgs: List<JsExpression>, parameterCount: Int, thisExpr: JsExpression): JsExpression {
|
fun JsExpression.toInvocationWith(
|
||||||
|
leadingExtraArgs: List<JsExpression>,
|
||||||
|
parameterCount: Int,
|
||||||
|
thisExpr: JsExpression
|
||||||
|
): JsExpression {
|
||||||
val qualifier: JsExpression
|
val qualifier: JsExpression
|
||||||
fun padArguments(arguments: List<JsExpression>) = arguments + (1..(parameterCount - arguments.size))
|
fun padArguments(arguments: List<JsExpression>) = arguments + (1..(parameterCount - arguments.size))
|
||||||
.map { Namer.getUndefinedExpression() }
|
.map { Namer.getUndefinedExpression() }
|
||||||
|
|||||||
+4
-2
@@ -143,11 +143,11 @@
|
|||||||
return type === "string" ||
|
return type === "string" ||
|
||||||
type === "boolean" ||
|
type === "boolean" ||
|
||||||
Kotlin.isNumber(value) ||
|
Kotlin.isNumber(value) ||
|
||||||
Kotlin.isType(value, Kotlin.Comparable);
|
Kotlin.isType(value, Kotlin.kotlin.Comparable);
|
||||||
};
|
};
|
||||||
|
|
||||||
Kotlin.isCharSequence = function (value) {
|
Kotlin.isCharSequence = function (value) {
|
||||||
return typeof value === "string" || Kotlin.isType(value, CharSequence);
|
return typeof value === "string" || Kotlin.isType(value, Kotlin.kotlin.CharSequence);
|
||||||
};
|
};
|
||||||
|
|
||||||
Kotlin.charInc = function (value) {
|
Kotlin.charInc = function (value) {
|
||||||
@@ -497,5 +497,7 @@
|
|||||||
}
|
}
|
||||||
return obj1;
|
return obj1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Kotlin.identityHashCode = getObjectHashCode;
|
||||||
})(Kotlin);
|
})(Kotlin);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user