JS: refactor JsScope, JsName and related things, since it's became unnecessary to track scopes and declaration order of temporary JsName's

This commit is contained in:
Alexey Andreev
2017-02-10 20:04:41 +03:00
parent 9530ce6c26
commit 9e0a06a4aa
28 changed files with 68 additions and 114 deletions
@@ -15,7 +15,7 @@ public class JsCatchScope extends JsDeclarationScope {
public JsCatchScope(JsScope parent, @NotNull String ident) { public JsCatchScope(JsScope parent, @NotNull String ident) {
super(parent, "Catch scope", true); super(parent, "Catch scope", true);
name = new JsName(this, ident, false); name = new JsName(ident, false);
} }
@Override @Override
@@ -12,10 +12,6 @@ import org.jetbrains.annotations.NotNull;
* An abstract base class for named JavaScript objects. * An abstract base class for named JavaScript objects.
*/ */
public class JsName extends HasMetadata implements Symbol { public class JsName extends HasMetadata implements Symbol {
private static int ordinalGenerator;
private final JsScope enclosing;
private final int ordinal;
@NotNull @NotNull
private final String ident; private final String ident;
@@ -24,19 +20,9 @@ public class JsName extends HasMetadata implements Symbol {
/** /**
* @param ident the unmangled ident to use for this name * @param ident the unmangled ident to use for this name
*/ */
JsName(JsScope enclosing, @NotNull String ident, boolean temporary) { JsName(@NotNull String ident, boolean temporary) {
this.enclosing = enclosing;
this.ident = ident; this.ident = ident;
this.temporary = temporary; this.temporary = temporary;
ordinal = temporary ? ordinalGenerator++ : 0;
}
public int getOrdinal() {
return ordinal;
}
public JsScope getEnclosing() {
return enclosing;
} }
public boolean isTemporary() { public boolean isTemporary() {
@@ -4,9 +4,9 @@
package org.jetbrains.kotlin.js.backend.ast; package org.jetbrains.kotlin.js.backend.ast;
import org.jetbrains.kotlin.js.util.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.util.Maps;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -43,8 +43,6 @@ public abstract class JsScope {
@NotNull @NotNull
private final String description; private final String description;
private Map<String, JsName> names = Collections.emptyMap(); private Map<String, JsName> names = Collections.emptyMap();
private Map<JsName, Object> temporaryNames;
private Set<JsName> readonlyTemporaryNames = null;
private final JsScope parent; private final JsScope parent;
private static final Pattern FRESH_NAME_SUFFIX = Pattern.compile("[\\$_]\\d+$"); private static final Pattern FRESH_NAME_SUFFIX = Pattern.compile("[\\$_]\\d+$");
@@ -59,16 +57,6 @@ public abstract class JsScope {
parent = null; parent = null;
} }
public Set<JsName> getTemporaryNames() {
if (temporaryNames == null) {
return Collections.emptySet();
}
if (readonlyTemporaryNames == null) {
readonlyTemporaryNames = Collections.unmodifiableSet(temporaryNames.keySet());
}
return readonlyTemporaryNames;
}
@NotNull @NotNull
public JsScope innerObjectScope(@NotNull String scopeName) { public JsScope innerObjectScope(@NotNull String scopeName) {
return new JsObjectScope(this, scopeName); return new JsObjectScope(this, scopeName);
@@ -103,14 +91,9 @@ public abstract class JsScope {
} }
@NotNull @NotNull
public JsName declareTemporaryName(@NotNull String suggestedName) { public static JsName declareTemporaryName(@NotNull String suggestedName) {
assert !suggestedName.isEmpty(); assert !suggestedName.isEmpty();
JsName name = new JsName(this, suggestedName, true); return new JsName(suggestedName, true);
if (temporaryNames == null) {
temporaryNames = new WeakHashMap<JsName, Object>();
}
temporaryNames.put(name, this);
return name;
} }
/** /**
@@ -120,7 +103,7 @@ public abstract class JsScope {
* Future declarations of variables might however clash with the temporary. * Future declarations of variables might however clash with the temporary.
*/ */
@NotNull @NotNull
public JsName declareTemporary() { public static JsName declareTemporary() {
return declareTemporaryName("tmp$"); return declareTemporaryName("tmp$");
} }
@@ -171,7 +154,7 @@ public abstract class JsScope {
} }
public void copyOwnNames(JsScope other) { public void copyOwnNames(JsScope other) {
names = new HashMap<String, JsName>(names); names = new HashMap<>(names);
names.putAll(other.names); names.putAll(other.names);
} }
@@ -182,7 +165,7 @@ public abstract class JsScope {
@NotNull @NotNull
protected JsName doCreateName(@NotNull String ident) { protected JsName doCreateName(@NotNull String ident) {
JsName name = new JsName(this, ident, false); JsName name = new JsName(ident, false);
names = Maps.put(names, ident, name); names = Maps.put(names, ident, name);
return name; return name;
} }
@@ -21,7 +21,7 @@ import java.util.*
class JsObjectScope(parent: JsScope, description: String) : JsScope(parent, description) class JsObjectScope(parent: JsScope, description: String) : JsScope(parent, description)
object JsDynamicScope : JsScope(null, "Scope for dynamic declarations") { object JsDynamicScope : JsScope(null, "Scope for dynamic declarations") {
override fun doCreateName(name: String) = JsName(this, name, false) override fun doCreateName(name: String) = JsName(name, false)
} }
open class JsFunctionScope(parent: JsScope, description: String) : JsDeclarationScope(parent, description) { open class JsFunctionScope(parent: JsScope, description: String) : JsDeclarationScope(parent, description) {
@@ -61,7 +61,7 @@ open class JsDeclarationScope(parent: JsScope, description: String, useParentSco
else -> ident else -> ident
} }
labelName = JsName(this@JsDeclarationScope, freshIdent, false) labelName = JsName(freshIdent, false)
} }
override fun findOwnName(name: String): JsName? = override fun findOwnName(name: String): JsName? =
@@ -130,9 +130,6 @@ class DelegatingJsFunctionScopeWithTemporaryParent(
override fun declareFreshName(suggestedName: String): JsName = override fun declareFreshName(suggestedName: String): JsName =
delegatingScope.declareFreshName(suggestedName) delegatingScope.declareFreshName(suggestedName)
override fun declareTemporary(): JsName =
delegatingScope.declareTemporary()
override fun enterLabel(label: String): JsName = override fun enterLabel(label: String): JsName =
delegatingScope.enterLabel(label) delegatingScope.enterLabel(label)
@@ -365,7 +365,7 @@ internal class ExpressionDecomposer private constructor(
} }
private inner class Temporary(val value: JsExpression? = null) { private inner class Temporary(val value: JsExpression? = null) {
val name: JsName = scope.declareTemporary() val name: JsName = JsScope.declareTemporary()
val variable: JsVars = newVar(name, value).apply { val variable: JsVars = newVar(name, value).apply {
synthetic = true synthetic = true
@@ -50,9 +50,6 @@ class NamingContext(
fun getFreshName(candidate: String): JsName = scope.declareFreshName(candidate) fun getFreshName(candidate: String): JsName = scope.declareFreshName(candidate)
fun getTemporaryName(candidate: String): JsName = scope.declareTemporaryName(candidate)
fun newVar(name: JsName, value: JsExpression? = null) { fun newVar(name: JsName, value: JsExpression? = null) {
val vars = JsAstUtils.newVar(name, value) val vars = JsAstUtils.newVar(name, value)
vars.synthetic = true vars.synthetic = true
@@ -32,7 +32,7 @@ fun aliasArgumentsIfNeeded(
for ((arg, param) in arguments.zip(parameters)) { for ((arg, param) in arguments.zip(parameters)) {
val paramName = param.name val paramName = param.name
val replacement = context.getTemporaryName(paramName.ident).apply { val replacement = JsScope.declareTemporaryName(paramName.ident).apply {
staticRef = arg staticRef = arg
context.newVar(this, arg.deepCopy()) context.newVar(this, arg.deepCopy())
}.makeRef() }.makeRef()
@@ -43,7 +43,7 @@ fun aliasArgumentsIfNeeded(
val defaultParams = parameters.subList(arguments.size, parameters.size) val defaultParams = parameters.subList(arguments.size, parameters.size)
for (defaultParam in defaultParams) { for (defaultParam in defaultParams) {
val paramName = defaultParam.name val paramName = defaultParam.name
val freshName = context.getTemporaryName(paramName.ident) val freshName = JsScope.declareTemporaryName(paramName.ident)
context.newVar(freshName) context.newVar(freshName)
context.replaceName(paramName, freshName.makeRef()) context.replaceName(paramName, freshName.makeRef())
@@ -58,7 +58,7 @@ fun renameLocalNames(
function: JsFunction function: JsFunction
) { ) {
for (name in collectDefinedNames(function.body)) { for (name in collectDefinedNames(function.body)) {
val temporaryName = context.getTemporaryName(name.ident).apply { staticRef = name.staticRef } val temporaryName = JsScope.declareTemporaryName(name.ident).apply { staticRef = name.staticRef }
context.replaceName(name, temporaryName.makeRef()) context.replaceName(name, temporaryName.makeRef())
} }
} }
@@ -68,7 +68,7 @@ class NameResolutionTest {
if (node is HasName) { if (node is HasName) {
node.name = node.name?.let { name -> node.name = node.name?.let { name ->
if (name.ident.startsWith("$")) { if (name.ident.startsWith("$")) {
cache.getOrPut(name) { JsDynamicScope.declareTemporaryName("x") } cache.getOrPut(name) { JsScope.declareTemporaryName("x") }
} }
else { else {
name name
@@ -110,7 +110,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")
val valueName = function.scope.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()
function function
@@ -130,7 +130,7 @@ internal class DeclarationExporter(val context: StaticContext) {
} }
var name = localPackageNames[packageName] var name = localPackageNames[packageName]
if (name == null) { if (name == null) {
name = context.fragment.scope.declareTemporaryName("package$" + packageName.shortName().asString()) name = JsScope.declareTemporaryName("package$" + packageName.shortName().asString())
localPackageNames.put(packageName, name) localPackageNames.put(packageName, name)
val parentRef = getLocalPackageReference(packageName.parent()) val parentRef = getLocalPackageReference(packageName.parent())
@@ -62,7 +62,7 @@ public final class DynamicContext {
currentBlock.getStatements().add(vars); currentBlock.getStatements().add(vars);
} }
JsName temporaryName = currentScope.declareTemporary(); JsName temporaryName = JsScope.declareTemporary();
JsVar var = new JsVar(temporaryName, null); JsVar var = new JsVar(temporaryName, null);
MetadataProperties.setSynthetic(var, true); MetadataProperties.setSynthetic(var, true);
vars.add(var); vars.add(var);
@@ -396,7 +396,7 @@ public final class StaticContext {
if (suggested.getDescriptor() instanceof LocalVariableDescriptor || if (suggested.getDescriptor() instanceof LocalVariableDescriptor ||
suggested.getDescriptor() instanceof ValueParameterDescriptor suggested.getDescriptor() instanceof ValueParameterDescriptor
) { ) {
name = scope.declareTemporaryName(baseName); name = JsScope.declareTemporaryName(baseName);
} }
else { else {
if (!DescriptorUtils.isDescriptorWithLocalVisibility(suggested.getDescriptor())) { if (!DescriptorUtils.isDescriptorWithLocalVisibility(suggested.getDescriptor())) {
@@ -461,7 +461,7 @@ public final class StaticContext {
// since local scope inherited from global scope. // since local scope inherited from global scope.
// TODO: remove prefix when problem with scopes is solved // TODO: remove prefix when problem with scopes is solved
JsName result = fragment.getScope().declareTemporaryName(suggestedName); JsName result = JsScope.declareTemporaryName(suggestedName);
MetadataProperties.setImported(result, true); MetadataProperties.setImported(result, true);
fragment.getImports().put(tag, declaration); fragment.getImports().put(tag, declaration);
return result; return result;
@@ -477,7 +477,7 @@ public final class StaticContext {
name = importDeclaration(suggestedName, tag, getQualifiedReference(descriptor)); name = importDeclaration(suggestedName, tag, getQualifiedReference(descriptor));
} }
else { else {
name = fragment.getScope().declareTemporaryName(suggestedName); name = JsScope.declareTemporaryName(suggestedName);
} }
if (tag != null) { if (tag != null) {
fragment.getNameBindings().add(new JsNameBinding(tag, name)); fragment.getNameBindings().add(new JsNameBinding(tag, name));
@@ -674,7 +674,7 @@ public final class StaticContext {
JsImportedModule module = importedModules.get(key); JsImportedModule module = importedModules.get(key);
if (module == null) { if (module == null) {
JsName internalName = rootScope.declareTemporaryName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(baseName)); JsName internalName = JsScope.declareTemporaryName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(baseName));
module = createImportedModule(key, baseName, internalName, plainName != null ? pureFqn(plainName, null) : null); module = createImportedModule(key, baseName, internalName, plainName != null ? pureFqn(plainName, null) : null);
} }
return module; return module;
@@ -158,13 +158,13 @@ public class TranslationContext {
@NotNull @NotNull
public TranslationContext newFunctionBodyWithUsageTracker(@NotNull JsFunction fun, @NotNull MemberDescriptor descriptor) { public TranslationContext newFunctionBodyWithUsageTracker(@NotNull JsFunction fun, @NotNull MemberDescriptor descriptor) {
DynamicContext dynamicContext = DynamicContext.newContext(fun.getScope(), fun.getBody()); DynamicContext dynamicContext = DynamicContext.newContext(fun.getScope(), fun.getBody());
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, fun.getScope()); UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor);
return new TranslationContext(this, this.staticContext, dynamicContext, this.aliasingContext.inner(), usageTracker, descriptor); return new TranslationContext(this, this.staticContext, dynamicContext, this.aliasingContext.inner(), usageTracker, descriptor);
} }
@NotNull @NotNull
public TranslationContext innerWithUsageTracker(@NotNull JsScope scope, @NotNull MemberDescriptor descriptor) { public TranslationContext innerWithUsageTracker(@NotNull MemberDescriptor descriptor) {
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, scope); UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor);
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext.inner(), usageTracker, descriptor); return new TranslationContext(this, staticContext, dynamicContext, aliasingContext.inner(), usageTracker, descriptor);
} }
@@ -652,11 +652,6 @@ public class TranslationContext {
staticContext.getTopLevelStatements().add(statement); staticContext.getTopLevelStatements().add(statement);
} }
@NotNull
public JsName createGlobalName(@NotNull String suggestedName) {
return staticContext.getFragment().getScope().declareTemporaryName(suggestedName);
}
@NotNull @NotNull
public JsFunction createRootScopedFunction(@NotNull DeclarationDescriptor descriptor) { public JsFunction createRootScopedFunction(@NotNull DeclarationDescriptor descriptor) {
return createRootScopedFunction(descriptor.toString()); return createRootScopedFunction(descriptor.toString());
@@ -16,9 +16,9 @@
package org.jetbrains.kotlin.js.translate.context package org.jetbrains.kotlin.js.translate.context
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.backend.ast.JsName import org.jetbrains.kotlin.js.backend.ast.JsName
import org.jetbrains.kotlin.js.backend.ast.JsScope import org.jetbrains.kotlin.js.backend.ast.JsScope
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
import org.jetbrains.kotlin.js.descriptorUtils.isCoroutineLambda import org.jetbrains.kotlin.js.descriptorUtils.isCoroutineLambda
import org.jetbrains.kotlin.js.naming.NameSuggestion import org.jetbrains.kotlin.js.naming.NameSuggestion
@@ -30,8 +30,7 @@ private val CAPTURED_RECEIVER_NAME_PREFIX : String = "this$"
class UsageTracker( class UsageTracker(
private val parent: UsageTracker?, private val parent: UsageTracker?,
val containingDescriptor: MemberDescriptor, val containingDescriptor: MemberDescriptor
private val scope: JsScope
) { ) {
private val captured = linkedMapOf<DeclarationDescriptor, JsName>() private val captured = linkedMapOf<DeclarationDescriptor, JsName>()
@@ -172,7 +171,7 @@ class UsageTracker(
} }
} }
return scope.declareTemporaryName(suggestedName).apply { descriptor = this@getJsNameForCapturedDescriptor } return JsScope.declareTemporaryName(suggestedName).apply { descriptor = this@getJsNameForCapturedDescriptor }
} }
} }
@@ -67,7 +67,6 @@ class ClassTranslator private constructor(
private fun isTrait(): Boolean = descriptor.kind == ClassKind.INTERFACE private fun isTrait(): Boolean = descriptor.kind == ClassKind.INTERFACE
private fun translate() { private fun translate() {
val scope = context().getScopeForDescriptor(descriptor)
val context = context().newDeclaration(descriptor) val context = context().newDeclaration(descriptor)
val constructorFunction = descriptor.unsubstitutedPrimaryConstructor?.let { context.getFunctionObject(it) } ?: val constructorFunction = descriptor.unsubstitutedPrimaryConstructor?.let { context.getFunctionObject(it) } ?:
@@ -76,7 +75,7 @@ class ClassTranslator private constructor(
context.addDeclarationStatement(constructorFunction.makeStmt()) context.addDeclarationStatement(constructorFunction.makeStmt())
val enumInitFunction = if (descriptor.kind == ClassKind.ENUM_CLASS) createEnumInitFunction() else null val enumInitFunction = if (descriptor.kind == ClassKind.ENUM_CLASS) createEnumInitFunction() else null
val nonConstructorContext = context.withUsageTrackerIfNecessary(scope, descriptor) val nonConstructorContext = context.withUsageTrackerIfNecessary(descriptor)
nonConstructorContext.startDeclaration() nonConstructorContext.startDeclaration()
val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext) val delegationTranslator = DelegationTranslator(classDeclaration, nonConstructorContext)
translatePropertiesAsConstructorParameters(nonConstructorContext) translatePropertiesAsConstructorParameters(nonConstructorContext)
@@ -117,9 +116,9 @@ class ClassTranslator private constructor(
} }
} }
private fun TranslationContext.withUsageTrackerIfNecessary(scope: JsScope, innerDescriptor: MemberDescriptor): TranslationContext { private fun TranslationContext.withUsageTrackerIfNecessary(innerDescriptor: MemberDescriptor): TranslationContext {
return if (isLocalClass) { return if (isLocalClass) {
innerWithUsageTracker(scope, innerDescriptor) innerWithUsageTracker(innerDescriptor)
} }
else { else {
inner(innerDescriptor) inner(innerDescriptor)
@@ -135,7 +134,7 @@ class ClassTranslator private constructor(
delegationTranslator: DelegationTranslator delegationTranslator: DelegationTranslator
) { ) {
if (!isTrait()) { if (!isTrait()) {
val constructorContext = classContext.innerWithUsageTracker(constructorFunction.scope, descriptor) val constructorContext = classContext.innerWithUsageTracker(descriptor)
if (isObjectLike()) { if (isObjectLike()) {
addObjectCache(constructorFunction.body.statements) addObjectCache(constructorFunction.body.statements)
} }
@@ -152,7 +151,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 = context().createGlobalName(StaticContext.getSuggestedName(descriptor) + "_initFields") function.name = JsScope.declareTemporaryName(StaticContext.getSuggestedName(descriptor) + "_initFields")
val emptyFunction = context().createRootScopedFunction(descriptor) val emptyFunction = context().createRootScopedFunction(descriptor)
function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction).makeStmt() function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction).makeStmt()
context().addDeclarationStatement(function.makeStmt()) context().addDeclarationStatement(function.makeStmt())
@@ -194,14 +193,12 @@ class ClassTranslator private constructor(
as ClassConstructorDescriptor as ClassConstructorDescriptor
val classDescriptor = constructorDescriptor.containingDeclaration val classDescriptor = constructorDescriptor.containingDeclaration
val constructorScope = classContext.getScopeForDescriptor(constructorDescriptor) val thisName = JsScope.declareTemporaryName(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
var context = classContext var context = classContext
.innerWithUsageTracker(constructorScope, constructorDescriptor) .innerWithUsageTracker(constructorDescriptor)
.innerContextWithAliased(receiverDescriptor, thisNameRef) .innerContextWithAliased(receiverDescriptor, thisNameRef)
val outerClassName = context.getOuterClassReference(classDescriptor) val outerClassName = context.getOuterClassReference(classDescriptor)
@@ -234,8 +231,8 @@ class ClassTranslator private constructor(
val leadingArgs = mutableListOf<JsExpression>() val leadingArgs = mutableListOf<JsExpression>()
if (descriptor.kind == ClassKind.ENUM_CLASS) { if (descriptor.kind == ClassKind.ENUM_CLASS) {
val nameParamName = constructorInitializer.scope.declareTemporaryName("name") val nameParamName = JsScope.declareTemporaryName("name")
val ordinalParamName = constructorInitializer.scope.declareTemporaryName("ordinal") val ordinalParamName = JsScope.declareTemporaryName("ordinal")
constructorInitializer.parameters.addAll(0, listOf(JsParameter(nameParamName), JsParameter(ordinalParamName))) constructorInitializer.parameters.addAll(0, listOf(JsParameter(nameParamName), JsParameter(ordinalParamName)))
leadingArgs += listOf(nameParamName.makeRef(), ordinalParamName.makeRef()) leadingArgs += listOf(nameParamName.makeRef(), ordinalParamName.makeRef())
} }
@@ -434,7 +431,7 @@ class ClassTranslator private constructor(
} }
private fun addObjectCache(statements: MutableList<JsStatement>) { private fun addObjectCache(statements: MutableList<JsStatement>) {
cachedInstanceName = context().createGlobalName(StaticContext.getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_VAR_SUFFIX) cachedInstanceName = JsScope.declareTemporaryName(StaticContext.getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_VAR_SUFFIX)
statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsObjectLiteral.THIS).makeStmt() statements += JsAstUtils.assignment(cachedInstanceName.makeRef(), JsObjectLiteral.THIS).makeStmt()
} }
@@ -66,7 +66,7 @@ class DeclarationBodyVisitor(
} }
else { else {
val enumName = context.getInnerNameForDescriptor(descriptor) val enumName = context.getInnerNameForDescriptor(descriptor)
val enumInstanceName = context.createGlobalName(enumName.ident + "_instance") val enumInstanceName = JsScope.declareTemporaryName(enumName.ident + "_instance")
assert(supertypes.size == 1) { "Simple Enum entry must have one supertype" } assert(supertypes.size == 1) { "Simple Enum entry must have one supertype" }
val jsEnumEntryCreation = ClassInitializerTranslator.generateEnumEntryInstanceCreation(context, enumEntry, enumEntryOrdinal) val jsEnumEntryCreation = ClassInitializerTranslator.generateEnumEntryInstanceCreation(context, enumEntry, enumEntryOrdinal)
@@ -118,7 +118,7 @@ class DeclarationBodyVisitor(
.translateAndAliasParameters(descriptor, caller.parameters) .translateAndAliasParameters(descriptor, caller.parameters)
.innerBlock(caller.body) .innerBlock(caller.body)
val callbackName = caller.scope.declareTemporaryName("callback" + Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX) val callbackName = JsScope.declareTemporaryName("callback" + Namer.DEFAULT_PARAMETER_IMPLEMENTOR_SUFFIX)
val callee = JsNameRef(bodyName, JsLiteral.THIS) val callee = JsNameRef(bodyName, JsLiteral.THIS)
val defaultInvocation = JsInvocation(callee, listOf<JsExpression>()) val defaultInvocation = JsInvocation(callee, listOf<JsExpression>())
@@ -135,7 +135,7 @@ class DelegationTranslator(
"setter for " + setterDescriptor.name.asString()) "setter for " + setterDescriptor.name.asString())
assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" } assert(setterDescriptor.valueParameters.size == 1) { "Setter must have 1 parameter" }
val defaultParameter = JsParameter(jsFunction.scope.declareTemporary()) val defaultParameter = JsParameter(JsScope.declareTemporary())
val defaultParameterRef = defaultParameter.name.makeRef() val defaultParameterRef = defaultParameter.name.makeRef()
val delegateRef = JsNameRef(delegateName, JsLiteral.THIS) val delegateRef = JsNameRef(delegateName, JsLiteral.THIS)
@@ -46,7 +46,7 @@ class EnumTranslator(
private fun generateValueOfFunction() { private fun generateValueOfFunction() {
val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, DescriptorUtils.ENUM_VALUE_OF)) val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, DescriptorUtils.ENUM_VALUE_OF))
val nameParam = function.scope.declareTemporaryName("name") val nameParam = JsScope.declareTemporaryName("name")
function.parameters += JsParameter(nameParam) function.parameters += JsParameter(nameParam)
val clauses = entries.map { entry -> val clauses = entries.map { entry ->
@@ -97,7 +97,7 @@ class CatchTranslator(
val additionalStatements = mutableListOf<JsStatement>() val additionalStatements = mutableListOf<JsStatement>()
val parameterRef = if (parameterName.ident != initialCatchParameterRef.ident) { val parameterRef = if (parameterName.ident != initialCatchParameterRef.ident) {
val parameterAlias = context.scope().declareTemporaryName(parameterName.ident) val parameterAlias = JsScope.declareTemporaryName(parameterName.ident)
additionalStatements += JsAstUtils.newVar(parameterAlias, initialCatchParameterRef) additionalStatements += JsAstUtils.newVar(parameterAlias, initialCatchParameterRef)
val ref = JsAstUtils.pureFqn(parameterAlias, null) val ref = JsAstUtils.pureFqn(parameterAlias, null)
ref ref
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention; import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
import org.jetbrains.kotlin.js.backend.ast.*; import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties; import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
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.declaration.ClassTranslator; import org.jetbrains.kotlin.js.translate.declaration.ClassTranslator;
import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt; import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt;
@@ -114,7 +113,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
KtExpression jetInitializer = multiDeclaration.getInitializer(); KtExpression jetInitializer = multiDeclaration.getInitializer();
assert jetInitializer != null : "Initializer for multi declaration must be not null"; assert jetInitializer != null : "Initializer for multi declaration must be not null";
JsExpression initializer = Translation.translateAsExpression(jetInitializer, context); JsExpression initializer = Translation.translateAsExpression(jetInitializer, context);
return DestructuringDeclarationTranslator.translate(multiDeclaration, context.scope().declareTemporary(), initializer, context); return DestructuringDeclarationTranslator.translate(multiDeclaration, JsScope.declareTemporary(), initializer, context);
} }
@Override @Override
@@ -125,7 +124,11 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
// TODO: add related descriptor to context and use it here // TODO: add related descriptor to context and use it here
KtDeclarationWithBody parent = PsiTreeUtil.getParentOfType(jetReturnExpression, KtDeclarationWithBody.class); KtDeclarationWithBody parent = PsiTreeUtil.getParentOfType(jetReturnExpression, KtDeclarationWithBody.class);
if (parent instanceof KtSecondaryConstructor) { if (parent instanceof KtSecondaryConstructor) {
return new JsReturn(new JsNameRef(Namer.ANOTHER_THIS_PARAMETER_NAME)).source(jetReturnExpression); ClassDescriptor classDescriptor = context.getClassDescriptor();
assert classDescriptor != null : "Missing class descriptor in context while translating constructor: " +
PsiUtilsKt.getTextWithLocation(jetReturnExpression);
JsExpression ref = ReferenceTranslator.translateAsValueReference(classDescriptor.getThisAsReceiverParameter(), context);
return new JsReturn(ref.source(jetReturnExpression));
} }
JsReturn jsReturn; JsReturn jsReturn;
@@ -602,8 +605,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull ClassDescriptor descriptor, @NotNull ClassDescriptor descriptor,
@NotNull TranslationContext context @NotNull TranslationContext context
) { ) {
JsScope scope = context.getScopeForDescriptor(descriptor); TranslationContext classContext = context.innerWithUsageTracker(descriptor);
TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
ClassTranslator.translate(declaration, classContext, null); ClassTranslator.translate(declaration, classContext, null);
} }
} }
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.js.backend.ast.JsExpression import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.backend.ast.JsFunction import org.jetbrains.kotlin.js.backend.ast.JsFunction
import org.jetbrains.kotlin.js.backend.ast.JsParameter import org.jetbrains.kotlin.js.backend.ast.JsParameter
import org.jetbrains.kotlin.js.backend.ast.JsScope
import org.jetbrains.kotlin.js.backend.ast.metadata.functionDescriptor import org.jetbrains.kotlin.js.backend.ast.metadata.functionDescriptor
import org.jetbrains.kotlin.js.backend.ast.metadata.hasDefaultValue import org.jetbrains.kotlin.js.backend.ast.metadata.hasDefaultValue
import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.Namer
@@ -48,14 +49,14 @@ fun TranslationContext.translateAndAliasParameters(
targetList += JsParameter(paramNameForType) targetList += JsParameter(paramNameForType)
val suggestedName = Namer.isInstanceSuggestedName(type) val suggestedName = Namer.isInstanceSuggestedName(type)
val paramName = scope().declareTemporaryName(suggestedName) val paramName = JsScope.declareTemporaryName(suggestedName)
targetList += JsParameter(paramName) targetList += JsParameter(paramName)
aliases[type] = paramName.makeRef() aliases[type] = paramName.makeRef()
} }
} }
if (descriptor.requiresExtensionReceiverParameter) { if (descriptor.requiresExtensionReceiverParameter) {
val receiverParameterName = scope().declareTemporaryName(Namer.getReceiverParameterName()) val receiverParameterName = JsScope.declareTemporaryName(Namer.getReceiverParameterName())
aliases[descriptor.extensionReceiverParameter!!] = receiverParameterName.makeRef() aliases[descriptor.extensionReceiverParameter!!] = receiverParameterName.makeRef()
targetList += JsParameter(receiverParameterName) targetList += JsParameter(receiverParameterName)
} }
@@ -209,8 +209,7 @@ private fun moveCapturedLocalInside(capturingFunction: JsFunction, capturedName:
private fun moveCapturedLocalInside(capturingFunction: JsFunction, capturedName: JsName, localFunAlias: JsInvocation): CapturedArgsParams { private fun moveCapturedLocalInside(capturingFunction: JsFunction, capturedName: JsName, localFunAlias: JsInvocation): CapturedArgsParams {
val capturedArgs = localFunAlias.arguments val capturedArgs = localFunAlias.arguments
val scope = capturingFunction.getInnerFunction()?.scope!! val freshNames = getTemporaryNamesInScope(capturedArgs)
val freshNames = getTemporaryNamesInScope(scope, capturedArgs)
val aliasCallArguments = freshNames.map(JsName::makeRef) val aliasCallArguments = freshNames.map(JsName::makeRef)
val alias = JsInvocation(localFunAlias.qualifier, aliasCallArguments) val alias = JsInvocation(localFunAlias.qualifier, aliasCallArguments)
@@ -225,7 +224,7 @@ private fun declareAliasInsideFunction(function: JsFunction, name: JsName, alias
function.getInnerFunction()?.addDeclaration(name, alias) function.getInnerFunction()?.addDeclaration(name, alias)
} }
private fun getTemporaryNamesInScope(scope: JsScope, suggested: List<JsExpression>): List<JsName> { private fun getTemporaryNamesInScope(suggested: List<JsExpression>): List<JsName> {
val freshNames = arrayListOf<JsName>() val freshNames = arrayListOf<JsName>()
for (suggestion in suggested) { for (suggestion in suggested) {
@@ -234,7 +233,7 @@ private fun getTemporaryNamesInScope(scope: JsScope, suggested: List<JsExpressio
} }
val ident = suggestion.ident val ident = suggestion.ident
val name = scope.declareTemporaryName(ident) val name = JsScope.declareTemporaryName(ident)
freshNames.add(name) freshNames.add(name)
} }
@@ -100,7 +100,7 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
context.getNameForElement(loopParameter) context.getNameForElement(loopParameter)
} }
else { else {
context.scope().declareTemporary() JsScope.declareTemporary()
} }
fun translateBody(itemValue: JsExpression?): JsStatement? { fun translateBody(itemValue: JsExpression?): JsStatement? {
@@ -68,7 +68,7 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
val nameMap = mutableMapOf<JsName, JsName>() val nameMap = mutableMapOf<JsName, JsName>()
for (nameBinding in fragment.nameBindings) { for (nameBinding in fragment.nameBindings) {
nameMap[nameBinding.name] = nameTable.getOrPut(nameBinding.key) { nameMap[nameBinding.name] = nameTable.getOrPut(nameBinding.key) {
fragment.scope.declareTemporaryName(nameBinding.name.ident).also { it.copyMetadataFrom(nameBinding.name) } JsScope.declareTemporaryName(nameBinding.name.ident).also { it.copyMetadataFrom(nameBinding.name) }
} }
} }
fragment.scope.findName(Namer.getRootPackageName())?.let { nameMap[it] = internalModuleName } fragment.scope.findName(Namer.getRootPackageName())?.let { nameMap[it] = internalModuleName }
@@ -77,7 +77,7 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
nameMap[importedModule.internalName] = importedModuleTable.getOrPut(importedModule.key) { nameMap[importedModule.internalName] = importedModuleTable.getOrPut(importedModule.key) {
val scope = rootFunction.scope val scope = rootFunction.scope
val newName = importedModule.internalName.let { val newName = importedModule.internalName.let {
if (it.isTemporary) scope.declareTemporaryName(it.ident) else scope.declareName(it.ident) if (it.isTemporary) JsScope.declareTemporaryName(it.ident) else scope.declareName(it.ident)
} }
newName.also { newName.also {
importedModulesImpl += JsImportedModule(importedModule.externalName, it, importedModule.plainReference) importedModulesImpl += JsImportedModule(importedModule.externalName, it, importedModule.plainReference)
@@ -97,7 +97,7 @@ object CallableReferenceTranslator {
val function = JsFunction(context.scope(), JsBlock(), "") val function = JsFunction(context.scope(), JsBlock(), "")
val receiverParam = if (descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null) { val receiverParam = if (descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null) {
val paramName = function.scope.declareTemporaryName(Namer.getReceiverParameterName()) val paramName = JsScope.declareTemporaryName(Namer.getReceiverParameterName())
function.parameters += JsParameter(paramName) function.parameters += JsParameter(paramName)
paramName.makeRef() paramName.makeRef()
} }
@@ -107,7 +107,7 @@ object CallableReferenceTranslator {
val aliases = mutableMapOf<KtExpression, JsExpression>() val aliases = mutableMapOf<KtExpression, JsExpression>()
for ((index, valueArg) in fakeCall.valueArguments.withIndex()) { for ((index, valueArg) in fakeCall.valueArguments.withIndex()) {
val paramName = function.scope.declareTemporaryName(descriptor.valueParameters[index].name.asString()) val paramName = JsScope.declareTemporaryName(descriptor.valueParameters[index].name.asString())
function.parameters += JsParameter(paramName) function.parameters += JsParameter(paramName)
aliases[valueArg.getArgumentExpression()!!] = paramName.makeRef() aliases[valueArg.getArgumentExpression()!!] = paramName.makeRef()
} }
@@ -162,7 +162,7 @@ object CallableReferenceTranslator {
val accessorFunction = JsFunction(context.scope(), JsBlock(), "") val accessorFunction = JsFunction(context.scope(), JsBlock(), "")
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 = accessorFunction.scope.declareTemporaryName(Namer.getReceiverParameterName()) val name = JsScope.declareTemporaryName(Namer.getReceiverParameterName())
accessorFunction.parameters += JsParameter(name) accessorFunction.parameters += JsParameter(name)
name.makeRef() name.makeRef()
} }
@@ -171,7 +171,7 @@ object CallableReferenceTranslator {
} }
val valueParam = if (isSetter) { val valueParam = if (isSetter) {
val name = accessorFunction.scope.declareTemporaryName("value") val name = JsScope.declareTemporaryName("value")
accessorFunction.parameters += JsParameter(name) accessorFunction.parameters += JsParameter(name)
name.makeRef() name.makeRef()
} }
@@ -56,7 +56,7 @@ public final class FunctionBodyTranslator extends AbstractTranslator {
for (FunctionDescriptor localFunction : functionCollector.getFunctions()) { for (FunctionDescriptor localFunction : functionCollector.getFunctions()) {
String localIdent = localFunction.getName().isSpecial() ? "lambda" : localFunction.getName().asString(); String localIdent = localFunction.getName().isSpecial() ? "lambda" : localFunction.getName().asString();
JsName localName = functionBodyContext.scope().getParent().declareTemporaryName(NameSuggestion.sanitizeName(localIdent)); JsName localName = JsScope.declareTemporaryName(NameSuggestion.sanitizeName(localIdent));
MetadataProperties.setDescriptor(localName, localFunction); MetadataProperties.setDescriptor(localName, localFunction);
JsExpression alias = JsAstUtils.pureFqn(localName, null); JsExpression alias = JsAstUtils.pureFqn(localName, null);
aliases.put(localFunction, alias); aliases.put(localFunction, alias);
@@ -24,7 +24,7 @@ fun JsFunction.addStatement(stmt: JsStatement) {
} }
fun JsFunction.addParameter(identifier: String, index: Int? = null): JsParameter { fun JsFunction.addParameter(identifier: String, index: Int? = null): JsParameter {
val name = scope.declareTemporaryName(identifier) val name = JsScope.declareTemporaryName(identifier)
val parameter = JsParameter(name) val parameter = JsParameter(name)
if (index == null) { if (index == null) {
@@ -134,8 +134,7 @@ private class TypeCheckRewritingVisitor : JsVisitorWithContextImpl() {
} }
private fun generateAlias(argument: JsExpression): Pair<JsExpression, JsExpression> { private fun generateAlias(argument: JsExpression): Pair<JsExpression, JsExpression> {
val currentScope = scopes.peek() val tmp = JsScope.declareTemporary()
val tmp = currentScope.declareTemporary()
val statementContext = lastStatementLevelContext val statementContext = lastStatementLevelContext
statementContext.addPrevious(newVar(tmp, null)) statementContext.addPrevious(newVar(tmp, null))
return Pair(assignment(tmp.makeRef(), argument), tmp.makeRef()) return Pair(assignment(tmp.makeRef(), argument), tmp.makeRef())
@@ -50,17 +50,16 @@ fun generateDelegateCall(
val parameters = SmartList<JsParameter>() val parameters = SmartList<JsParameter>()
val args = SmartList<JsExpression>() val args = SmartList<JsExpression>()
val functionScope = context.getScopeForDescriptor(fromDescriptor)
if (DescriptorUtils.isExtension(fromDescriptor)) { if (DescriptorUtils.isExtension(fromDescriptor)) {
val extensionFunctionReceiverName = functionScope.declareTemporaryName(Namer.getReceiverParameterName()) val extensionFunctionReceiverName = JsScope.declareTemporaryName(Namer.getReceiverParameterName())
parameters.add(JsParameter(extensionFunctionReceiverName)) parameters.add(JsParameter(extensionFunctionReceiverName))
args.add(JsNameRef(extensionFunctionReceiverName)) args.add(JsNameRef(extensionFunctionReceiverName))
} }
for (param in fromDescriptor.valueParameters) { for (param in fromDescriptor.valueParameters) {
val paramName = param.name.asString() val paramName = param.name.asString()
val jsParamName = functionScope.declareTemporaryName(paramName) val jsParamName = JsScope.declareTemporaryName(paramName)
parameters.add(JsParameter(jsParamName)) parameters.add(JsParameter(jsParamName))
args.add(JsNameRef(jsParamName)) args.add(JsNameRef(jsParamName))
} }