diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsLineNumberTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsLineNumberTestGenerated.java index b9405fd44fe..354717dd9ec 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsLineNumberTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsLineNumberTestGenerated.java @@ -71,4 +71,10 @@ public class JsLineNumberTestGenerated extends AbstractJsLineNumberTest { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt"); doTest(fileName); } + + @TestMetadata("syntheticCodeInEnums.kt") + public void testSyntheticCodeInEnums() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/lineNumbers/syntheticCodeInEnums.kt"); + doTest(fileName); + } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt index c55404cbb81..6587dfaccb9 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt @@ -473,7 +473,7 @@ class ClassTranslator private constructor( } private fun generateEnumStandardMethods(entries: List) { - EnumTranslator(context(), descriptor, entries).generateStandardMethods() + EnumTranslator(context(), descriptor, entries, classDeclaration).generateStandardMethods() } private fun mayBeAddThrowableProperties(context: TranslationContext) { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.kt index 368c5212848..aaae8707102 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DeclarationBodyVisitor.kt @@ -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"); * you may not use this file except in compliance with the License. @@ -49,7 +49,8 @@ class DeclarationBodyVisitor( if (classOrObject is KtObjectDeclaration) { if (classOrObject.isCompanion() && containingClass.kind != ClassKind.ENUM_CLASS) { 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) { 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 { val enumName = context.getInnerNameForDescriptor(descriptor) @@ -77,8 +78,8 @@ class DeclarationBodyVisitor( enumInstanceFunction.name = context.getNameForObjectInstance(descriptor) context.addDeclarationStatement(enumInstanceFunction.makeStmt()) - enumInstanceFunction.body.statements += JsInvocation(pureFqn(enumInitializer.name, null)).makeStmt() - enumInstanceFunction.body.statements += JsReturn(enumInstanceName.makeRef()) + enumInstanceFunction.body.statements += JsInvocation(pureFqn(enumInitializer.name, null)).source(enumEntry).makeStmt() + enumInstanceFunction.body.statements += JsReturn(enumInstanceName.makeRef().source(enumEntry)) } context.export(descriptor) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/EnumTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/EnumTranslator.kt index f744e936190..0d107528a98 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/EnumTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/EnumTranslator.kt @@ -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"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.js.translate.declaration +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.js.backend.ast.* @@ -29,7 +30,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe class EnumTranslator( context: TranslationContext, val descriptor: ClassDescriptor, - val entries: List + val entries: List, + private val psi: PsiElement ) : AbstractTranslator(context) { fun generateStandardMethods() { generateValuesFunction() @@ -39,7 +41,9 @@ class EnumTranslator( private fun generateValuesFunction() { 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)) } @@ -52,18 +56,19 @@ class EnumTranslator( val clauses = entries.map { entry -> JsCase().apply { 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, context().program().getStringLiteral("No enum constant ${descriptor.fqNameSafe}."), nameParam.makeRef()) - val throwStatement = JsExpressionStatement(JsInvocation(Namer.throwIllegalStateExceptionFunRef(), message)) + val throwStatement = JsExpressionStatement(JsInvocation(Namer.throwIllegalStateExceptionFunRef(), message).source(psi)) if (clauses.isNotEmpty()) { 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 { function.body.statements += throwStatement diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java index 033185e0cb9..5d6d789f7ac 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java @@ -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.ResolvedValueArgument; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; -import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import java.util.ArrayList; @@ -113,7 +112,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { // Initialize enum 'name' and 'ordinal' before translating property initializers. 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())); } - private static void addEnumClassParameters(JsFunction constructorFunction) { + private static void addEnumClassParameters(JsFunction constructorFunction, PsiElement psiElement) { JsName nameParamName = constructorFunction.getScope().declareFreshName("name"); JsName ordinalParamName = constructorFunction.getScope().declareFreshName("ordinal"); constructorFunction.getParameters().addAll(0, Arrays.asList(new JsParameter(nameParamName), new JsParameter(ordinalParamName))); - constructorFunction.getBody().getStatements().add(JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef())); - constructorFunction.getBody().getStatements().add(JsAstUtils.assignmentToThisField(Namer.ENUM_ORDINAL_FIELD, ordinalParamName.makeRef())); + JsStatement nameAssignment = JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef().source(psiElement)); + 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) { @@ -170,7 +173,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { invocation.getArguments().addAll(0, additionalArgs); } - return call; + return call.source(enumEntry); } private void mayBeAddCallToSuperMethod(JsFunction initializer) { diff --git a/js/js.translator/testData/lineNumbers/syntheticCodeInEnums.kt b/js/js.translator/testData/lineNumbers/syntheticCodeInEnums.kt new file mode 100644 index 00000000000..1ae602e011e --- /dev/null +++ b/js/js.translator/testData/lineNumbers/syntheticCodeInEnums.kt @@ -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 \ No newline at end of file