KT-11030 Minor code improvements
This commit is contained in:
@@ -171,4 +171,18 @@ public final class ClosureTest extends SingleFileTranslationTest {
|
|||||||
public void testLocalConstructorAndMethod() throws Exception {
|
public void testLocalConstructorAndMethod() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: tests UsageTracker but encounters issue somewhere else. Uncomment when issue with `this` generation gets fixed
|
||||||
|
// Presumably, KT-11823
|
||||||
|
/*public void testDeepInnerClassInLocalClass() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeepInnerClassInLocalClassFromExtension() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public void testImplicitGenericReceiverInExtensionInLocalClass() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-5
@@ -210,11 +210,8 @@ object ConstructorCallCase : FunctionCallCase() {
|
|||||||
val arguments = argumentsInfo.getArguments()
|
val arguments = argumentsInfo.getArguments()
|
||||||
|
|
||||||
val constructorDescriptor = callableDescriptor as ConstructorDescriptor
|
val constructorDescriptor = callableDescriptor as ConstructorDescriptor
|
||||||
val closure = context.getLocalClassClosure(constructorDescriptor)
|
val closure = context.getClassOrConstructorClosure(constructorDescriptor)
|
||||||
var closureArgs = emptyList<JsExpression>()
|
val closureArgs = closure?.map { context.getParameterNameRefForInvocation(it) } ?: emptyList()
|
||||||
if (closure != null) {
|
|
||||||
closureArgs = closure.asSequence().map { context.getParameterNameRefForInvocation(it) }.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (constructorDescriptor.isPrimary || AnnotationsUtils.isNativeObject(constructorDescriptor)) {
|
if (constructorDescriptor.isPrimary || AnnotationsUtils.isNativeObject(constructorDescriptor)) {
|
||||||
return JsNew(functionRef, closureArgs + arguments)
|
return JsNew(functionRef, closureArgs + arguments)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideE
|
|||||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.*;
|
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.*;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getMangledName;
|
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getMangledName;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName;
|
import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName;
|
||||||
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getParentOfType;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isExtension;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isExtension;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt.isDynamic;
|
import static org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt.isDynamic;
|
||||||
@@ -252,7 +253,7 @@ public final class StaticContext {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Rule<JsName> localDeclarations = new Rule<JsName>() {
|
Rule<JsName> localClasses = new Rule<JsName>() {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
@@ -263,9 +264,7 @@ public final class StaticContext {
|
|||||||
|
|
||||||
String suggested = getSuggestedName(descriptor);
|
String suggested = getSuggestedName(descriptor);
|
||||||
|
|
||||||
do {
|
descriptor = getParentOfType(descriptor, ClassOrPackageFragmentDescriptor.class, true);
|
||||||
descriptor = descriptor.getContainingDeclaration();
|
|
||||||
} while (descriptor != null && !(descriptor instanceof ClassOrPackageFragmentDescriptor));
|
|
||||||
assert descriptor != null;
|
assert descriptor != null;
|
||||||
|
|
||||||
JsScope scope = getScopeForDescriptor(descriptor);
|
JsScope scope = getScopeForDescriptor(descriptor);
|
||||||
@@ -291,7 +290,7 @@ public final class StaticContext {
|
|||||||
return scope.declareFreshName(getSuggestedName(descriptor));
|
return scope.declareFreshName(getSuggestedName(descriptor));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Rule<JsName> constructorOrCompanionObjectHasTheSameNameAsTheClass = new Rule<JsName>() {
|
Rule<JsName> constructorOrNativeCompanionObjectHasTheSameNameAsTheClass = new Rule<JsName>() {
|
||||||
@Override
|
@Override
|
||||||
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
if (descriptor instanceof ConstructorDescriptor && ((ConstructorDescriptor) descriptor).isPrimary() ||
|
if (descriptor instanceof ConstructorDescriptor && ((ConstructorDescriptor) descriptor).isPrimary() ||
|
||||||
@@ -385,9 +384,9 @@ public final class StaticContext {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addRule(namesForDynamic);
|
addRule(namesForDynamic);
|
||||||
addRule(localDeclarations);
|
addRule(localClasses);
|
||||||
addRule(namesForStandardClasses);
|
addRule(namesForStandardClasses);
|
||||||
addRule(constructorOrCompanionObjectHasTheSameNameAsTheClass);
|
addRule(constructorOrNativeCompanionObjectHasTheSameNameAsTheClass);
|
||||||
addRule(propertyOrPropertyAccessor);
|
addRule(propertyOrPropertyAccessor);
|
||||||
addRule(predefinedObjectsHasUnobfuscatableNames);
|
addRule(predefinedObjectsHasUnobfuscatableNames);
|
||||||
addRule(overridingDescriptorsReferToOriginalName);
|
addRule(overridingDescriptorsReferToOriginalName);
|
||||||
@@ -573,7 +572,7 @@ public final class StaticContext {
|
|||||||
if (!(descriptor instanceof ClassDescriptor)) {
|
if (!(descriptor instanceof ClassDescriptor)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
DeclarationDescriptor container = getEnclosing(descriptor.getContainingDeclaration());
|
DeclarationDescriptor container = getParentOfType(descriptor, ClassDescriptor.class);
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -593,12 +592,8 @@ public final class StaticContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor = descriptor.getContainingDeclaration();
|
descriptor = getParentOfType(descriptor, PackageFragmentDescriptor.class, true);
|
||||||
while (descriptor != null && !(descriptor instanceof ClassOrPackageFragmentDescriptor)) {
|
assert descriptor != null;
|
||||||
descriptor = descriptor.getContainingDeclaration();
|
|
||||||
}
|
|
||||||
if (!(descriptor instanceof PackageFragmentDescriptor)) return null;
|
|
||||||
|
|
||||||
return getQualifiedReference(descriptor);
|
return getQualifiedReference(descriptor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -614,14 +609,6 @@ public final class StaticContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static ClassDescriptor getEnclosing(@Nullable DeclarationDescriptor descriptor) {
|
|
||||||
while (descriptor != null && !(descriptor instanceof ClassDescriptor)) {
|
|
||||||
descriptor = descriptor.getContainingDeclaration();
|
|
||||||
}
|
|
||||||
return (ClassDescriptor) descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JsExpression applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) {
|
private static JsExpression applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) {
|
||||||
if (expression instanceof HasMetadata) {
|
if (expression instanceof HasMetadata) {
|
||||||
if (descriptor instanceof FunctionDescriptor ||
|
if (descriptor instanceof FunctionDescriptor ||
|
||||||
@@ -650,13 +637,13 @@ public final class StaticContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putLocalClassClosure(@NotNull MemberDescriptor localClass, @NotNull List<DeclarationDescriptor> closure) {
|
public void putClassOrConstructorClosure(@NotNull MemberDescriptor localClass, @NotNull List<DeclarationDescriptor> closure) {
|
||||||
localClassesClosure.put(localClass, Lists.newArrayList(closure));
|
localClassesClosure.put(localClass, Lists.newArrayList(closure));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<DeclarationDescriptor> getLocalClassClosure(@NotNull MemberDescriptor localClass) {
|
public List<DeclarationDescriptor> getClassOrConstructorClosure(@NotNull MemberDescriptor descriptor) {
|
||||||
List<DeclarationDescriptor> result = localClassesClosure.get(localClass);
|
List<DeclarationDescriptor> result = localClassesClosure.get(descriptor);
|
||||||
return result != null ? Lists.newArrayList(result) : null;
|
return result != null ? Lists.newArrayList(result) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-6
@@ -356,11 +356,17 @@ public class TranslationContext {
|
|||||||
if (descriptor.getValue() instanceof ExtensionReceiver) return JsLiteral.THIS;
|
if (descriptor.getValue() instanceof ExtensionReceiver) return JsLiteral.THIS;
|
||||||
|
|
||||||
ClassifierDescriptor classifier = descriptor.getValue().getType().getConstructor().getDeclarationDescriptor();
|
ClassifierDescriptor classifier = descriptor.getValue().getType().getConstructor().getDeclarationDescriptor();
|
||||||
if (!(classifier instanceof ClassDescriptor)) return JsLiteral.THIS;
|
|
||||||
|
// TODO: can't tell why this assertion is valid, revisit this code later
|
||||||
|
assert classifier instanceof ClassDescriptor;
|
||||||
|
|
||||||
ClassDescriptor cls = (ClassDescriptor) classifier;
|
ClassDescriptor cls = (ClassDescriptor) classifier;
|
||||||
|
|
||||||
JsExpression receiver = getAliasForDescriptor(cls.getThisAsReceiverParameter());
|
JsExpression receiver = getAliasForDescriptor(cls.getThisAsReceiverParameter());
|
||||||
|
|
||||||
|
// I could reproduce situation when receiver == null, although there's no test to reproduce it. Have no time for investigation
|
||||||
|
// Hint: try generating field with getter/setter, see deepInnerClassInLocalClass.kt
|
||||||
|
// TODO: revisit this code later
|
||||||
if (receiver == null) {
|
if (receiver == null) {
|
||||||
receiver = JsLiteral.THIS;
|
receiver = JsLiteral.THIS;
|
||||||
}
|
}
|
||||||
@@ -447,15 +453,15 @@ public class TranslationContext {
|
|||||||
return declarationDescriptor;
|
return declarationDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putLocalClassClosure(@NotNull MemberDescriptor localClass, @NotNull List<DeclarationDescriptor> closure) {
|
public void putClassOrConstructorClosure(@NotNull MemberDescriptor descriptor, @NotNull List<DeclarationDescriptor> closure) {
|
||||||
staticContext.putLocalClassClosure(localClass, closure);
|
staticContext.putClassOrConstructorClosure(descriptor, closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<DeclarationDescriptor> getLocalClassClosure(@NotNull MemberDescriptor localClass) {
|
public List<DeclarationDescriptor> getClassOrConstructorClosure(@NotNull MemberDescriptor localClass) {
|
||||||
List<DeclarationDescriptor> result = staticContext.getLocalClassClosure(localClass);
|
List<DeclarationDescriptor> result = staticContext.getClassOrConstructorClosure(localClass);
|
||||||
if (result == null && localClass instanceof ConstructorDescriptor && ((ConstructorDescriptor) localClass).isPrimary()) {
|
if (result == null && localClass instanceof ConstructorDescriptor && ((ConstructorDescriptor) localClass).isPrimary()) {
|
||||||
result = staticContext.getLocalClassClosure((ClassDescriptor) localClass.getContainingDeclaration());
|
result = staticContext.getClassOrConstructorClosure((ClassDescriptor) localClass.getContainingDeclaration());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,11 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.context
|
package org.jetbrains.kotlin.js.translate.context
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isAncestor
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsName
|
import com.google.dart.compiler.backend.js.ast.JsName
|
||||||
import org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName
|
import org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName
|
||||||
import com.google.dart.compiler.backend.js.ast.JsScope
|
import com.google.dart.compiler.backend.js.ast.JsScope
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.getParentOfType
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
|
||||||
|
|
||||||
private val CAPTURED_RECEIVER_NAME_PREFIX : String = "this$"
|
private val CAPTURED_RECEIVER_NAME_PREFIX : String = "this$"
|
||||||
|
|
||||||
@@ -64,14 +62,23 @@ class UsageTracker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun captureIfNeed(descriptor: DeclarationDescriptor?) {
|
private fun captureIfNeed(descriptor: DeclarationDescriptor?) {
|
||||||
if (descriptor == null || isCaptured(descriptor) || isAncestor(containingDescriptor, descriptor, /* strict = */ true) ||
|
if (descriptor == null || isCaptured(descriptor) || !isInLocalDeclaration() ||
|
||||||
isReceiverAncestor(descriptor) || isSingletonReceiver(descriptor)) return
|
isAncestor(containingDescriptor, descriptor, /* strict = */ true) ||
|
||||||
|
isReceiverAncestor(descriptor) || isSingletonReceiver(descriptor)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
parent?.captureIfNeed(descriptor)
|
parent?.captureIfNeed(descriptor)
|
||||||
|
|
||||||
captured[descriptor] = descriptor.getJsNameForCapturedDescriptor()
|
captured[descriptor] = descriptor.getJsNameForCapturedDescriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isInLocalDeclaration(): Boolean {
|
||||||
|
val container = containingDescriptor
|
||||||
|
return isDescriptorWithLocalVisibility(if (container is ConstructorDescriptor) container.containingDeclaration else container)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We shouldn't capture current `this` or outer `this`. Assuming `C` is current translating class,
|
* We shouldn't capture current `this` or outer `this`. Assuming `C` is current translating class,
|
||||||
* we have `descriptor == A::this` in the following cases:
|
* we have `descriptor == A::this` in the following cases:
|
||||||
@@ -92,10 +99,10 @@ class UsageTracker(
|
|||||||
*/
|
*/
|
||||||
private fun isReceiverAncestor(descriptor: DeclarationDescriptor): Boolean {
|
private fun isReceiverAncestor(descriptor: DeclarationDescriptor): Boolean {
|
||||||
if (descriptor !is ReceiverParameterDescriptor) return false
|
if (descriptor !is ReceiverParameterDescriptor) return false
|
||||||
if (containingDescriptor !is ClassDescriptor && DescriptorUtils.isDescriptorWithLocalVisibility(containingDescriptor)) return false
|
if (containingDescriptor !is ClassDescriptor && containingDescriptor !is ConstructorDescriptor) return false
|
||||||
|
|
||||||
val currentClass = DescriptorUtils.getClassDescriptorForType(descriptor.type)
|
|
||||||
val containingClass = getParentOfType(containingDescriptor, ClassDescriptor::class.java, false) ?: return false
|
val containingClass = getParentOfType(containingDescriptor, ClassDescriptor::class.java, false) ?: return false
|
||||||
|
val currentClass = descriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||||
|
|
||||||
for (outerDeclaration in generateSequence(containingClass) { it.containingDeclaration as? ClassDescriptor }) {
|
for (outerDeclaration in generateSequence(containingClass) { it.containingDeclaration as? ClassDescriptor }) {
|
||||||
if (DescriptorUtils.isSubclass(outerDeclaration, currentClass)) return true
|
if (DescriptorUtils.isSubclass(outerDeclaration, currentClass)) return true
|
||||||
@@ -124,19 +131,17 @@ class UsageTracker(
|
|||||||
private fun isSingletonReceiver(descriptor: DeclarationDescriptor): Boolean {
|
private fun isSingletonReceiver(descriptor: DeclarationDescriptor): Boolean {
|
||||||
if (descriptor !is ReceiverParameterDescriptor) return false
|
if (descriptor !is ReceiverParameterDescriptor) return false
|
||||||
|
|
||||||
val value = descriptor.value
|
val container = descriptor.containingDeclaration
|
||||||
if (value !is ImplicitReceiver) return false
|
if (!DescriptorUtils.isObject(container)) return false
|
||||||
|
|
||||||
if (!DescriptorUtils.isObject(value.declarationDescriptor)) return false
|
|
||||||
|
|
||||||
// This is workaround, since sometimes translator generates wrong expression for `this` expressions.
|
// This is workaround, since sometimes translator generates wrong expression for `this` expressions.
|
||||||
// Presumably, it's related to KT-11823
|
// Presumably, it's related to KT-11823
|
||||||
// TODO: remove when issue gets fixed.
|
// TODO: remove when issue gets fixed.
|
||||||
if (containingDescriptor == value.declarationDescriptor) return false
|
if (containingDescriptor == container) return false
|
||||||
|
|
||||||
if (containingDescriptor !is ClassDescriptor) {
|
if (containingDescriptor !is ClassDescriptor) {
|
||||||
val containingClass = getParentOfType(containingDescriptor, ClassDescriptor::class.java, false);
|
val containingClass = getParentOfType(containingDescriptor, ClassDescriptor::class.java, false);
|
||||||
if (containingClass == value.declarationDescriptor) return false
|
if (containingClass == container) return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
+40
-66
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
|||||||
import org.jetbrains.kotlin.types.CommonSupertypes.topologicallySortSuperclassesAndRecordAllInstances
|
import org.jetbrains.kotlin.types.CommonSupertypes.topologicallySortSuperclassesAndRecordAllInstances
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
import org.jetbrains.kotlin.utils.identity
|
import org.jetbrains.kotlin.utils.identity
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,9 +64,8 @@ class ClassTranslator private constructor(
|
|||||||
private var primaryConstructor: ConstructorInfo? = null
|
private var primaryConstructor: ConstructorInfo? = null
|
||||||
private lateinit var definitionPlace: DefinitionPlace
|
private lateinit var definitionPlace: DefinitionPlace
|
||||||
|
|
||||||
fun translate(): TranslationResult {
|
private fun translate(): TranslationResult {
|
||||||
invocationArguments.clear()
|
generateClassCreateInvocationArguments()
|
||||||
getClassCreateInvocationArguments()
|
|
||||||
|
|
||||||
val classNameRef = context().getNameForDescriptor(descriptor).makeRef()
|
val classNameRef = context().getNameForDescriptor(descriptor).makeRef()
|
||||||
val classCreation = JsInvocation(context().namer().classCreateInvocation(descriptor), invocationArguments)
|
val classCreation = JsInvocation(context().namer().classCreateInvocation(descriptor), invocationArguments)
|
||||||
@@ -76,16 +76,14 @@ class ClassTranslator private constructor(
|
|||||||
|
|
||||||
private fun isTrait(): Boolean = descriptor.kind == ClassKind.INTERFACE
|
private fun isTrait(): Boolean = descriptor.kind == ClassKind.INTERFACE
|
||||||
|
|
||||||
private fun getClassCreateInvocationArguments() {
|
private fun generateClassCreateInvocationArguments() {
|
||||||
var context = context()
|
|
||||||
|
|
||||||
val properties = SmartList<JsPropertyInitializer>()
|
val properties = SmartList<JsPropertyInitializer>()
|
||||||
val staticProperties = SmartList<JsPropertyInitializer>()
|
val staticProperties = SmartList<JsPropertyInitializer>()
|
||||||
|
|
||||||
val qualifiedReference = context.getQualifiedReference(descriptor)
|
val qualifiedReference = context().getQualifiedReference(descriptor)
|
||||||
val scope = context().getScopeForDescriptor(descriptor)
|
val scope = context().getScopeForDescriptor(descriptor)
|
||||||
val definitionPlace = DefinitionPlace(scope as JsObjectScope, qualifiedReference, staticProperties)
|
val definitionPlace = DefinitionPlace(scope as JsObjectScope, qualifiedReference, staticProperties)
|
||||||
context = context.newDeclaration(descriptor, definitionPlace)
|
val context = context().newDeclaration(descriptor, definitionPlace)
|
||||||
|
|
||||||
invocationArguments += getSuperclassReferences(context)
|
invocationArguments += getSuperclassReferences(context)
|
||||||
|
|
||||||
@@ -96,16 +94,14 @@ class ClassTranslator private constructor(
|
|||||||
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
|
bodyVisitor.traverseContainer(classDeclaration, nonConstructorContext)
|
||||||
delegationTranslator.generateDelegated(properties)
|
delegationTranslator.generateDelegated(properties)
|
||||||
|
|
||||||
var enumFunction: JsFunction? = null
|
|
||||||
if (isEnumClass(descriptor)) {
|
|
||||||
val enumEntries = JsObjectLiteral(bodyVisitor.enumEntryList, true)
|
|
||||||
enumFunction = simpleReturnFunction(nonConstructorContext.getScopeForDescriptor(descriptor), enumEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
translatePrimaryConstructor(context, delegationTranslator)
|
translatePrimaryConstructor(context, delegationTranslator)
|
||||||
classDeclaration.getSecondaryConstructors().forEach { generateSecondaryConstructor(context, it) }
|
classDeclaration.getSecondaryConstructors().forEach { generateSecondaryConstructor(context, it) }
|
||||||
generatedBridgeMethods(properties)
|
generatedBridgeMethods(properties)
|
||||||
enumFunction?.let { invocationArguments += it }
|
|
||||||
|
if (isEnumClass(descriptor)) {
|
||||||
|
val enumEntries = JsObjectLiteral(bodyVisitor.enumEntryList, true)
|
||||||
|
invocationArguments += simpleReturnFunction(nonConstructorContext.getScopeForDescriptor(descriptor), enumEntries)
|
||||||
|
}
|
||||||
|
|
||||||
val dataClassGenerator = JsDataClassGenerator(classDeclaration, context, properties)
|
val dataClassGenerator = JsDataClassGenerator(classDeclaration, context, properties)
|
||||||
|
|
||||||
@@ -118,6 +114,12 @@ class ClassTranslator private constructor(
|
|||||||
dataClassGenerator.generate()
|
dataClassGenerator.generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExpressionVisitor.visitObjectLiteralExpression uses DefinitionPlace of the translated class to generate call to
|
||||||
|
// super constructor. Sometimes, when generating super call, we may translate another anonymous class passed as an
|
||||||
|
// argument. This class will be declared in the DefinitionPlace and put it static properties. See full explanation
|
||||||
|
// in ExpressionVisitor.visitObjectLiteralExpression
|
||||||
|
// TODO: It's a hack, we should think how to generate staticProperties lazily, whenever somebody tries to put
|
||||||
|
// definition into DefinitionPlace.
|
||||||
val hasStaticProperties = !staticProperties.isEmpty() || DescriptorUtils.isAnonymousObject(descriptor)
|
val hasStaticProperties = !staticProperties.isEmpty() || DescriptorUtils.isAnonymousObject(descriptor)
|
||||||
if (!properties.isEmpty() || hasStaticProperties) {
|
if (!properties.isEmpty() || hasStaticProperties) {
|
||||||
if (properties.isEmpty()) {
|
if (properties.isEmpty()) {
|
||||||
@@ -144,7 +146,7 @@ class ClassTranslator private constructor(
|
|||||||
if (isTrait()) return
|
if (isTrait()) return
|
||||||
|
|
||||||
val scope = JsFunctionScope(classContext.scope(), "$descriptor: primary constructor")
|
val scope = JsFunctionScope(classContext.scope(), "$descriptor: primary constructor")
|
||||||
var constructorContext = classContext.innerWithUsageTracker(scope, descriptor)
|
val constructorContext = classContext.innerWithUsageTracker(scope, descriptor)
|
||||||
val initializer = ClassInitializerTranslator(classDeclaration, constructorContext).generateInitializeMethod(delegationTranslator)
|
val initializer = ClassInitializerTranslator(classDeclaration, constructorContext).generateInitializeMethod(delegationTranslator)
|
||||||
invocationArguments += initializer
|
invocationArguments += initializer
|
||||||
|
|
||||||
@@ -157,21 +159,20 @@ class ClassTranslator private constructor(
|
|||||||
val classDescriptor = constructorDescriptor.containingDeclaration
|
val classDescriptor = constructorDescriptor.containingDeclaration
|
||||||
|
|
||||||
val constructorScope = classContext.getScopeForDescriptor(constructorDescriptor)
|
val constructorScope = classContext.getScopeForDescriptor(constructorDescriptor)
|
||||||
var context = classContext.innerWithUsageTracker(constructorScope, constructorDescriptor)
|
|
||||||
|
|
||||||
val thisName = constructorScope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME)
|
val thisName = constructorScope.declareName(Namer.ANOTHER_THIS_PARAMETER_NAME)
|
||||||
val thisNameRef = thisName.makeRef()
|
val thisNameRef = thisName.makeRef()
|
||||||
val receiverDescriptor = classDescriptor.thisAsReceiverParameter
|
val receiverDescriptor = classDescriptor.thisAsReceiverParameter
|
||||||
|
|
||||||
context = context.newDeclaration(constructorDescriptor.containingDeclaration, context.definitionPlace)
|
var context = classContext
|
||||||
context = context.newDeclaration(constructorDescriptor, context.definitionPlace)
|
.innerWithUsageTracker(constructorScope, constructorDescriptor)
|
||||||
context = context.innerContextWithAliased(receiverDescriptor, thisNameRef)
|
.innerContextWithAliased(receiverDescriptor, thisNameRef)
|
||||||
|
|
||||||
val outerName = context.getOuterClassReference(classDescriptor);
|
val outerClassName = context.getOuterClassReference(classDescriptor);
|
||||||
val outerClass = DescriptorUtils.getContainingClass(classDescriptor)
|
val outerClass = DescriptorUtils.getContainingClass(classDescriptor)
|
||||||
if (outerClass != null && outerName != null) {
|
if (outerClassName != null) {
|
||||||
val outerClassRef = outerClass.thisAsReceiverParameter
|
val outerClassReceiver = outerClass!!.thisAsReceiverParameter
|
||||||
context = context.innerContextWithAliased(outerClassRef, outerName.makeRef())
|
context = context.innerContextWithAliased(outerClassReceiver, outerClassName.makeRef())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate constructor body
|
// Translate constructor body
|
||||||
@@ -191,9 +192,9 @@ class ClassTranslator private constructor(
|
|||||||
// Add parameter for outer instance
|
// Add parameter for outer instance
|
||||||
val leadingArgs = mutableListOf<JsExpression>()
|
val leadingArgs = mutableListOf<JsExpression>()
|
||||||
|
|
||||||
if (outerName != null) {
|
if (outerClassName != null) {
|
||||||
constructorFunction.parameters.add(0, JsParameter(outerName))
|
constructorFunction.parameters.add(0, JsParameter(outerClassName))
|
||||||
leadingArgs += outerName.makeRef()
|
leadingArgs += outerClassName.makeRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructorFunction.parameters += JsParameter(thisName)
|
constructorFunction.parameters += JsParameter(thisName)
|
||||||
@@ -212,8 +213,8 @@ class ClassTranslator private constructor(
|
|||||||
if (!delegationCtorInTheSameClass && !classDescriptor.hasPrimaryConstructor()) {
|
if (!delegationCtorInTheSameClass && !classDescriptor.hasPrimaryConstructor()) {
|
||||||
superCallGenerators += {
|
superCallGenerators += {
|
||||||
val usageTracker = context.usageTracker()!!
|
val usageTracker = context.usageTracker()!!
|
||||||
val closure = context.getLocalClassClosure(classDescriptor).orEmpty().map {
|
val closure = context.getClassOrConstructorClosure(classDescriptor).orEmpty().map {
|
||||||
usageTracker.capturedDescriptorToJsName[it]?.makeRef() as? JsExpression ?: JsLiteral.NULL
|
usageTracker.getNameForCapturedDescriptor(it)!!.makeRef()
|
||||||
}
|
}
|
||||||
it += JsInvocation(Namer.getFunctionCallRef(referenceToClass), listOf(thisNameRef) + closure + leadingArgs).makeStmt()
|
it += JsInvocation(Namer.getFunctionCallRef(referenceToClass), listOf(thisNameRef) + closure + leadingArgs).makeStmt()
|
||||||
}
|
}
|
||||||
@@ -242,9 +243,8 @@ class ClassTranslator private constructor(
|
|||||||
private fun emitConstructors(nonConstructorContext: TranslationContext) {
|
private fun emitConstructors(nonConstructorContext: TranslationContext) {
|
||||||
// Build map that maps constructor to all constructors called via this()
|
// Build map that maps constructor to all constructors called via this()
|
||||||
val constructorMap = allConstructors.map { it.descriptor to it }.toMap()
|
val constructorMap = allConstructors.map { it.descriptor to it }.toMap()
|
||||||
val primaryConstructor = this.primaryConstructor
|
|
||||||
|
|
||||||
val thisCalls = allConstructors.map {
|
val thisCalls = secondaryConstructors.map {
|
||||||
val set = mutableSetOf<ConstructorInfo>()
|
val set = mutableSetOf<ConstructorInfo>()
|
||||||
val descriptor = it.descriptor
|
val descriptor = it.descriptor
|
||||||
if (descriptor is ConstructorDescriptor) {
|
if (descriptor is ConstructorDescriptor) {
|
||||||
@@ -256,72 +256,46 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (primaryConstructor != null && primaryConstructor != it) {
|
|
||||||
set += primaryConstructor
|
|
||||||
}
|
|
||||||
Pair(it, set)
|
Pair(it, set)
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
|
||||||
// Sort graph of constructors
|
val sortedConstructors = DFS.topologicalOrder(allConstructors.asIterable()) { thisCalls[it].orEmpty() }.reversed()
|
||||||
val sortedConstructors = mutableListOf<ConstructorInfo>()
|
|
||||||
val visitedConstructors = mutableSetOf<ConstructorInfo>()
|
|
||||||
|
|
||||||
fun sort(constructor: ConstructorInfo) {
|
|
||||||
if (!visitedConstructors.add(constructor)) return
|
|
||||||
|
|
||||||
sortedConstructors += constructor
|
|
||||||
for (thisCall in thisCalls[constructor].orEmpty()) {
|
|
||||||
sort(thisCall)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allConstructors.forEach(::sort)
|
|
||||||
|
|
||||||
// Emit constructors
|
|
||||||
for (constructor in sortedConstructors) {
|
for (constructor in sortedConstructors) {
|
||||||
constructor.superCallGenerator()
|
constructor.superCallGenerator()
|
||||||
|
|
||||||
val nonConstructorUsageTracker = nonConstructorContext.usageTracker()!!
|
val nonConstructorUsageTracker = nonConstructorContext.usageTracker()!!
|
||||||
val usageTracker = constructor.context.usageTracker() ?: continue
|
val usageTracker = constructor.context.usageTracker()!!
|
||||||
|
|
||||||
val nonConstructorCapturedVars = nonConstructorUsageTracker.capturedDescriptors
|
val nonConstructorCapturedVars = nonConstructorUsageTracker.capturedDescriptors
|
||||||
val constructorCapturedVars = usageTracker.capturedDescriptors
|
val constructorCapturedVars = usageTracker.capturedDescriptors
|
||||||
|
|
||||||
val capturedVars = (nonConstructorCapturedVars.asSequence() +
|
val capturedVars = (nonConstructorCapturedVars + constructorCapturedVars).distinct()
|
||||||
constructorCapturedVars.asSequence().filter { it !in nonConstructorCapturedVars }).toList()
|
|
||||||
|
|
||||||
val descriptor = constructor.descriptor
|
val descriptor = constructor.descriptor
|
||||||
nonConstructorContext.putLocalClassClosure(descriptor, capturedVars)
|
nonConstructorContext.putClassOrConstructorClosure(descriptor, capturedVars)
|
||||||
if (descriptor is ClassDescriptor) {
|
|
||||||
if (primaryConstructor != null) {
|
|
||||||
nonConstructorContext.putLocalClassClosure(primaryConstructor.descriptor, capturedVars)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (thisCall in thisCalls[constructor].orEmpty()) {
|
|
||||||
val callUsageTracker = thisCall.context.usageTracker() ?: continue
|
|
||||||
callUsageTracker.capturedDescriptors.forEach { usageTracker.used(it) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addClosureParameters(constructor: ConstructorInfo, nonConstructorContext: TranslationContext,
|
private fun addClosureParameters(constructor: ConstructorInfo, nonConstructorContext: TranslationContext,
|
||||||
dataClassGenerator: JsDataClassGenerator) {
|
dataClassGenerator: JsDataClassGenerator) {
|
||||||
val usageTracker = constructor.context.usageTracker()!!
|
val usageTracker = constructor.context.usageTracker()!!
|
||||||
val capturedVars = context().getLocalClassClosure(constructor.descriptor) ?: return
|
val capturedVars = context().getClassOrConstructorClosure(constructor.descriptor) ?: return
|
||||||
val nonConstructorUsageTracker = nonConstructorContext.usageTracker()!!
|
val nonConstructorUsageTracker = nonConstructorContext.usageTracker()!!
|
||||||
|
|
||||||
val function = constructor.function
|
val function = constructor.function
|
||||||
|
val additionalStatements = mutableListOf<JsStatement>()
|
||||||
for ((i, capturedVar) in capturedVars.withIndex()) {
|
for ((i, capturedVar) in capturedVars.withIndex()) {
|
||||||
val fieldName = nonConstructorUsageTracker.capturedDescriptorToJsName[capturedVar]
|
val fieldName = nonConstructorUsageTracker.capturedDescriptorToJsName[capturedVar]
|
||||||
val name = usageTracker.capturedDescriptorToJsName[capturedVar] ?: fieldName!!
|
val name = usageTracker.capturedDescriptorToJsName[capturedVar] ?: fieldName!!
|
||||||
|
|
||||||
function.parameters.add(i, JsParameter(name))
|
function.parameters.add(i, JsParameter(name))
|
||||||
if (fieldName != null && constructor == primaryConstructor) {
|
if (fieldName != null && constructor == primaryConstructor) {
|
||||||
function.body.statements.add(i, JsAstUtils.defineSimpleProperty(fieldName.ident, name.makeRef()))
|
additionalStatements += JsAstUtils.defineSimpleProperty(fieldName.ident, name.makeRef())
|
||||||
dataClassGenerator.addClosureVariable(fieldName)
|
dataClassGenerator.addClosureVariable(fieldName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function.body.statements.addAll(0, additionalStatements);
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSuperclassReferences(declarationContext: TranslationContext): JsExpression {
|
private fun getSuperclassReferences(declarationContext: TranslationContext): JsExpression {
|
||||||
|
|||||||
+1
-7
@@ -62,7 +62,7 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitClass(@NotNull KtClass declaration, TranslationContext context) {
|
public Void visitClassOrObject(@NotNull KtClassOrObject declaration, TranslationContext context) {
|
||||||
staticResult.addAll(ClassTranslator.translate(declaration, context).getProperties());
|
staticResult.addAll(ClassTranslator.translate(declaration, context).getProperties());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -82,12 +82,6 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visitObjectDeclaration(@NotNull KtObjectDeclaration declaration, TranslationContext context) {
|
|
||||||
staticResult.addAll(ClassTranslator.translate(declaration, context).getProperties());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitNamedFunction(@NotNull KtNamedFunction expression, TranslationContext context) {
|
public Void visitNamedFunction(@NotNull KtNamedFunction expression, TranslationContext context) {
|
||||||
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
||||||
|
|||||||
+2
-14
@@ -26,10 +26,7 @@ import org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateIn
|
|||||||
import org.jetbrains.kotlin.js.translate.initializer.InitializerVisitor
|
import org.jetbrains.kotlin.js.translate.initializer.InitializerVisitor
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptor
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptor
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
|
||||||
|
|
||||||
class FileDeclarationVisitor(
|
class FileDeclarationVisitor(
|
||||||
val context: TranslationContext,
|
val context: TranslationContext,
|
||||||
@@ -49,20 +46,11 @@ class FileDeclarationVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClass(declaration: KtClass, context: TranslationContext?): Void? {
|
override fun visitClassOrObject(declaration: KtClassOrObject, context: TranslationContext?): Void? {
|
||||||
result += ClassTranslator.translate(declaration, context!!).properties
|
result += ClassTranslator.translate(declaration, context!!).properties
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitObjectDeclaration(declaration: KtObjectDeclaration, context: TranslationContext?): Void? {
|
|
||||||
context!!
|
|
||||||
|
|
||||||
// TODO: avoid duplication with superclass
|
|
||||||
result += ClassTranslator.translate(declaration, context).properties
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitProperty(expression: KtProperty, context: TranslationContext?): Void? {
|
override fun visitProperty(expression: KtProperty, context: TranslationContext?): Void? {
|
||||||
context!! // hack
|
context!! // hack
|
||||||
|
|
||||||
|
|||||||
+13
-10
@@ -522,15 +522,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) {
|
public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) {
|
||||||
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), expression.getObjectDeclaration());
|
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), expression.getObjectDeclaration());
|
||||||
JsScope scope = context.getScopeForDescriptor(descriptor);
|
ClassTranslator.TranslationResult result = translateClassOrObject(expression.getObjectDeclaration(), descriptor, context);
|
||||||
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
|
|
||||||
|
|
||||||
ClassTranslator.TranslationResult result = ClassTranslator.translate(expression.getObjectDeclaration(), classContext);
|
|
||||||
List<JsPropertyInitializer> properties = result.getProperties();
|
List<JsPropertyInitializer> properties = result.getProperties();
|
||||||
context.getDefinitionPlace().getProperties().addAll(properties);
|
context.getDefinitionPlace().getProperties().addAll(properties);
|
||||||
|
|
||||||
JsExpression constructor = context.getQualifiedReference(descriptor);
|
JsExpression constructor = context.getQualifiedReference(descriptor);
|
||||||
List<DeclarationDescriptor> closure = context.getLocalClassClosure(descriptor);
|
List<DeclarationDescriptor> closure = context.getClassOrConstructorClosure(descriptor);
|
||||||
List<JsExpression> closureArgs = new ArrayList<JsExpression>();
|
List<JsExpression> closureArgs = new ArrayList<JsExpression>();
|
||||||
if (closure != null) {
|
if (closure != null) {
|
||||||
for (DeclarationDescriptor capturedValue : closure) {
|
for (DeclarationDescriptor capturedValue : closure) {
|
||||||
@@ -601,11 +598,17 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
@Override
|
@Override
|
||||||
public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) {
|
public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) {
|
||||||
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass);
|
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass);
|
||||||
JsScope scope = context.getScopeForDescriptor(descriptor);
|
context.getDefinitionPlace().getProperties().addAll(translateClassOrObject(klass, descriptor, context).getProperties());
|
||||||
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
|
|
||||||
|
|
||||||
context.getDefinitionPlace().getProperties().addAll(ClassTranslator.translate(klass, classContext).getProperties());
|
|
||||||
|
|
||||||
return JsEmpty.INSTANCE;
|
return JsEmpty.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ClassTranslator.TranslationResult translateClassOrObject(
|
||||||
|
@NotNull KtClassOrObject declaration,
|
||||||
|
@NotNull ClassDescriptor descriptor,
|
||||||
|
@NotNull TranslationContext context
|
||||||
|
) {
|
||||||
|
JsScope scope = context.getScopeForDescriptor(descriptor);
|
||||||
|
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
|
||||||
|
return ClassTranslator.translate(declaration, classContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.js.translate.context.UsageTracker;
|
|||||||
import org.jetbrains.kotlin.js.translate.declaration.DelegationTranslator;
|
import org.jetbrains.kotlin.js.translate.declaration.DelegationTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator;
|
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.AstUtilsKt;
|
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.AstUtilsKt;
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
@@ -149,7 +148,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hasAncestorClass(bindingContext(), classDeclaration)) {
|
if (hasAncestorClass(bindingContext(), classDeclaration)) {
|
||||||
ResolvedCall<FunctionDescriptor> superCall = BindingUtils.getSuperCall(bindingContext(), classDeclaration);
|
ResolvedCall<FunctionDescriptor> superCall = getSuperCall(bindingContext(), classDeclaration);
|
||||||
if (superCall == null) return;
|
if (superCall == null) return;
|
||||||
|
|
||||||
if (classDeclaration instanceof KtEnumEntry) {
|
if (classDeclaration instanceof KtEnumEntry) {
|
||||||
@@ -163,9 +162,11 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
ConstructorDescriptor superDescriptor = (ConstructorDescriptor) superCall.getResultingDescriptor();
|
ConstructorDescriptor superDescriptor = (ConstructorDescriptor) superCall.getResultingDescriptor();
|
||||||
|
|
||||||
List<DeclarationDescriptor> superclassClosure = context.getLocalClassClosure(superDescriptor);
|
List<DeclarationDescriptor> superclassClosure = context.getClassOrConstructorClosure(superDescriptor);
|
||||||
UsageTracker tracker = context.usageTracker();
|
if (superclassClosure != null) {
|
||||||
if (superclassClosure != null && tracker != null) {
|
UsageTracker tracker = context.usageTracker();
|
||||||
|
assert tracker != null : "Closure exists, therefore UsageTracker must exist too. Translating constructor of " +
|
||||||
|
descriptor;
|
||||||
for (DeclarationDescriptor capturedValue : superclassClosure) {
|
for (DeclarationDescriptor capturedValue : superclassClosure) {
|
||||||
tracker.used(capturedValue);
|
tracker.used(capturedValue);
|
||||||
arguments.add(tracker.getCapturedDescriptorToJsName().get(capturedValue).makeRef());
|
arguments.add(tracker.getCapturedDescriptorToJsName().get(capturedValue).makeRef());
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ public class ManglingUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Collections.reverse(parts);
|
Collections.reverse(parts);
|
||||||
return StringUtil.join(parts, "$") + "$";
|
String result = StringUtil.join(parts, "$");
|
||||||
|
return !result.isEmpty() ? result + "$" : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
fun test(): Int {
|
||||||
|
open class B(open val x: Int) {
|
||||||
|
inner class C(override val x: Int) : B(x * 10) {
|
||||||
|
inner class D() {
|
||||||
|
var baz: () -> Int = { 0 }
|
||||||
|
constructor(b: Boolean) : this() {
|
||||||
|
baz = { x + this@B.x }
|
||||||
|
}
|
||||||
|
fun bar() = { x + this@B.x }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B(3).C(2).D().bar()() + B(5).C(4).D(true).baz()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(2345, A().test())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
fun test(): Int {
|
||||||
|
open class B(open val x: Int) {
|
||||||
|
inner class C(override val x: Int) : B(x * 10) {
|
||||||
|
inner class D() {
|
||||||
|
fun baz() = bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun D.bar() = { x + this@B.x }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return B(3).C(2).D().baz()()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(23, A().test())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun test() = 23
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : A> T.foo(): Int {
|
||||||
|
class B {
|
||||||
|
fun foo() = test()
|
||||||
|
}
|
||||||
|
return B().foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(23, A().foo())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user