Fix generation of JS source maps for synthetic code in constructors

This commit is contained in:
Alexey Andreev
2017-05-03 14:22:18 +03:00
parent 4332f1cb2c
commit fb3a864892
8 changed files with 70 additions and 20 deletions
@@ -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);
}
}
@@ -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;
}
}
@@ -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);
}
@@ -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<JsStatement>()
@@ -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<JsStatement>) {
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() {
@@ -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.
@@ -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<FunctionDescriptor> 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<JsExpression> arguments, @NotNull JsFunction initializer) {
private void addCallToSuperMethod(@NotNull List<JsExpression> 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());
@@ -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
@@ -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