Generated source map for JS function's closing curly bracket

This commit is contained in:
Alexey Andreev
2017-06-22 18:39:59 +03:00
parent 4e18ea2d04
commit 1e74325c52
57 changed files with 113 additions and 63 deletions
@@ -275,7 +275,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
@Override @Override
public void visitBlock(@NotNull JsBlock x) { public void visitBlock(@NotNull JsBlock x) {
printJsBlock(x, true); printJsBlock(x, true, null);
} }
@Override @Override
@@ -496,7 +496,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
@Override @Override
public void visitExpressionStatement(@NotNull JsExpressionStatement x) { public void visitExpressionStatement(@NotNull JsExpressionStatement x) {
Object source = x.getSource(); Object source = x.getSource();
if (source == null) { if (source == null && !(x.getExpression() instanceof JsFunction)) {
source = x.getExpression().getSource(); source = x.getExpression().getSource();
} }
pushSourceInfo(source); pushSourceInfo(source);
@@ -605,8 +605,6 @@ public class JsToStringGenerationVisitor extends JsVisitor {
@Override @Override
public void visitFunction(@NotNull JsFunction x) { public void visitFunction(@NotNull JsFunction x) {
pushSourceInfo(x.getSource());
p.print(CHARS_FUNCTION); p.print(CHARS_FUNCTION);
space(); space();
if (x.getName() != null) { if (x.getName() != null) {
@@ -626,12 +624,10 @@ public class JsToStringGenerationVisitor extends JsVisitor {
lineBreakAfterBlock = false; lineBreakAfterBlock = false;
sourceLocationConsumer.pushSourceInfo(null); sourceLocationConsumer.pushSourceInfo(null);
accept(x.getBody()); printJsBlock(x.getBody(), true, x.getSource());
sourceLocationConsumer.popSourceInfo(); sourceLocationConsumer.popSourceInfo();
needSemi = true; needSemi = true;
popSourceInfo();
} }
@Override @Override
@@ -1111,7 +1107,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
} }
} }
private void printJsBlock(JsBlock x, boolean finalNewline) { private void printJsBlock(JsBlock x, boolean finalNewline, Object closingBracketLocation) {
if (!lineBreakAfterBlock) { if (!lineBreakAfterBlock) {
finalNewline = false; finalNewline = false;
lineBreakAfterBlock = true; lineBreakAfterBlock = true;
@@ -1184,7 +1180,15 @@ public class JsToStringGenerationVisitor extends JsVisitor {
if (needBraces) { if (needBraces) {
// _blockClose() modified // _blockClose() modified
p.indentOut(); p.indentOut();
if (closingBracketLocation != null) {
pushSourceInfo(closingBracketLocation);
}
p.print('}'); p.print('}');
if (closingBracketLocation != null) {
popSourceInfo();
}
if (finalNewline) { if (finalNewline) {
newlineOpt(); newlineOpt();
} }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
import org.jetbrains.kotlin.js.inline.util.getInnerFunction import org.jetbrains.kotlin.js.inline.util.getInnerFunction
import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.finalElement
class CoroutineFunctionTransformer(private val function: JsFunction, name: String?) { class CoroutineFunctionTransformer(private val function: JsFunction, name: String?) {
private val innerFunction = function.getInnerFunction() private val innerFunction = function.getInnerFunction()
@@ -61,6 +62,7 @@ class CoroutineFunctionTransformer(private val function: JsFunction, name: Strin
val psiElement = context.metadata.psiElement val psiElement = context.metadata.psiElement
val constructor = JsFunction(function.scope.parent, JsBlock(), "Continuation") val constructor = JsFunction(function.scope.parent, JsBlock(), "Continuation")
constructor.source = psiElement?.finalElement
constructor.name = className constructor.name = className
if (context.metadata.hasReceiver) { if (context.metadata.hasReceiver) {
constructor.parameters += JsParameter(context.receiverFieldName) constructor.parameters += JsParameter(context.receiverFieldName)
@@ -130,6 +132,7 @@ class CoroutineFunctionTransformer(private val function: JsFunction, name: Strin
statements: MutableList<JsStatement> statements: MutableList<JsStatement>
) { ) {
val resumeFunction = JsFunction(function.scope.parent, JsBlock(), "resume function") val resumeFunction = JsFunction(function.scope.parent, JsBlock(), "resume function")
resumeFunction.source = context.metadata.psiElement?.finalElement
val coroutineBody = generateCoroutineBody(context, coroutineBlocks) val coroutineBody = generateCoroutineBody(context, coroutineBlocks)
functionWithBody.body.statements.clear() functionWithBody.body.statements.clear()
@@ -208,6 +208,7 @@ public class Parser extends Observable {
int savedFunctionNumber = functionNumber; int savedFunctionNumber = functionNumber;
Node args; Node args;
Node body; Node body;
CodePosition closingBracketPosition;
try { try {
functionNumber = 0; functionNumber = 0;
args = nf.createLeaf(TokenStream.LP, ts.tokenPosition); args = nf.createLeaf(TokenStream.LP, ts.tokenPosition);
@@ -226,6 +227,7 @@ public class Parser extends Observable {
mustMatchToken(ts, TokenStream.LC, "msg.no.brace.body"); mustMatchToken(ts, TokenStream.LC, "msg.no.brace.body");
body = parseFunctionBody(ts); body = parseFunctionBody(ts);
closingBracketPosition = ts.tokenPosition;
mustMatchToken(ts, TokenStream.RC, "msg.no.brace.after.body"); mustMatchToken(ts, TokenStream.RC, "msg.no.brace.after.body");
// skip the last EOL so nested functions work... // skip the last EOL so nested functions work...
} }
@@ -234,7 +236,7 @@ public class Parser extends Observable {
functionNumber = savedFunctionNumber; functionNumber = savedFunctionNumber;
} }
Node pn = nf.createFunction(nameNode, args, body, basePosition); Node pn = nf.createFunction(nameNode, args, body, closingBracketPosition);
if (memberExprNode != null) { if (memberExprNode != null) {
pn = nf.createBinary(TokenStream.ASSIGN, TokenStream.NOP, memberExprNode, pn, basePosition); pn = nf.createBinary(TokenStream.ASSIGN, TokenStream.NOP, memberExprNode, pn, basePosition);
} }
@@ -100,6 +100,12 @@ class SourceMapLocationRemapper(private val sourceMap: SourceMap) {
override fun visitInvocation(invocation: JsInvocation) = override fun visitInvocation(invocation: JsInvocation) =
handleNode(invocation, invocation.qualifier, *invocation.arguments.toTypedArray()) handleNode(invocation, invocation.qualifier, *invocation.arguments.toTypedArray())
override fun visitFunction(x: JsFunction) {
x.parameters.forEach { accept(it) }
x.body.statements.forEach { accept(it) }
nodeList += x
}
override fun visitElement(node: JsNode) { override fun visitElement(node: JsNode) {
nodeList += node nodeList += node
node.acceptChildren(this) node.acceptChildren(this)
@@ -57,14 +57,8 @@ class LineCollector : RecursiveJsVisitor() {
} }
override fun visitExpressionStatement(x: JsExpressionStatement) { override fun visitExpressionStatement(x: JsExpressionStatement) {
val expression = x.expression withStatement(x) {
if (expression is JsFunction) { super.visitExpressionStatement(x)
expression.accept(this)
}
else {
withStatement(x) {
super.visitExpressionStatement(x)
}
} }
} }
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.source.getPsi
internal class DeclarationExporter(val context: StaticContext) { internal class DeclarationExporter(val context: StaticContext) {
private val objectLikeKinds = setOf(ClassKind.OBJECT, ClassKind.ENUM_ENTRY) private val objectLikeKinds = setOf(ClassKind.OBJECT, ClassKind.ENUM_ENTRY)
@@ -113,6 +114,7 @@ internal class DeclarationExporter(val context: StaticContext) {
val setterBody: JsExpression = if (simpleProperty) { val setterBody: JsExpression = if (simpleProperty) {
val statements = mutableListOf<JsStatement>() val statements = mutableListOf<JsStatement>()
val function = JsFunction(context.fragment.scope, JsBlock(statements), "$declaration setter") val function = JsFunction(context.fragment.scope, JsBlock(statements), "$declaration setter")
function.source = declaration.source.getPsi()
val valueName = JsScope.declareTemporaryName("value") val valueName = JsScope.declareTemporaryName("value")
function.parameters += JsParameter(valueName) function.parameters += JsParameter(valueName)
statements += assignment(context.getInnerNameForDescriptor(declaration).makeRef(), valueName.makeRef()).makeStmt() statements += assignment(context.getInnerNameForDescriptor(declaration).makeRef(), valueName.makeRef()).makeStmt()
@@ -48,6 +48,8 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt; import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
import org.jetbrains.kotlin.serialization.js.ModuleKind; import org.jetbrains.kotlin.serialization.js.ModuleKind;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
@@ -667,6 +669,7 @@ public final class StaticContext {
JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(fragment.getScope()); JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(fragment.getScope());
assert (!scopeToFunction.containsKey(correspondingFunction.getScope())) : "Scope to function value overridden for " + descriptor; assert (!scopeToFunction.containsKey(correspondingFunction.getScope())) : "Scope to function value overridden for " + descriptor;
scopeToFunction.put(correspondingFunction.getScope(), correspondingFunction); scopeToFunction.put(correspondingFunction.getScope(), correspondingFunction);
correspondingFunction.setSource(KotlinSourceElementKt.getPsi(((CallableDescriptor) descriptor).getSource()));
return correspondingFunction.getScope(); return correspondingFunction.getScope();
}; };
Rule<JsScope> scopeForPackage = descriptor -> { Rule<JsScope> scopeForPackage = descriptor -> {
@@ -56,6 +56,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor<Unit>() {
} }
else { else {
val function = context.getFunctionObject(getter) val function = context.getFunctionObject(getter)
function.source = expression
defaultTranslator.generateDefaultGetterFunction(getter, function) defaultTranslator.generateDefaultGetterFunction(getter, function)
function function
} }
@@ -67,6 +68,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor<Unit>() {
} }
else { else {
val function = context.getFunctionObject(setter) val function = context.getFunctionObject(setter)
function.source = expression
defaultTranslator.generateDefaultSetterFunction(setter, function) defaultTranslator.generateDefaultSetterFunction(setter, function)
function function
} }
@@ -98,6 +100,7 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor<Unit>() {
context: TranslationContext context: TranslationContext
): JsExpression { ): JsExpression {
val function = context.getFunctionObject(descriptor) val function = context.getFunctionObject(descriptor)
function.source = expression.finalElement
val innerContext = context.newDeclaration(descriptor).translateAndAliasParameters(descriptor, function.parameters) val innerContext = context.newDeclaration(descriptor).translateAndAliasParameters(descriptor, function.parameters)
if (descriptor.isSuspend) { if (descriptor.isSuspend) {
@@ -158,6 +158,7 @@ class ClassTranslator private constructor(
private fun createEnumInitFunction(): JsFunction { private fun createEnumInitFunction(): JsFunction {
val function = context().createRootScopedFunction(descriptor) val function = context().createRootScopedFunction(descriptor)
function.name = JsScope.declareTemporaryName(StaticContext.getSuggestedName(descriptor) + "_initFields") function.name = JsScope.declareTemporaryName(StaticContext.getSuggestedName(descriptor) + "_initFields")
function.source = classDeclaration
val emptyFunction = context().createRootScopedFunction(descriptor) val emptyFunction = context().createRootScopedFunction(descriptor)
function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction) function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction)
.source(classDeclaration).makeStmt() .source(classDeclaration).makeStmt()
@@ -455,6 +456,7 @@ class ClassTranslator private constructor(
val instanceFun = context().createRootScopedFunction("Instance function: " + descriptor) val instanceFun = context().createRootScopedFunction("Instance function: " + descriptor)
instanceFun.name = context().getNameForObjectInstance(descriptor) instanceFun.name = context().getNameForObjectInstance(descriptor)
instanceFun.source = classDeclaration
if (enumInitializerName != null) { if (enumInitializerName != null) {
instanceFun.body.statements += JsInvocation(pureFqn(enumInitializerName, null)).source(classDeclaration).makeStmt() instanceFun.body.statements += JsInvocation(pureFqn(enumInitializerName, null)).source(classDeclaration).makeStmt()
@@ -75,6 +75,7 @@ class DeclarationBodyVisitor(
enumInitializer.body.statements += JsAstUtils.assignment(pureFqn(enumInstanceName, null), jsEnumEntryCreation).makeStmt() enumInitializer.body.statements += JsAstUtils.assignment(pureFqn(enumInstanceName, null), jsEnumEntryCreation).makeStmt()
val enumInstanceFunction = context.createRootScopedFunction(descriptor) val enumInstanceFunction = context.createRootScopedFunction(descriptor)
enumInstanceFunction.source = enumEntry
enumInstanceFunction.name = context.getNameForObjectInstance(descriptor) enumInstanceFunction.name = context.getNameForObjectInstance(descriptor)
context.addDeclarationStatement(enumInstanceFunction.makeStmt()) context.addDeclarationStatement(enumInstanceFunction.makeStmt())
@@ -114,6 +115,7 @@ class DeclarationBodyVisitor(
if (descriptor.hasOwnParametersWithDefaultValue()) { if (descriptor.hasOwnParametersWithDefaultValue()) {
val caller = JsFunction(context.getScopeForDescriptor(containingClass), JsBlock(), "") val caller = JsFunction(context.getScopeForDescriptor(containingClass), JsBlock(), "")
caller.source = psi.finalElement
val callerContext = context val callerContext = context
.newDeclaration(descriptor) .newDeclaration(descriptor)
.translateAndAliasParameters(descriptor, caller.parameters) .translateAndAliasParameters(descriptor, caller.parameters)
@@ -131,6 +131,7 @@ class DelegationTranslator(
returnExpression.source(specifier) returnExpression.source(specifier)
val jsFunction = simpleReturnFunction(context().getScopeForDescriptor(getterDescriptor.containingDeclaration), returnExpression) val jsFunction = simpleReturnFunction(context().getScopeForDescriptor(getterDescriptor.containingDeclaration), returnExpression)
jsFunction.source = specifier
if (DescriptorUtils.isExtension(descriptor)) { if (DescriptorUtils.isExtension(descriptor)) {
val receiverName = jsFunction.scope.declareName(Namer.getReceiverParameterName()) val receiverName = jsFunction.scope.declareName(Namer.getReceiverParameterName())
jsFunction.parameters.add(JsParameter(receiverName)) jsFunction.parameters.add(JsParameter(receiverName))
@@ -141,6 +142,7 @@ class DelegationTranslator(
fun generateDelegateSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction { fun generateDelegateSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction {
val jsFunction = JsFunction(context().program().rootScope, val jsFunction = JsFunction(context().program().rootScope,
"setter for " + setterDescriptor.name.asString()) "setter for " + setterDescriptor.name.asString())
jsFunction.source = specifier
assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" } assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" }
val defaultParameter = JsParameter(JsScope.declareTemporary()) val defaultParameter = JsParameter(JsScope.declareTemporary())
@@ -208,6 +208,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
private JsFunction generateJsMethod(@NotNull FunctionDescriptor functionDescriptor) { private JsFunction generateJsMethod(@NotNull FunctionDescriptor functionDescriptor) {
JsFunction functionObject = context.createRootScopedFunction(functionDescriptor); JsFunction functionObject = context.createRootScopedFunction(functionDescriptor);
functionObject.setSource(getDeclaration());
ClassDescriptor containingClass = (ClassDescriptor) functionDescriptor.getContainingDeclaration(); ClassDescriptor containingClass = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
context.addDeclarationStatement(UtilsKt.addFunctionToPrototype(context, containingClass, functionDescriptor, functionObject)); context.addDeclarationStatement(UtilsKt.addFunctionToPrototype(context, containingClass, functionDescriptor, functionObject));
return functionObject; return functionObject;
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.* import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.*
import org.jetbrains.kotlin.js.translate.utils.finalElement
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addParameter import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addParameter
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addStatement import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.addStatement
import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtProperty
@@ -245,12 +246,16 @@ private class PropertyTranslator(
private fun translateCustomAccessor(expression: KtPropertyAccessor): JsPropertyInitializer { private fun translateCustomAccessor(expression: KtPropertyAccessor): JsPropertyInitializer {
val descriptor = BindingUtils.getFunctionDescriptor(bindingContext(), expression) val descriptor = BindingUtils.getFunctionDescriptor(bindingContext(), expression)
val function = JsFunction(context().getScopeForDescriptor(descriptor), JsBlock(), descriptor.toString()) val function = JsFunction(context().getScopeForDescriptor(descriptor), JsBlock(), descriptor.toString())
function.source = expression.finalElement
context().translateAndAliasParameters(descriptor, function.parameters).translateFunction(expression, function) context().translateAndAliasParameters(descriptor, function.parameters).translateFunction(expression, function)
return translateFunctionAsEcma5PropertyDescriptor(function, descriptor, context()) return translateFunctionAsEcma5PropertyDescriptor(function, descriptor, context())
} }
private fun createFunction(descriptor: VariableAccessorDescriptor) = private fun createFunction(descriptor: VariableAccessorDescriptor): JsFunction {
JsFunction(context().getScopeForDescriptor(descriptor), JsBlock(), accessorDescription(descriptor)) val function = JsFunction(context().getScopeForDescriptor(descriptor), JsBlock(), accessorDescription(descriptor))
function.source = descriptor.source.getPsi()?.finalElement
return function
}
private fun accessorDescription(accessorDescriptor: VariableAccessorDescriptor): String { private fun accessorDescription(accessorDescriptor: VariableAccessorDescriptor): String {
val accessorType = val accessorType =
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.js.translate.utils.FunctionBodyTranslator.translateF
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
import org.jetbrains.kotlin.js.translate.utils.fillCoroutineMetadata import org.jetbrains.kotlin.js.translate.utils.fillCoroutineMetadata
import org.jetbrains.kotlin.js.translate.utils.finalElement
import org.jetbrains.kotlin.psi.KtDeclarationWithBody import org.jetbrains.kotlin.psi.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslator(context) { class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslator(context) {
fun translate(declaration: KtDeclarationWithBody): JsExpression { fun translate(declaration: KtDeclarationWithBody): JsExpression {
val finalElement = declaration.finalElement
val invokingContext = context() val invokingContext = context()
val descriptor = getFunctionDescriptor(invokingContext.bindingContext(), declaration) val descriptor = getFunctionDescriptor(invokingContext.bindingContext(), declaration)
@@ -59,6 +61,7 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
lambda.body.statements += setDefaultValueForArguments(descriptor, functionContext) lambda.body.statements += setDefaultValueForArguments(descriptor, functionContext)
lambda.body.statements += translateFunctionBody(descriptor, declaration, functionContext) lambda.body.statements += translateFunctionBody(descriptor, declaration, functionContext)
lambda.functionDescriptor = descriptor lambda.functionDescriptor = descriptor
lambda.source = finalElement
val tracker = functionContext.usageTracker()!! val tracker = functionContext.usageTracker()!!
@@ -71,6 +74,7 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
} }
lambdaCreator.name.staticRef = lambdaCreator lambdaCreator.name.staticRef = lambdaCreator
lambdaCreator.fillCoroutineMetadata(invokingContext, descriptor) lambdaCreator.fillCoroutineMetadata(invokingContext, descriptor)
lambdaCreator.source = declaration
return lambdaCreator.withCapturedParameters(descriptor, functionContext, invokingContext) return lambdaCreator.withCapturedParameters(descriptor, functionContext, invokingContext)
} }
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.general.Translation import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.BindingUtils import org.jetbrains.kotlin.js.translate.utils.BindingUtils
import org.jetbrains.kotlin.js.translate.utils.finalElement
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
@@ -96,6 +97,7 @@ object CallableReferenceTranslator {
} }
val function = JsFunction(context.scope(), JsBlock(), "") val function = JsFunction(context.scope(), JsBlock(), "")
function.source = expression
val receiverParam = if (descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null) { val receiverParam = if (descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null) {
val paramName = JsScope.declareTemporaryName(Namer.getReceiverParameterName()) val paramName = JsScope.declareTemporaryName(Namer.getReceiverParameterName())
function.parameters += JsParameter(paramName) function.parameters += JsParameter(paramName)
@@ -127,12 +129,12 @@ object CallableReferenceTranslator {
): JsExpression { ): JsExpression {
val call = expression.callableReference.getPropertyResolvedCallWithAssert(context.bindingContext()) val call = expression.callableReference.getPropertyResolvedCallWithAssert(context.bindingContext())
val getter = translateForPropertyAccessor(call, descriptor, context, receiver, false) { context, call, _, receiverParam -> val getter = translateForPropertyAccessor(call, expression, descriptor, context, receiver, false) { context, call, _, receiverParam ->
CallTranslator.translateGet(context, call, receiverParam) CallTranslator.translateGet(context, call, receiverParam)
} }
val setter = if (isSetterVisible(descriptor, context)) { val setter = if (isSetterVisible(descriptor, context)) {
translateForPropertyAccessor(call, descriptor, context, receiver, true, CallTranslator::translateSet) translateForPropertyAccessor(call, expression, descriptor, context, receiver, true, CallTranslator::translateSet)
} }
else { else {
null null
@@ -153,6 +155,7 @@ object CallableReferenceTranslator {
private fun translateForPropertyAccessor( private fun translateForPropertyAccessor(
call: ResolvedCall<out PropertyDescriptor>, call: ResolvedCall<out PropertyDescriptor>,
expression: KtExpression,
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
context: TranslationContext, context: TranslationContext,
receiver: JsExpression?, receiver: JsExpression?,
@@ -160,6 +163,7 @@ object CallableReferenceTranslator {
translator: (TranslationContext, ResolvedCall<out PropertyDescriptor>, JsExpression, JsExpression?) -> JsExpression translator: (TranslationContext, ResolvedCall<out PropertyDescriptor>, JsExpression, JsExpression?) -> JsExpression
): JsExpression { ): JsExpression {
val accessorFunction = JsFunction(context.scope(), JsBlock(), "") val accessorFunction = JsFunction(context.scope(), JsBlock(), "")
accessorFunction.source = expression.finalElement
val accessorContext = context.innerBlock(accessorFunction.body) val accessorContext = context.innerBlock(accessorFunction.body)
val receiverParam = if (descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null) { val receiverParam = if (descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null) {
val name = JsScope.declareTemporaryName(Namer.getReceiverParameterName()) val name = JsScope.declareTemporaryName(Namer.getReceiverParameterName())
@@ -35,6 +35,10 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsicWithReceiverComputed
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOrInheritsParametersWithDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasOrInheritsParametersWithDefaultValue
@@ -88,6 +92,7 @@ fun generateDelegateCall(
invocation.source = source invocation.source = source
val functionObject = simpleReturnFunction(context.scope(), invocation) val functionObject = simpleReturnFunction(context.scope(), invocation)
functionObject.source = source?.finalElement
functionObject.parameters.addAll(parameters) functionObject.parameters.addAll(parameters)
val fromFunctionName = fromDescriptor.getNameForFunctionWithPossibleDefaultParam() val fromFunctionName = fromDescriptor.getNameForFunctionWithPossibleDefaultParam()
@@ -201,3 +206,11 @@ fun definePackageAlias(name: String, varName: JsName, tag: String, parentRef: Js
return JsAstUtils.newVar(varName, rhs).apply { exportedPackage = tag } return JsAstUtils.newVar(varName, rhs).apply { exportedPackage = tag }
} }
val PsiElement.finalElement: PsiElement
get() = when (this) {
is KtFunctionLiteral -> rBrace ?: this
is KtDeclarationWithBody -> (bodyExpression as? KtBlockExpression)?.rBrace ?: bodyExpression ?: this
is KtLambdaExpression -> bodyExpression?.rBrace ?: this
else -> this
}
@@ -6,4 +6,4 @@ fun box(x: Int, y: Int) {
fun foo(x: Int) = x fun foo(x: Int) = x
// LINES: 3 3 * 3 3 4 4 * 4 4 2 3 7 // LINES: 5 * 3 3 * 3 3 4 4 * 4 4 2 3 7 7
+1 -1
View File
@@ -12,4 +12,4 @@ open class A {
} }
} }
// LINES: 2 4 2 2 * 5 6 8 9 10 11 // LINES: 1 2 4 2 2 2 5 5 6 12 8 9 10 11
+1 -1
View File
@@ -19,4 +19,4 @@ fun bar() {
} }
} }
// LINES: 3 5 5 6 8 8 9 * 15 18 // LINES: 11 3 5 5 6 8 8 9 * 20 15 18
+1 -1
View File
@@ -14,4 +14,4 @@ class C {
val baz: dynamic get() = null val baz: dynamic get() = null
} }
// LINES: 2 4 3 2 6 8 7 6 12 * 14 // LINES: 9 2 4 3 2 6 8 7 6 11 12 12 14 14
@@ -14,4 +14,4 @@ fun A.foo() {
fun baz() = 23 fun baz() = 23
// LINES: 5 5 7 8 * 4 11 12 15 // LINES: 1 * 5 5 5 9 7 8 * 13 4 11 12 15 15
+1 -1
View File
@@ -5,4 +5,4 @@ fun box(x: Int, y: Int): Int {
return foo(y) return foo(y)
} }
// LINES: 2 4 2 5 // LINES: 2 2 4 6 2 5
@@ -11,4 +11,4 @@ fun baz() = 1
fun bar() = 2 fun bar() = 2
// LINES: 2 3 4 4 5 2 8 10 12 // LINES: 8 * 2 3 4 4 5 2 8 10 10 12 12
@@ -14,4 +14,4 @@ private inline fun foo(): Int {
return 23 return 23
} }
// LINES: 3 3 4 3 6 13 3 14 2 13 14 // LINES: 10 3 3 4 3 6 13 3 14 2 15 13 14
+1 -1
View File
@@ -14,4 +14,4 @@ suspend fun bar(): Unit {
println(a + b) println(a + b)
} }
// LINES: 4 5 5 6 4 9 9 9 9 9 9 9 9 * 10 11 11 11 11 11 * 11 12 13 13 13 13 13 13 14 // LINES: 4 4 5 5 6 4 4 15 9 9 9 9 15 9 9 9 9 * 15 10 11 11 11 11 11 * 11 12 13 13 13 13 13 13 14
+1 -1
View File
@@ -3,4 +3,4 @@ data class A(
val y: String val y: String
) )
// LINES: 2 3 * 2 * 3 * 1 2 3 * 1 2 3 * 1 2 3 1 * 1 2 3 // LINES: 1 2 3 * 1 2 1 3 1 1 2 3 1 1 2 3 1 1 2 3 1 1 1 2 3
+1 -1
View File
@@ -13,4 +13,4 @@ class Delegate(val f: () -> Int) {
} }
} }
// LINES: 2 3 2 * 3 * 7 10 12 // LINES: 1 2 3 2 2 3 3 * 8 7 10 10 13 12
+1 -1
View File
@@ -15,4 +15,4 @@ class B {
} }
} }
// LINES: 4 5 4 4 2 * 10 * 14 // LINES: 3 4 5 4 4 4 2 * 8 11 10 15 14
+1 -1
View File
@@ -18,4 +18,4 @@ val o = object : I {
} }
} }
// LINES: 2 3 2 2 * 2 * 12 * 15 17 // LINES: 1 2 3 2 2 2 2 2 * 11 12 12 15 15 18 17
@@ -13,4 +13,4 @@ fun box() {
) )
} }
// LINES: 8 3 2 3 3 8 11 * 3 7 12 3 3 4 // LINES: 14 8 3 2 3 3 8 11 * 3 7 12 3 3 4
@@ -6,4 +6,4 @@ enum class Foo {
} }
} }
// LINES: 1 1 1 1 2 4 * 2 2 4 5 * 4 4 4 4 * 1 * 1 1 1 // LINES: 1 1 1 1 1 1 2 4 * 2 2 2 4 4 5 * 4 4 4 4 4 * 1 1 * 1 1 1 1
+1 -1
View File
@@ -10,4 +10,4 @@ enum class E {
} }
} }
// LINES: 1 1 1 1 2 4 8 * 2 2 4 4 5 * 4 4 8 8 9 * 8 8 * 1 * 1 1 1 1 1 // LINES: 1 1 1 1 1 1 2 4 8 * 2 2 2 4 4 4 5 5 * 4 4 4 8 8 8 9 9 * 8 8 8 * 1 1 * 1 1 1 1 1 1
@@ -4,4 +4,4 @@ fun box() =
fun foo() = fun foo() =
23 23
// LINES: 2 5 // LINES: 2 2 5 5
+1 -1
View File
@@ -17,4 +17,4 @@ fun box() {
} }
} }
// LINES: 2 10 15 2 2 2 2 3 6 6 6 7 10 10 10 10 11 14 15 15 15 15 15 15 15 16 // LINES: 18 2 10 15 2 2 2 2 3 6 6 6 7 10 10 10 10 11 14 15 15 15 15 15 15 15 16
+1 -1
View File
@@ -8,4 +8,4 @@ fun foo(x: Int) {
println(y) println(y)
} }
// LINES: 2 3 4 5 6 7 8 // LINES: 9 2 3 4 5 6 7 8
@@ -9,4 +9,4 @@ fun bar() {
foo(42) foo(42)
} }
// LINES: 2 3 3 4 * 2 9 2 3 3 4 // LINES: 6 2 3 3 4 10 2 9 2 3 3 4
@@ -8,7 +8,7 @@ inline fun foo(x: String) {
println("foo2($x);") println("foo2($x);")
} }
// LINES: 7 8 // LINES: 9 7 8
// MODULE: main(lib) // MODULE: main(lib)
// FILE: main.kt // FILE: main.kt
@@ -21,4 +21,4 @@ fun box() {
foo("42") foo("42")
} }
// LINES: 7 20 7 8 20 8 7 21 7 8 21 8 // LINES: 22 7 20 7 8 20 8 7 21 7 8 21 8
+1 -1
View File
@@ -21,4 +21,4 @@ fun bar(x: Int) {
println("%") println("%")
} }
// LINES: 2 2 3 4 7 9 9 10 11 14 16 * 20 * 2 2 3 4 3 7 9 9 10 11 10 14 16 * 20 21 // LINES: 17 2 2 3 4 7 9 9 10 11 14 16 22 20 * 2 2 3 4 3 7 9 9 10 11 10 14 16 * 20 21
+1 -1
View File
@@ -11,4 +11,4 @@ inline fun bar() {
println("bar2") println("bar2")
} }
// LINES: 2 10 11 4 10 11 6 10 11 // LINES: 7 2 10 11 4 10 11 6 12 10 11
@@ -16,4 +16,4 @@ inline fun foo(f: () -> Unit) {
println("after") println("after")
} }
// LINES: 2 14 4 16 6 14 8 16 10 14 15 16 // LINES: 11 2 14 4 16 6 14 8 16 10 17 14 15 16
+1 -1
View File
@@ -6,4 +6,4 @@ class A(val x: Int) {
} }
} }
// LINES: 1 2 4 // LINES: 1 1 2 2 5 4
+1 -1
View File
@@ -4,4 +4,4 @@ fun foo(x: Int): () -> Unit = {
fun bar() = 23 fun bar() = 23
// LINES: 1 2 1 5 // LINES: 1 1 2 1 1 5 5
+1 -1
View File
@@ -26,4 +26,4 @@ fun bar(vararg x: Any?) {
println(x) println(x)
} }
// LINES: 3 4 5 6 7 8 9 10 13 14 15 16 17 18 19 20 * 26 // LINES: 1 22 3 4 5 6 7 8 9 10 13 14 15 16 17 18 19 20 * 27 26
+1 -1
View File
@@ -5,4 +5,4 @@ fun foo() {
0L) 0L)
} }
// LINES: 2 3 4 5 // LINES: 6 2 3 4 5
@@ -10,4 +10,4 @@ class B : A() {
} }
} }
// LINES: 2 * 2 2 2 * 4 * 7 9 // LINES: 1 2 2 2 2 2 2 4 4 * 7 7 10 9
@@ -12,4 +12,4 @@ object O {
val y = 23 val y = 23
} }
// LINES: 2 3 4 6 7 8 11 12 * 11 11 11 // LINES: 9 2 3 4 6 7 8 11 11 12 * 11 11 11 11
@@ -4,4 +4,4 @@ fun foo() {
println("foo") println("foo")
} }
// LINES: 1 * 1 1 1 4 // LINES: 1 1 * 1 1 1 1 5 4
+1 -1
View File
@@ -7,4 +7,4 @@ fun box(
println(y) println(y)
} }
// LINES: 2 2 3 3 4 6 7 // LINES: 8 2 2 3 3 4 6 7
@@ -9,4 +9,4 @@ open class A {
} }
} }
// LINES: 2 4 7 8 4 // LINES: 1 2 4 7 8 4 4
+1 -1
View File
@@ -3,4 +3,4 @@ fun box() {
println("bar") println("bar")
} }
// LINES: 2 3 // LINES: 4 2 3
+1 -1
View File
@@ -4,4 +4,4 @@ fun box(x: Int): String {
"suffix" "suffix"
} }
// LINES: 2 3 4 // LINES: 5 2 3 4
@@ -25,4 +25,4 @@ class C : A {
) )
} }
// LINES: 1 3 * 1 1 1 * 10 11 * 15 16 17 14 19 15 22 23 24 22 // LINES: 1 1 3 * 1 1 1 1 7 * 9 10 11 * 15 15 16 17 14 19 15 22 22 23 24 22
@@ -8,4 +8,4 @@ enum class E {
} }
} }
// LINES: 1 1 1 1 2 3 4 * 2 2 * 3 3 4 4 6 * 4 4 * 1 * 1 1 1 1 1 // LINES: 1 1 1 1 1 1 2 3 4 * 2 2 2 * 3 3 3 4 4 4 6 * 4 4 4 * 1 1 * 1 1 1 1 1 1
+1 -1
View File
@@ -7,4 +7,4 @@ fun foo() {
A(23, "foo") A(23, "foo")
} }
// LINES: 2 3 * 7 // LINES: 1 2 3 * 8 7
+1 -1
View File
@@ -13,4 +13,4 @@ fun foo(): Int = 23
fun bar(): IntRange = 1000..2000 fun bar(): IntRange = 1000..2000
// LINES: 2 2 3 4 5 6 7 8 12 14 // LINES: 10 2 2 3 4 5 6 7 8 12 12 14 14
+1 -1
View File
@@ -13,4 +13,4 @@ open class A
open class B : A() open class B : A()
// LINES: 2 2 3 4 5 6 8 * 14 // LINES: 10 2 2 3 4 5 6 8 12 * 14 14
@@ -12,4 +12,4 @@ fun box() {
} }
} }
// LINES: 5 2 3 5 8 * 3 4 9 3 11 // LINES: 13 5 2 3 5 8 * 3 4 9 3 11