All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.js.translate.declaration.EnumTranslator.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2017 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.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.translate.context.Namer
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.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe

class EnumTranslator(
        context: TranslationContext,
        val descriptor: ClassDescriptor,
        val entries: List,
        private val psi: PsiElement
) : AbstractTranslator(context) {
    fun generateStandardMethods() {
        generateValuesFunction()
        generateValueOfFunction()
    }

    private fun generateValuesFunction() {
        val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, StandardNames.ENUM_VALUES))

        val values = entries.map {
            JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(it), null)).source(psi)
        }
        function.body.statements += JsReturn(JsArrayLiteral(values).source(psi)).apply { source = psi }
    }

    private fun generateValueOfFunction() {
        val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, StandardNames.ENUM_VALUE_OF))

        val nameParam = JsScope.declareTemporaryName("name")
        function.parameters += JsParameter(nameParam)

        val clauses = entries.map { entry ->
            JsCase().apply {
                caseExpression = JsStringLiteral(entry.name.asString()).source(psi)
                statements += JsReturn(JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(entry), null)).source(psi))
                        .apply { source = psi }
                source = psi
            }
        }

        val message = JsBinaryOperation(JsBinaryOperator.ADD,
                                        JsStringLiteral("No enum constant ${descriptor.fqNameSafe}."),
                                        nameParam.makeRef())
        val throwFunction = context().getReferenceToIntrinsic(Namer.THROW_ILLEGAL_STATE_EXCEPTION_FUN_NAME)
        val throwStatement = JsExpressionStatement(JsInvocation(throwFunction, message).source(psi))

        if (clauses.isNotEmpty()) {
            val defaultCase = JsDefault().apply {
                statements += throwStatement
                source = psi
            }
            function.body.statements += JsSwitch(nameParam.makeRef().source(psi), clauses + defaultCase).apply { source = psi }
        }
        else {
            function.body.statements += throwStatement
        }
    }

    private fun createFunction(functionDescriptor: FunctionDescriptor): JsFunction {
        val function = context().getFunctionObject(functionDescriptor)
        function.name = context().getInnerNameForDescriptor(functionDescriptor)
        function.source = psi
        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
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy