KT-11030 Refactoring code to properly implement secondary constructors in local classes
This commit is contained in:
@@ -28,7 +28,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.js.config.Config;
|
||||
import org.jetbrains.kotlin.js.config.EcmaVersion;
|
||||
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig;
|
||||
import org.jetbrains.kotlin.js.translate.context.generator.Generator;
|
||||
import org.jetbrains.kotlin.js.translate.context.generator.Rule;
|
||||
@@ -39,8 +38,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -106,9 +103,6 @@ public final class StaticContext {
|
||||
@NotNull
|
||||
private final Config config;
|
||||
|
||||
@NotNull
|
||||
private final EcmaVersion ecmaVersion;
|
||||
|
||||
//TODO: too many parameters in constructor
|
||||
private StaticContext(@NotNull JsProgram program, @NotNull BindingTrace bindingTrace,
|
||||
@NotNull Namer namer, @NotNull Intrinsics intrinsics,
|
||||
@@ -120,14 +114,9 @@ public final class StaticContext {
|
||||
this.rootScope = rootScope;
|
||||
this.standardClasses = standardClasses;
|
||||
this.config = config;
|
||||
this.ecmaVersion = config.getTarget();
|
||||
this.reflectionTypes = new ReflectionTypes(moduleDescriptor);
|
||||
}
|
||||
|
||||
public boolean isEcma5() {
|
||||
return ecmaVersion == EcmaVersion.v5;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsProgram getProgram() {
|
||||
return program;
|
||||
@@ -272,21 +261,15 @@ public final class StaticContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> parts = new ArrayList<String>();
|
||||
String suggested = getSuggestedName(descriptor);
|
||||
|
||||
do {
|
||||
parts.add(descriptor.getName().isSpecial() ? "f" : descriptor.getName().getIdentifier());
|
||||
descriptor = descriptor.getContainingDeclaration();
|
||||
} while (descriptor != null && !(descriptor instanceof ClassOrPackageFragmentDescriptor));
|
||||
assert descriptor != null;
|
||||
|
||||
Collections.reverse(parts);
|
||||
StringBuilder suggestedName = new StringBuilder(parts.get(0));
|
||||
for (int i = 1; i < parts.size(); ++i) {
|
||||
suggestedName.append('$').append(parts.get(i));
|
||||
}
|
||||
|
||||
JsScope scope = getScopeForDescriptor(descriptor);
|
||||
return scope.declareFreshName(suggestedName.toString());
|
||||
return scope.declareFreshName(suggested);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class Generator<V> {
|
||||
@NotNull
|
||||
private final List<Rule<V>> rules = Lists.newArrayList();
|
||||
|
||||
public void addRule(@NotNull Rule<V> rule) {
|
||||
protected final void addRule(@NotNull Rule<V> rule) {
|
||||
rules.add(rule);
|
||||
}
|
||||
|
||||
|
||||
+46
-26
@@ -295,6 +295,7 @@ class ClassTranslator private constructor(
|
||||
}
|
||||
|
||||
private fun generateSecondaryConstructor(constructor: KtSecondaryConstructor, context: TranslationContext): JsPropertyInitializer {
|
||||
// Prepare
|
||||
val constructorDescriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), constructor) as ConstructorDescriptor
|
||||
val classDescriptor = constructorDescriptor.containingDeclaration
|
||||
|
||||
@@ -309,6 +310,9 @@ class ClassTranslator private constructor(
|
||||
translationContext = translationContext.newDeclaration(constructorDescriptor, translationContext.definitionPlace)
|
||||
translationContext = translationContext.innerContextWithAliased(receiverDescriptor, thisNameRef)
|
||||
|
||||
val closure = translationContext.getLocalClassClosure(classDescriptor)
|
||||
val usageTracker = context.usageTracker()
|
||||
|
||||
val outerName = translationContext.getOuterClassReference(classDescriptor);
|
||||
val outerClass = DescriptorUtils.getContainingClass(classDescriptor)
|
||||
if (outerClass != null && outerName != null) {
|
||||
@@ -316,43 +320,59 @@ class ClassTranslator private constructor(
|
||||
translationContext = translationContext.innerContextWithAliased(outerClassRef, outerName.makeRef())
|
||||
}
|
||||
|
||||
// Translate constructor body
|
||||
val constructorInitializer = FunctionTranslator.newInstance(constructor, translationContext).translateAsMethod()
|
||||
val constructorFunction = constructorInitializer.valueExpr as JsFunction
|
||||
|
||||
val leadingArgs = mutableListOf<JsExpression>()
|
||||
|
||||
if (outerName != null) {
|
||||
constructorFunction.parameters.add(0, JsParameter(outerName))
|
||||
leadingArgs.add(outerName.makeRef())
|
||||
}
|
||||
constructorFunction.parameters.add(JsParameter(thisName))
|
||||
// Translate super/this call
|
||||
val forAddToBeginning = arrayListOf<JsStatement>()
|
||||
|
||||
val referenceToClass = translationContext.getQualifiedReference(classDescriptor)
|
||||
|
||||
val forAddToBeginning: List<JsStatement> =
|
||||
with(arrayListOf<JsStatement>()) {
|
||||
addAll(FunctionBodyTranslator.setDefaultValueForArguments(constructorDescriptor, translationContext))
|
||||
forAddToBeginning.addAll(FunctionBodyTranslator.setDefaultValueForArguments(constructorDescriptor, translationContext))
|
||||
|
||||
val createInstance = Namer.createObjectWithPrototypeFrom(referenceToClass)
|
||||
val instanceVar = JsAstUtils.assignment(thisNameRef, JsAstUtils.or(thisNameRef, createInstance)).makeStmt()
|
||||
add(instanceVar)
|
||||
val createInstance = Namer.createObjectWithPrototypeFrom(referenceToClass)
|
||||
val instanceVar = JsAstUtils.assignment(thisNameRef, JsAstUtils.or(thisNameRef, createInstance)).makeStmt()
|
||||
forAddToBeginning.add(instanceVar)
|
||||
|
||||
val resolvedCall = BindingContextUtils.getDelegationConstructorCall(translationContext.bindingContext(),
|
||||
constructorDescriptor)
|
||||
val delegationClassDescriptor = resolvedCall?.resultingDescriptor?.containingDeclaration
|
||||
val resolvedCall = BindingContextUtils.getDelegationConstructorCall(translationContext.bindingContext(),
|
||||
constructorDescriptor)
|
||||
val delegationClassDescriptor = resolvedCall?.resultingDescriptor?.containingDeclaration
|
||||
val superCall = if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) {
|
||||
CallTranslator.translate(translationContext, resolvedCall)
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
|
||||
if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) {
|
||||
val superCall = CallTranslator.translate(translationContext, resolvedCall)
|
||||
add(superCall.toInvocationWith(leadingArgs, thisNameRef).makeStmt())
|
||||
}
|
||||
// Add parameters for closure and outer instance
|
||||
val leadingArgs = mutableListOf<JsExpression>()
|
||||
|
||||
val delegationCtorInTheSameClass = delegationClassDescriptor == classDescriptor
|
||||
if (!delegationCtorInTheSameClass && !classDescriptor.hasPrimaryConstructor()) {
|
||||
add(JsInvocation(Namer.getFunctionCallRef(referenceToClass), listOf(thisNameRef) + leadingArgs).makeStmt())
|
||||
}
|
||||
var additionalParameterIndex = 0
|
||||
if (closure != null && usageTracker != null) {
|
||||
for (capturedValue in closure) {
|
||||
val capturedName = usageTracker.capturedDescriptorToJsName[capturedValue]!!
|
||||
constructorFunction.parameters.add(additionalParameterIndex++, JsParameter(capturedName))
|
||||
leadingArgs.add(capturedName.makeRef())
|
||||
}
|
||||
}
|
||||
|
||||
this
|
||||
}
|
||||
if (outerName != null) {
|
||||
constructorFunction.parameters.add(additionalParameterIndex, JsParameter(outerName))
|
||||
leadingArgs.add(outerName.makeRef())
|
||||
}
|
||||
|
||||
constructorFunction.parameters.add(JsParameter(thisName))
|
||||
|
||||
// Insert super/this call to beginning of function
|
||||
if (superCall != null) {
|
||||
forAddToBeginning.add(superCall.toInvocationWith(leadingArgs, thisNameRef).makeStmt())
|
||||
}
|
||||
|
||||
val delegationCtorInTheSameClass = delegationClassDescriptor == classDescriptor
|
||||
if (!delegationCtorInTheSameClass && !classDescriptor.hasPrimaryConstructor()) {
|
||||
forAddToBeginning.add(JsInvocation(Namer.getFunctionCallRef(referenceToClass), listOf(thisNameRef) + leadingArgs).makeStmt())
|
||||
}
|
||||
|
||||
with(constructorFunction.body.statements) {
|
||||
addAll(0, forAddToBeginning)
|
||||
|
||||
+2
-3
@@ -572,9 +572,8 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
JsObjectScope scope = new JsObjectScope(context.scope(), descriptor.toString(), "");
|
||||
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
|
||||
|
||||
JsInvocation jsClass = ClassTranslator.generateClassCreation(klass, classContext);
|
||||
context.getDefinitionPlace().getProperties().addAll(ClassTranslator.Companion.translate(klass, classContext));
|
||||
|
||||
JsName name = context.getNameForDescriptor(descriptor);
|
||||
return context.define(name, jsClass);
|
||||
return JsEmpty.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
|
||||
public class ManglingUtils {
|
||||
private ManglingUtils() {}
|
||||
|
||||
public static final Comparator<CallableDescriptor> CALLABLE_COMPARATOR = new CallableComparator();
|
||||
private static final Comparator<CallableDescriptor> CALLABLE_COMPARATOR = new CallableComparator();
|
||||
|
||||
@NotNull
|
||||
public static String getMangledName(@NotNull PropertyDescriptor descriptor, @NotNull String suggestedName) {
|
||||
@@ -49,7 +49,7 @@ public class ManglingUtils {
|
||||
|
||||
@NotNull
|
||||
public static String getSuggestedName(@NotNull DeclarationDescriptor descriptor) {
|
||||
String suggestedName = descriptor.getName().asString();
|
||||
String suggestedName = descriptor.getName().isSpecial() ? "f" : descriptor.getName().getIdentifier();
|
||||
|
||||
if (descriptor instanceof FunctionDescriptor ||
|
||||
descriptor instanceof PropertyDescriptor && DescriptorUtils.isExtension((PropertyDescriptor) descriptor)
|
||||
@@ -57,9 +57,37 @@ public class ManglingUtils {
|
||||
suggestedName = getMangledName((CallableMemberDescriptor) descriptor);
|
||||
}
|
||||
|
||||
ClassDescriptor localClass = null;
|
||||
if (descriptor instanceof ConstructorDescriptor) {
|
||||
ConstructorDescriptor constructor = (ConstructorDescriptor) descriptor;
|
||||
localClass = constructor.getContainingDeclaration();
|
||||
}
|
||||
else if (descriptor instanceof ClassDescriptor) {
|
||||
localClass = (ClassDescriptor) descriptor;
|
||||
}
|
||||
|
||||
if (DescriptorUtils.isDescriptorWithLocalVisibility(localClass)) {
|
||||
suggestedName = getSuggestedLocalPrefix(localClass) + suggestedName;
|
||||
}
|
||||
|
||||
return suggestedName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getSuggestedLocalPrefix(@NotNull DeclarationDescriptor descriptor) {
|
||||
List<String> parts = new ArrayList<String>();
|
||||
while (true) {
|
||||
descriptor = descriptor.getContainingDeclaration();
|
||||
if (descriptor == null || descriptor instanceof ClassOrPackageFragmentDescriptor) {
|
||||
break;
|
||||
}
|
||||
parts.add(descriptor.getName().isSpecial() ? "f" : descriptor.getName().getIdentifier());
|
||||
}
|
||||
|
||||
Collections.reverse(parts);
|
||||
return StringUtil.join(parts, "$") + "$";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getMangledName(@NotNull CallableMemberDescriptor descriptor) {
|
||||
if (needsStableMangling(descriptor)) {
|
||||
@@ -142,7 +170,7 @@ public class ManglingUtils {
|
||||
@NotNull
|
||||
private static String getSuggestedName(@NotNull CallableDescriptor descriptor) {
|
||||
if (descriptor instanceof ConstructorDescriptor && !((ConstructorDescriptor) descriptor).isPrimary()) {
|
||||
return descriptor.getContainingDeclaration().getName().asString();
|
||||
return descriptor.getContainingDeclaration().getName().asString() + "_init";
|
||||
}
|
||||
else {
|
||||
return descriptor.getName().asString();
|
||||
|
||||
Reference in New Issue
Block a user