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 c42eff26d15..b9405fd44fe 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 @@ -65,4 +65,10 @@ public class JsLineNumberTestGenerated extends AbstractJsLineNumberTest { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/lineNumbers/simple.kt"); doTest(fileName); } + + @TestMetadata("syntheticCodeInConstructors.kt") + public void testSyntheticCodeInConstructors() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt"); + doTest(fileName); + } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/AliasingContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/AliasingContext.java index f8f20d740c2..856070480f0 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/AliasingContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/AliasingContext.java @@ -74,12 +74,14 @@ public class AliasingContext { public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) { // these aliases cannot be shared and applicable only in current context JsExpression alias = aliasesForDescriptors != null ? aliasesForDescriptors.get(descriptor.getOriginal()) : null; - return alias != null || parent == null ? alias : parent.getAliasForDescriptor(descriptor); + JsExpression result = alias != null || parent == null ? alias : parent.getAliasForDescriptor(descriptor); + return result != null ? result.deepCopy() : null; } @Nullable public JsExpression getAliasForExpression(@NotNull KtExpression element) { JsExpression alias = aliasesForExpressions != null ? aliasesForExpressions.get(element) : null; - return alias != null || parent == null ? alias : parent.getAliasForExpression(element); + JsExpression result = alias != null || parent == null ? alias : parent.getAliasForExpression(element); + return result != null ? result.deepCopy() : null; } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java index af8687521dc..bd61824588d 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 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. @@ -66,6 +66,9 @@ public final class DynamicContext { JsVar var = new JsVar(temporaryName, null); MetadataProperties.setSynthetic(var, true); vars.add(var); + if (initExpression != null) { + var.source(initExpression.getSource()); + } return TemporaryVariable.create(temporaryName, initExpression); } 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 66060d045dd..c55404cbb81 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 @@ -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. @@ -158,7 +158,8 @@ class ClassTranslator private constructor( val function = context().createRootScopedFunction(descriptor) function.name = JsScope.declareTemporaryName(StaticContext.getSuggestedName(descriptor) + "_initFields") val emptyFunction = context().createRootScopedFunction(descriptor) - function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction).makeStmt() + function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction) + .source(classDeclaration).makeStmt() context().addDeclarationStatement(function.makeStmt()) return function } @@ -229,7 +230,8 @@ class ClassTranslator private constructor( superCallGenerators += { it += FunctionBodyTranslator.setDefaultValueForArguments(constructorDescriptor, context) } val createInstance = Namer.createObjectWithPrototypeFrom(referenceToClass) - val instanceVar = JsAstUtils.assignment(thisNameRef, JsAstUtils.or(thisNameRef, createInstance)).makeStmt() + val instanceVar = JsAstUtils.assignment(thisNameRef.deepCopy(), JsAstUtils.or(thisNameRef.deepCopy(), createInstance)) + .source(constructor).makeStmt() superCallGenerators += { it += instanceVar } // Add parameter for outer instance @@ -265,8 +267,10 @@ class ClassTranslator private constructor( superCallGenerators += { val delegationConstructor = resolvedCall.resultingDescriptor val innerContext = context.innerBlock() - val statement = CallTranslator.translate(innerContext, resolvedCall) - .toInvocationWith(leadingArgs, delegationConstructor.valueParameters.size, thisNameRef).makeStmt() + val statement = CallTranslator.translate(innerContext, resolvedCall).toInvocationWith( + leadingArgs, delegationConstructor.valueParameters.size, thisNameRef.deepCopy()) + .source(resolvedCall.call.callElement) + .makeStmt() it += innerContext.currentBlock.statements it += statement } @@ -280,11 +284,14 @@ class ClassTranslator private constructor( val closure = context.getClassOrConstructorClosure(classDescriptor).orEmpty().map { usageTracker.getNameForCapturedDescriptor(it)!!.makeRef() } - it += JsInvocation(Namer.getFunctionCallRef(referenceToClass), listOf(thisNameRef) + closure + leadingArgs).makeStmt() + it += JsInvocation(Namer.getFunctionCallRef(referenceToClass), listOf(thisNameRef.deepCopy()) + closure + leadingArgs) + .source(classDeclaration).makeStmt() } } - constructorInitializer.body.statements += JsReturn(thisNameRef) + constructorInitializer.body.statements += JsReturn(thisNameRef.deepCopy()).apply { + source = constructor + } val compositeSuperCallGenerator: () -> Unit = { val additionalStatements = mutableListOf() @@ -310,8 +317,9 @@ class ClassTranslator private constructor( val constructorMap = allConstructors.map { it.descriptor to it }.toMap() val callSiteMap = callSites.groupBy { - val constructor = it.constructor - if (constructor.isPrimary) constructor.containingDeclaration else constructor + val constructor = it.constructor + val result: DeclarationDescriptor = if (constructor.isPrimary) constructor.containingDeclaration else constructor + result } val thisCalls = secondaryConstructors.map { @@ -437,7 +445,7 @@ class ClassTranslator private constructor( private fun addObjectCache(statements: MutableList) { cachedInstanceName = JsScope.declareTemporaryName(StaticContext.getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_VAR_SUFFIX) - statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsObjectLiteral.THIS).makeStmt() + statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsObjectLiteral.THIS).source(classDeclaration).makeStmt() } private fun addObjectMethods() { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java index e938cb5054c..bafe9cdccd9 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java @@ -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. 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 a5b4c5bce2f..033185e0cb9 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 @@ -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.initializer; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; @@ -48,6 +49,7 @@ 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; @@ -173,14 +175,14 @@ public final class ClassInitializerTranslator extends AbstractTranslator { private void mayBeAddCallToSuperMethod(JsFunction initializer) { if (classDeclaration.hasModifier(KtTokens.ENUM_KEYWORD)) { - addCallToSuperMethod(Collections.emptyList(), initializer); + addCallToSuperMethod(Collections.emptyList(), initializer, classDeclaration); } else if (hasAncestorClass(bindingContext(), classDeclaration)) { ResolvedCall superCall = getSuperCall(bindingContext(), classDeclaration); if (superCall == null) { if (DescriptorUtils.isEnumEntry(classDescriptor)) { - addCallToSuperMethod(getAdditionalArgumentsForEnumConstructor(), initializer); + addCallToSuperMethod(getAdditionalArgumentsForEnumConstructor(), initializer, classDeclaration); } return; } @@ -234,7 +236,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { } if (superDescriptor.isPrimary()) { - addCallToSuperMethod(arguments, initializer); + addCallToSuperMethod(arguments, initializer, superCall.getCall().getCallElement()); } else { int maxValueArgumentIndex = 0; @@ -325,7 +327,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { return additionalArguments; } - private void addCallToSuperMethod(@NotNull List arguments, @NotNull JsFunction initializer) { + private void addCallToSuperMethod(@NotNull List arguments, @NotNull JsFunction initializer, @NotNull PsiElement psi) { if (initializer.getName() == null) { JsName ref = context().scope().declareName(Namer.CALLEE_NAME); initializer.setName(ref); @@ -334,6 +336,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { ClassDescriptor superclassDescriptor = DescriptorUtilsKt.getSuperClassOrAny(classDescriptor); JsExpression superConstructorRef = context().getInnerReference(superclassDescriptor); JsInvocation call = new JsInvocation(Namer.getFunctionCallRef(superConstructorRef)); + call.setSource(psi); call.getArguments().add(JsLiteral.THIS); call.getArguments().addAll(arguments); initFunction.getBody().getStatements().add(call.makeStmt()); diff --git a/js/js.translator/testData/lineNumbers/multipleReferences.kt b/js/js.translator/testData/lineNumbers/multipleReferences.kt index d4d72176b26..10b48803020 100644 --- a/js/js.translator/testData/lineNumbers/multipleReferences.kt +++ b/js/js.translator/testData/lineNumbers/multipleReferences.kt @@ -12,4 +12,4 @@ object O { val y = 23 } -// LINES: 2 3 4 6 7 8 12 +// LINES: 2 3 4 6 7 8 11 12 diff --git a/js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt b/js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt new file mode 100644 index 00000000000..696aba5fb0f --- /dev/null +++ b/js/js.translator/testData/lineNumbers/syntheticCodeInConstructors.kt @@ -0,0 +1,28 @@ +object O { + init { + println() + } +} + +open class A(x: Int) + +class B : + A( + 23 + ) + +class C : A { + constructor(x: Int) : + super( + x + ) { + println() + } + + constructor() : + this ( + 42 + ) +} + +// LINES: 1 3 * 10 11 * 15 16 17 14 19 15 22 23 24 22 \ No newline at end of file