Fix generation of source maps for synthetic code in enums in JS BE

This commit is contained in:
Alexey Andreev
2017-05-04 16:46:49 +03:00
parent fb3a864892
commit 3a7df13440
6 changed files with 44 additions and 18 deletions
@@ -71,4 +71,10 @@ public class JsLineNumberTestGenerated extends AbstractJsLineNumberTest {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt"); String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt");
doTest(fileName); doTest(fileName);
} }
@TestMetadata("syntheticCodeInEnums.kt")
public void testSyntheticCodeInEnums() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/lineNumbers/syntheticCodeInEnums.kt");
doTest(fileName);
}
} }
@@ -473,7 +473,7 @@ class ClassTranslator private constructor(
} }
private fun generateEnumStandardMethods(entries: List<ClassDescriptor>) { private fun generateEnumStandardMethods(entries: List<ClassDescriptor>) {
EnumTranslator(context(), descriptor, entries).generateStandardMethods() EnumTranslator(context(), descriptor, entries, classDeclaration).generateStandardMethods()
} }
private fun mayBeAddThrowableProperties(context: TranslationContext) { private fun mayBeAddThrowableProperties(context: TranslationContext) {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * Copyright 2010-2017 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -49,7 +49,8 @@ class DeclarationBodyVisitor(
if (classOrObject is KtObjectDeclaration) { if (classOrObject is KtObjectDeclaration) {
if (classOrObject.isCompanion() && containingClass.kind != ClassKind.ENUM_CLASS) { if (classOrObject.isCompanion() && containingClass.kind != ClassKind.ENUM_CLASS) {
val descriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), classOrObject) as ClassDescriptor val descriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), classOrObject) as ClassDescriptor
addInitializerStatement(JsInvocation(context.getNameForObjectInstance(descriptor).makeRef()).makeStmt()) addInitializerStatement(JsInvocation(context.getNameForObjectInstance(descriptor).makeRef())
.source(classOrObject).makeStmt())
} }
} }
} }
@@ -62,7 +63,7 @@ class DeclarationBodyVisitor(
if (enumEntry.getBody() != null || supertypes.size > 1) { if (enumEntry.getBody() != null || supertypes.size > 1) {
ClassTranslator.translate(enumEntry, context, enumInitializer.name, enumEntryOrdinal) ClassTranslator.translate(enumEntry, context, enumInitializer.name, enumEntryOrdinal)
enumInitializer.body.statements += JsNew(context.getInnerReference(descriptor)).makeStmt() enumInitializer.body.statements += JsNew(context.getInnerReference(descriptor)).source(enumEntry).makeStmt()
} }
else { else {
val enumName = context.getInnerNameForDescriptor(descriptor) val enumName = context.getInnerNameForDescriptor(descriptor)
@@ -77,8 +78,8 @@ class DeclarationBodyVisitor(
enumInstanceFunction.name = context.getNameForObjectInstance(descriptor) enumInstanceFunction.name = context.getNameForObjectInstance(descriptor)
context.addDeclarationStatement(enumInstanceFunction.makeStmt()) context.addDeclarationStatement(enumInstanceFunction.makeStmt())
enumInstanceFunction.body.statements += JsInvocation(pureFqn(enumInitializer.name, null)).makeStmt() enumInstanceFunction.body.statements += JsInvocation(pureFqn(enumInitializer.name, null)).source(enumEntry).makeStmt()
enumInstanceFunction.body.statements += JsReturn(enumInstanceName.makeRef()) enumInstanceFunction.body.statements += JsReturn(enumInstanceName.makeRef().source(enumEntry))
} }
context.export(descriptor) context.export(descriptor)
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * Copyright 2010-2017 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.js.translate.declaration package org.jetbrains.kotlin.js.translate.declaration
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
@@ -29,7 +30,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
class EnumTranslator( class EnumTranslator(
context: TranslationContext, context: TranslationContext,
val descriptor: ClassDescriptor, val descriptor: ClassDescriptor,
val entries: List<ClassDescriptor> val entries: List<ClassDescriptor>,
private val psi: PsiElement
) : AbstractTranslator(context) { ) : AbstractTranslator(context) {
fun generateStandardMethods() { fun generateStandardMethods() {
generateValuesFunction() generateValuesFunction()
@@ -39,7 +41,9 @@ class EnumTranslator(
private fun generateValuesFunction() { private fun generateValuesFunction() {
val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, DescriptorUtils.ENUM_VALUES)) val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, DescriptorUtils.ENUM_VALUES))
val values = entries.map { JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(it), null)) } val values = entries.map {
JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(it), null)).source(psi)
}
function.body.statements += JsReturn(JsArrayLiteral(values)) function.body.statements += JsReturn(JsArrayLiteral(values))
} }
@@ -52,18 +56,19 @@ class EnumTranslator(
val clauses = entries.map { entry -> val clauses = entries.map { entry ->
JsCase().apply { JsCase().apply {
caseExpression = context().program().getStringLiteral(entry.name.asString()) caseExpression = context().program().getStringLiteral(entry.name.asString())
statements += JsReturn(JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(entry), null))) statements += JsReturn(JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(entry), null)).source(psi))
source = psi
} }
} }
val message = JsBinaryOperation(JsBinaryOperator.ADD, val message = JsBinaryOperation(JsBinaryOperator.ADD,
context().program().getStringLiteral("No enum constant ${descriptor.fqNameSafe}."), context().program().getStringLiteral("No enum constant ${descriptor.fqNameSafe}."),
nameParam.makeRef()) nameParam.makeRef())
val throwStatement = JsExpressionStatement(JsInvocation(Namer.throwIllegalStateExceptionFunRef(), message)) val throwStatement = JsExpressionStatement(JsInvocation(Namer.throwIllegalStateExceptionFunRef(), message).source(psi))
if (clauses.isNotEmpty()) { if (clauses.isNotEmpty()) {
val defaultCase = JsDefault().apply { statements += throwStatement } val defaultCase = JsDefault().apply { statements += throwStatement }
function.body.statements += JsSwitch(nameParam.makeRef(), clauses + defaultCase) function.body.statements += JsSwitch(nameParam.makeRef().source(psi), clauses + defaultCase)
} }
else { else {
function.body.statements += throwStatement function.body.statements += throwStatement
@@ -49,7 +49,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import java.util.ArrayList; import java.util.ArrayList;
@@ -113,7 +112,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
// Initialize enum 'name' and 'ordinal' before translating property initializers. // Initialize enum 'name' and 'ordinal' before translating property initializers.
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) { if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
addEnumClassParameters(initFunction); addEnumClassParameters(initFunction, classDeclaration);
} }
} }
@@ -123,13 +122,17 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
new InitializerVisitor().traverseContainer(classDeclaration, context().innerBlock(initFunction.getBody())); new InitializerVisitor().traverseContainer(classDeclaration, context().innerBlock(initFunction.getBody()));
} }
private static void addEnumClassParameters(JsFunction constructorFunction) { private static void addEnumClassParameters(JsFunction constructorFunction, PsiElement psiElement) {
JsName nameParamName = constructorFunction.getScope().declareFreshName("name"); JsName nameParamName = constructorFunction.getScope().declareFreshName("name");
JsName ordinalParamName = constructorFunction.getScope().declareFreshName("ordinal"); JsName ordinalParamName = constructorFunction.getScope().declareFreshName("ordinal");
constructorFunction.getParameters().addAll(0, Arrays.asList(new JsParameter(nameParamName), new JsParameter(ordinalParamName))); constructorFunction.getParameters().addAll(0, Arrays.asList(new JsParameter(nameParamName), new JsParameter(ordinalParamName)));
constructorFunction.getBody().getStatements().add(JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef())); JsStatement nameAssignment = JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef().source(psiElement));
constructorFunction.getBody().getStatements().add(JsAstUtils.assignmentToThisField(Namer.ENUM_ORDINAL_FIELD, ordinalParamName.makeRef())); constructorFunction.getBody().getStatements().add(nameAssignment);
JsStatement ordinalAssignment = JsAstUtils.assignmentToThisField(
Namer.ENUM_ORDINAL_FIELD, ordinalParamName.makeRef().source(psiElement));
constructorFunction.getBody().getStatements().add(ordinalAssignment);
} }
private void addOuterClassReference(ClassDescriptor classDescriptor) { private void addOuterClassReference(ClassDescriptor classDescriptor) {
@@ -170,7 +173,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
invocation.getArguments().addAll(0, additionalArgs); invocation.getArguments().addAll(0, additionalArgs);
} }
return call; return call.source(enumEntry);
} }
private void mayBeAddCallToSuperMethod(JsFunction initializer) { private void mayBeAddCallToSuperMethod(JsFunction initializer) {
@@ -0,0 +1,11 @@
enum class E {
X,
Y,
Z {
init {
println("Z")
}
}
}
// LINES: 1 1 1 1 2 3 4 * 2 2 * 3 3 4 4 6 * 1 * 1 1 1 1 1 1