JS backend: mangling JS reserved words.

This commit is contained in:
Zalim Bashorov
2014-09-24 00:44:49 +04:00
parent ef60a7f776
commit e91e724469
21 changed files with 129 additions and 71 deletions
+1
View File
@@ -8,6 +8,7 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" /> <orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
</component> </component>
</module> </module>
@@ -14,13 +14,13 @@ public class JsCatchScope extends JsScope {
private final JsName name; private final JsName name;
public JsCatchScope(JsScope parent, String ident) { public JsCatchScope(JsScope parent, String ident) {
super(parent, "Catch scope"); super(parent, "Catch scope", null);
name = new JsName(this, ident); name = new JsName(this, ident);
} }
@Override @Override
@NotNull @NotNull
public JsName declareName(String identifier) { public JsName declareName(@NotNull String identifier) {
// Declare into parent scope! // Declare into parent scope!
return getParent().declareName(identifier); return getParent().declareName(identifier);
} }
@@ -31,7 +31,7 @@ public class JsCatchScope extends JsScope {
} }
@Override @Override
protected JsName findOwnName(String ident) { protected JsName findOwnName(@NotNull String ident) {
return name.getIdent().equals(ident) ? name : null; return name.getIdent().equals(ident) ? name : null;
} }
} }
@@ -16,21 +16,21 @@ public final class JsFunction extends JsLiteral implements HasName {
private JsBlock body; private JsBlock body;
private List<JsParameter> params; private List<JsParameter> params;
@NotNull @NotNull
private final JsScope scope; private final JsFunctionScope scope;
private JsName name; private JsName name;
public JsFunction(JsScope parentScope) { public JsFunction(@NotNull JsScope parentScope, @NotNull String description) {
this(parentScope, (JsName) null); this(parentScope, description, null);
} }
public JsFunction(JsScope parentScope, @NotNull JsBlock body) { public JsFunction(@NotNull JsScope parentScope, @NotNull JsBlock body, @NotNull String description) {
this(parentScope, (JsName) null); this(parentScope, description, null);
this.body = body; this.body = body;
} }
private JsFunction(JsScope parentScope, @Nullable JsName name) { private JsFunction(@NotNull JsScope parentScope, @NotNull String description, @Nullable JsName name) {
this.name = name; this.name = name;
scope = new JsScope(parentScope, name == null ? null : name.getIdent()); scope = new JsFunctionScope(parentScope, name == null ? description : name.getIdent());
} }
@NotNull @NotNull
@@ -57,7 +57,7 @@ public final class JsFunction extends JsLiteral implements HasName {
} }
@NotNull @NotNull
public JsScope getScope() { public JsFunctionScope getScope() {
return scope; return scope;
} }
@@ -29,11 +29,11 @@ public final class JsProgram extends SourceInfoAwareJsNode {
private final JsRootScope rootScope; private final JsRootScope rootScope;
private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>(); private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>();
private final JsScope topScope; private final JsObjectScope topScope;
public JsProgram(String unitId) { public JsProgram(String unitId) {
rootScope = new JsRootScope(this); rootScope = new JsRootScope(this);
topScope = new JsScope(rootScope, "Global", unitId); topScope = new JsObjectScope(rootScope, "Global", unitId);
setFragmentCount(1); setFragmentCount(1);
emptyStatement = new JsEmpty(); emptyStatement = new JsEmpty();
@@ -94,7 +94,7 @@ public final class JsProgram extends SourceInfoAwareJsNode {
* Gets the top level scope. This is the scope of all the statements in the * Gets the top level scope. This is the scope of all the statements in the
* main program. * main program.
*/ */
public JsScope getScope() { public JsObjectScope getScope() {
return topScope; return topScope;
} }
@@ -5,6 +5,7 @@
package com.google.dart.compiler.backend.js.ast; package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.backend.js.JsReservedIdentifiers; import com.google.dart.compiler.backend.js.JsReservedIdentifiers;
import org.jetbrains.annotations.NotNull;
/** /**
* The root scope is the parent of every scope. All identifiers in this scope * The root scope is the parent of every scope. All identifiers in this scope
@@ -25,7 +26,7 @@ public final class JsRootScope extends JsScope {
} }
@Override @Override
protected JsName findOwnName(String ident) { protected JsName findOwnName(@NotNull String ident) {
JsName name = super.findOwnName(ident); JsName name = super.findOwnName(ident);
if (name == null) { if (name == null) {
if (JsReservedIdentifiers.reservedGlobalSymbols.contains(ident)) { if (JsReservedIdentifiers.reservedGlobalSymbols.contains(ident)) {
@@ -11,6 +11,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import static com.google.dart.compiler.backend.js.ast.AstPackage.JsObjectScope;
/** /**
* A scope is a factory for creating and allocating * A scope is a factory for creating and allocating
* {@link JsName}s. A JavaScript AST is * {@link JsName}s. A JavaScript AST is
@@ -37,40 +39,32 @@ import java.util.Map;
* with a qualifier and could therefore never be confused with the global scope * with a qualifier and could therefore never be confused with the global scope
* hierarchy. * hierarchy.
*/ */
public class JsScope { public abstract class JsScope {
@Nullable @NotNull
private final String description; private final String description;
private Map<String, JsName> names = Collections.emptyMap(); private Map<String, JsName> names = Collections.emptyMap();
private final JsScope parent; private final JsScope parent;
protected int tempIndex = 0; protected int tempIndex = 0;
private final String scopeId; private final String scopeId;
public JsScope(JsScope parent, @Nullable String description) { public JsScope(JsScope parent, @NotNull String description, @Nullable String scopeId) {
this(parent, description, null);
}
public JsScope(JsScope parent) {
this(parent, null);
}
public JsScope(JsScope parent, @Nullable String description, @Nullable String scopeId) {
assert (parent != null); assert (parent != null);
this.scopeId = scopeId; this.scopeId = scopeId;
this.description = description; this.description = description;
this.parent = parent; this.parent = parent;
} }
@NotNull protected JsScope(@NotNull String description) {
public JsScope innerScope(@Nullable String scopeName) {
return new JsScope(this, scopeName);
}
protected JsScope(@Nullable String description) {
this.description = description; this.description = description;
parent = null; parent = null;
scopeId = null; scopeId = null;
} }
@NotNull
public JsScope innerObjectScope(@NotNull String scopeName) {
return JsObjectScope(this, scopeName);
}
/** /**
* Gets a name object associated with the specified identifier in this scope, * Gets a name object associated with the specified identifier in this scope,
* creating it if necessary.<br/> * creating it if necessary.<br/>
@@ -81,7 +75,7 @@ public class JsScope {
* @param identifier An identifier that is unique within this scope. * @param identifier An identifier that is unique within this scope.
*/ */
@NotNull @NotNull
public JsName declareName(String identifier) { public JsName declareName(@NotNull String identifier) {
JsName name = findOwnName(identifier); JsName name = findOwnName(identifier);
return name != null ? name : doCreateName(identifier); return name != null ? name : doCreateName(identifier);
} }
@@ -93,7 +87,7 @@ public class JsScope {
* (unless they use this function). * (unless they use this function).
*/ */
@NotNull @NotNull
public JsName declareFreshName(String suggestedName) { public JsName declareFreshName(@NotNull String suggestedName) {
String name = suggestedName; String name = suggestedName;
int counter = 0; int counter = 0;
while (hasOwnName(name)) { while (hasOwnName(name)) {
@@ -173,7 +167,7 @@ public class JsScope {
* *
* @return <code>null</code> if the identifier has no associated name * @return <code>null</code> if the identifier has no associated name
*/ */
protected JsName findOwnName(String ident) { protected JsName findOwnName(@NotNull String ident) {
return names.get(ident); return names.get(ident);
} }
} }
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.dart.compiler.backend.js.ast
public fun JsObjectScope(parent: JsScope, description: String): JsObjectScope = JsObjectScope(parent, description, null)
public class JsObjectScope(parent: JsScope, description: String, scopeId: String?) : JsScope(parent, description, scopeId)
public class JsFunctionScope(parent: JsScope, description: String) : JsScope(parent, description, null) {
override fun declareName(identifier: String): JsName = super.declareFreshName(identifier)
override fun hasOwnName(name: String): Boolean = RESERVED_WORDS.contains(name) || super.hasOwnName(name)
public fun declareNameUnsafe(identifier: String): JsName = super.declareName(identifier)
class object {
public val RESERVED_WORDS: Set<String> = setOf(
// keywords
"await", "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else", "finally", "for", "function", "if",
"in", "instanceof", "new", "return", "switch", "this", "throw", "try", "typeof", "var", "void", "while", "with",
// future reserved words
"class", "const", "enum", "export", "extends", "import", "super",
// as future reserved words in strict mode
"implements", "interface", "let", "package", "private", "protected", "public", "static", "yield",
// additional reserved words
"null", "true", "false",
// disallowed as variable names in strict mode
"eval", "arguments",
// non-reserved words that act like reserved words
"NaN", "Infinity", "undefined",
// the special Kotlin object
"Kotlin"
)
}
}
@@ -19,10 +19,10 @@ package org.jetbrains.k2js.translate.context
import com.google.dart.compiler.backend.js.ast.JsExpression import com.google.dart.compiler.backend.js.ast.JsExpression
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer
import com.google.dart.compiler.backend.js.ast.JsNameRef import com.google.dart.compiler.backend.js.ast.JsNameRef
import com.google.dart.compiler.backend.js.ast.JsScope import com.google.dart.compiler.backend.js.ast.JsObjectScope
class DefinitionPlace( class DefinitionPlace(
private val scope: JsScope, private val scope: JsObjectScope,
private val fqName: JsExpression, private val fqName: JsExpression,
val properties: MutableList<JsPropertyInitializer> val properties: MutableList<JsPropertyInitializer>
) { ) {
@@ -31,4 +31,4 @@ class DefinitionPlace(
properties.add(JsPropertyInitializer(name.makeRef(), expression)) properties.add(JsPropertyInitializer(name.makeRef(), expression))
return JsNameRef(name, fqName) return JsNameRef(name, fqName)
} }
} }
@@ -23,6 +23,8 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.plugin.JetLanguage; import org.jetbrains.jet.plugin.JetLanguage;
import static com.google.dart.compiler.backend.js.ast.AstPackage.JsObjectScope;
/** /**
* Encapuslates different types of constants and naming conventions. * Encapuslates different types of constants and naming conventions.
*/ */
@@ -171,7 +173,7 @@ public final class Namer {
@NotNull @NotNull
private final JsName kotlinName; private final JsName kotlinName;
@NotNull @NotNull
private final JsScope kotlinScope; private final JsObjectScope kotlinScope;
@NotNull @NotNull
private final JsName className; private final JsName className;
@NotNull @NotNull
@@ -208,7 +210,7 @@ public final class Namer {
private Namer(@NotNull JsScope rootScope) { private Namer(@NotNull JsScope rootScope) {
kotlinName = rootScope.declareName(KOTLIN_NAME); kotlinName = rootScope.declareName(KOTLIN_NAME);
kotlinScope = new JsScope(rootScope, "Kotlin standard object"); kotlinScope = JsObjectScope(rootScope, "Kotlin standard object");
traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME); traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
definePackage = kotlin("definePackage"); definePackage = kotlin("definePackage");
@@ -318,7 +320,7 @@ public final class Namer {
} }
@NotNull @NotNull
/*package*/ JsScope getKotlinScope() { /*package*/ JsObjectScope getKotlinScope() {
return kotlinScope; return kotlinScope;
} }
@@ -18,7 +18,7 @@ package org.jetbrains.k2js.translate.context;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.dart.compiler.backend.js.ast.JsName; import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsScope; import com.google.dart.compiler.backend.js.ast.JsObjectScope;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Map; import java.util.Map;
import static com.google.dart.compiler.backend.js.ast.AstPackage.JsObjectScope;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName;
/** /**
@@ -85,7 +86,7 @@ public final class StandardClasses {
} }
@NotNull @NotNull
public static StandardClasses bindImplementations(@NotNull JsScope kotlinObjectScope) { public static StandardClasses bindImplementations(@NotNull JsObjectScope kotlinObjectScope) {
StandardClasses standardClasses = new StandardClasses(kotlinObjectScope); StandardClasses standardClasses = new StandardClasses(kotlinObjectScope);
declareKotlinStandardClasses(standardClasses); declareKotlinStandardClasses(standardClasses);
return standardClasses; return standardClasses;
@@ -107,24 +108,24 @@ public final class StandardClasses {
@NotNull @NotNull
private final JsScope kotlinScope; private final JsObjectScope kotlinScope;
@NotNull @NotNull
private final Map<FqNameUnsafe, JsName> standardObjects = Maps.newHashMap(); private final Map<FqNameUnsafe, JsName> standardObjects = Maps.newHashMap();
@NotNull @NotNull
private final Map<FqNameUnsafe, JsScope> scopeMap = Maps.newHashMap(); private final Map<FqNameUnsafe, JsObjectScope> scopeMap = Maps.newHashMap();
private StandardClasses(@NotNull JsScope kotlinScope) { private StandardClasses(@NotNull JsObjectScope kotlinScope) {
this.kotlinScope = kotlinScope; this.kotlinScope = kotlinScope;
} }
private void declareTopLevelObjectInScope(@NotNull JsScope scope, @NotNull Map<FqNameUnsafe, JsName> map, private void declareTopLevelObjectInScope(@NotNull JsObjectScope scope, @NotNull Map<FqNameUnsafe, JsName> map,
@NotNull FqNameUnsafe fullQualifiedName, @NotNull String name) { @NotNull FqNameUnsafe fullQualifiedName, @NotNull String name) {
JsName declaredName = scope.declareName(name); JsName declaredName = scope.declareName(name);
map.put(fullQualifiedName, declaredName); map.put(fullQualifiedName, declaredName);
scopeMap.put(fullQualifiedName, new JsScope(scope, "scope for " + name)); scopeMap.put(fullQualifiedName, JsObjectScope(scope, "scope for " + name));
} }
private void declareKotlinObject(@NotNull FqNameUnsafe fullQualifiedName, @NotNull String kotlinLibName) { private void declareKotlinObject(@NotNull FqNameUnsafe fullQualifiedName, @NotNull String kotlinLibName) {
@@ -134,7 +135,7 @@ public final class StandardClasses {
private void declareInner(@NotNull FqNameUnsafe fullQualifiedClassName, private void declareInner(@NotNull FqNameUnsafe fullQualifiedClassName,
@NotNull String shortMethodName, @NotNull String shortMethodName,
@NotNull String javascriptName) { @NotNull String javascriptName) {
JsScope classScope = scopeMap.get(fullQualifiedClassName); JsObjectScope classScope = scopeMap.get(fullQualifiedClassName);
assert classScope != null; assert classScope != null;
FqNameUnsafe fullQualifiedMethodName = fullQualifiedClassName.child(Name.guess(shortMethodName)); FqNameUnsafe fullQualifiedMethodName = fullQualifiedClassName.child(Name.guess(shortMethodName));
standardObjects.put(fullQualifiedMethodName, classScope.declareName(javascriptName)); standardObjects.put(fullQualifiedMethodName, classScope.declareName(javascriptName));
@@ -354,7 +354,7 @@ public final class StaticContext {
return null; return null;
} }
if (getSuperclass((ClassDescriptor) descriptor) == null) { if (getSuperclass((ClassDescriptor) descriptor) == null) {
return getRootScope().innerScope("Scope for class " + descriptor.getName()); return getRootScope().innerObjectScope("Scope for class " + descriptor.getName());
} }
return null; return null;
} }
@@ -369,7 +369,7 @@ public final class StaticContext {
if (superclass == null) { if (superclass == null) {
return null; return null;
} }
return getScopeForDescriptor(superclass).innerScope("Scope for class " + descriptor.getName()); return getScopeForDescriptor(superclass).innerObjectScope("Scope for class " + descriptor.getName());
} }
}; };
Rule<JsScope> generateNewScopesForPackageDescriptors = new Rule<JsScope>() { Rule<JsScope> generateNewScopesForPackageDescriptors = new Rule<JsScope>() {
@@ -378,7 +378,7 @@ public final class StaticContext {
if (!(descriptor instanceof PackageFragmentDescriptor)) { if (!(descriptor instanceof PackageFragmentDescriptor)) {
return null; return null;
} }
return getRootScope().innerScope("Package " + descriptor.getName()); return getRootScope().innerObjectScope("Package " + descriptor.getName());
} }
}; };
//TODO: never get there //TODO: never get there
@@ -386,7 +386,7 @@ public final class StaticContext {
@Override @Override
public JsScope apply(@NotNull DeclarationDescriptor descriptor) { public JsScope apply(@NotNull DeclarationDescriptor descriptor) {
JsScope enclosingScope = getEnclosingScope(descriptor); JsScope enclosingScope = getEnclosingScope(descriptor);
return enclosingScope.innerScope("Scope for member " + descriptor.getName()); return enclosingScope.innerObjectScope("Scope for member " + descriptor.getName());
} }
}; };
Rule<JsScope> createFunctionObjectsForCallableDescriptors = new Rule<JsScope>() { Rule<JsScope> createFunctionObjectsForCallableDescriptors = new Rule<JsScope>() {
@@ -19,15 +19,15 @@ package org.jetbrains.k2js.translate.context
import org.jetbrains.jet.lang.descriptors.* import org.jetbrains.jet.lang.descriptors.*
import org.jetbrains.jet.lang.resolve.DescriptorUtils.isAncestor import org.jetbrains.jet.lang.resolve.DescriptorUtils.isAncestor
import com.google.dart.compiler.backend.js.ast.JsName import com.google.dart.compiler.backend.js.ast.JsName
import com.google.dart.compiler.backend.js.ast.JsScope
import org.jetbrains.k2js.translate.utils.TranslationUtils.getSuggestedName import org.jetbrains.k2js.translate.utils.TranslationUtils.getSuggestedName
import com.google.dart.compiler.backend.js.ast.JsFunctionScope
private val CAPTURED_RECEIVER_NAME_PREFIX : String = "this$" 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 scope: JsFunctionScope
) { ) {
private val captured = linkedMapOf<CallableDescriptor, JsName>() private val captured = linkedMapOf<CallableDescriptor, JsName>()
@@ -114,7 +114,7 @@ public final class ClassTranslator extends AbstractTranslator {
if (!descriptor.getKind().isSingleton() && !isAnonymousObject(descriptor)) { if (!descriptor.getKind().isSingleton() && !isAnonymousObject(descriptor)) {
qualifiedReference = declarationContext.getQualifiedReference(descriptor); qualifiedReference = declarationContext.getQualifiedReference(descriptor);
JsScope scope = context().getScopeForDescriptor(descriptor); JsScope scope = context().getScopeForDescriptor(descriptor);
definitionPlace = new DefinitionPlace(scope, qualifiedReference, staticProperties); definitionPlace = new DefinitionPlace((JsObjectScope) scope, qualifiedReference, staticProperties);
} }
declarationContext = declarationContext.newDeclaration(descriptor, definitionPlace); declarationContext = declarationContext.newDeclaration(descriptor, definitionPlace);
@@ -240,7 +240,7 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression translateObjectInsideClass(@NotNull TranslationContext outerClassContext) { private JsExpression translateObjectInsideClass(@NotNull TranslationContext outerClassContext) {
JsFunction fun = new JsFunction(outerClassContext.scope(), new JsBlock()); JsFunction fun = new JsFunction(outerClassContext.scope(), new JsBlock(), "initializer for " + descriptor.getName().asString());
TranslationContext funContext = outerClassContext.newFunctionBodyWithUsageTracker(fun, descriptor); TranslationContext funContext = outerClassContext.newFunctionBodyWithUsageTracker(fun, descriptor);
fun.getBody().getStatements().add(new JsReturn(translate(funContext))); fun.getBody().getStatements().add(new JsReturn(translate(funContext)));
@@ -109,6 +109,7 @@ public class DelegationTranslator(
val propertyName: String = descriptor.getName().asString() val propertyName: String = descriptor.getName().asString()
fun generateDelegateGetterFunction(getterDescriptor: PropertyGetterDescriptor): JsFunction { fun generateDelegateGetterFunction(getterDescriptor: PropertyGetterDescriptor): JsFunction {
// TODO review: used wrong scope?
val delegateRefName = context().getScopeForDescriptor(getterDescriptor).declareName(delegateName) val delegateRefName = context().getScopeForDescriptor(getterDescriptor).declareName(delegateName)
val delegateRef = JsNameRef(delegateRefName, JsLiteral.THIS) val delegateRef = JsNameRef(delegateRefName, JsLiteral.THIS)
@@ -130,7 +131,8 @@ public class DelegationTranslator(
} }
fun generateDelegateSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction { fun generateDelegateSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction {
val jsFunction = JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration())) val jsFunction = JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration()),
"setter for " + setterDescriptor.getName().asString())
assert(setterDescriptor.getValueParameters().size() == 1, "Setter must have 1 parameter") assert(setterDescriptor.getValueParameters().size() == 1, "Setter must have 1 parameter")
val defaultParameter = JsParameter(jsFunction.getScope().declareTemporary()) val defaultParameter = JsParameter(jsFunction.getScope().declareTemporary())
@@ -169,8 +171,7 @@ public class DelegationTranslator(
return generateDelegateAccessor(setterDescriptor, generateDelegateSetterFunction(setterDescriptor)) return generateDelegateAccessor(setterDescriptor, generateDelegateSetterFunction(setterDescriptor))
} }
properties.addGetterAndSetter(descriptor, context(), ::generateDelegateGetter, ::generateDelegateSetter properties.addGetterAndSetter(descriptor, context(), ::generateDelegateGetter, ::generateDelegateSetter)
)
} }
@@ -50,7 +50,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
@Override @Override
public void generateCopyFunction(@NotNull FunctionDescriptor function, @NotNull List<JetParameter> constructorParameters) { public void generateCopyFunction(@NotNull FunctionDescriptor function, @NotNull List<JetParameter> constructorParameters) {
JsFunction functionObj = generateJsMethod(function); JsFunction functionObj = generateJsMethod(function);
JsScope funScope = functionObj.getScope(); JsFunctionScope funScope = functionObj.getScope();
assert function.getValueParameters().size() == constructorParameters.size(); assert function.getValueParameters().size() == constructorParameters.size();
@@ -145,7 +145,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
assert !classProperties.isEmpty(); assert !classProperties.isEmpty();
FunctionDescriptor prototypeFun = CodegenUtil.getAnyEqualsMethod(); FunctionDescriptor prototypeFun = CodegenUtil.getAnyEqualsMethod();
JsFunction functionObj = generateJsMethod(prototypeFun); JsFunction functionObj = generateJsMethod(prototypeFun);
JsScope funScope = functionObj.getScope(); JsFunctionScope funScope = functionObj.getScope();
JsName paramName = funScope.declareName("other"); JsName paramName = funScope.declareName("other");
functionObj.getParameters().add(new JsParameter(paramName)); functionObj.getParameters().add(new JsParameter(paramName));
@@ -42,7 +42,7 @@ final class PackageTranslator extends AbstractTranslator {
JsNameRef reference = context.getQualifiedReference(descriptor); JsNameRef reference = context.getQualifiedReference(descriptor);
SmartList<JsPropertyInitializer> properties = new SmartList<JsPropertyInitializer>(); SmartList<JsPropertyInitializer> properties = new SmartList<JsPropertyInitializer>();
DefinitionPlace definitionPlace = new DefinitionPlace(scope, reference, properties); DefinitionPlace definitionPlace = new DefinitionPlace((JsObjectScope) scope, reference, properties);
TranslationContext newContext = context.newDeclaration(descriptor, definitionPlace); TranslationContext newContext = context.newDeclaration(descriptor, definitionPlace);
FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext, definitionPlace.getProperties()); FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext, definitionPlace.getProperties());
@@ -127,7 +127,8 @@ private class PropertyTranslator(
} }
private fun generateDefaultSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction { private fun generateDefaultSetterFunction(setterDescriptor: PropertySetterDescriptor): JsFunction {
val jsFunction = JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration())) val jsFunction = JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration()),
"setter for " + setterDescriptor.getName().asString())
assert(setterDescriptor.getValueParameters().size() == 1, "Setter must have 1 parameter") assert(setterDescriptor.getValueParameters().size() == 1, "Setter must have 1 parameter")
val valueParameterDescriptor = setterDescriptor.getValueParameters().get(0) val valueParameterDescriptor = setterDescriptor.getValueParameters().get(0)
@@ -351,8 +351,9 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
} }
private static String getReferencedName(JetSimpleNameExpression expression) { private static String getReferencedName(JetSimpleNameExpression expression) {
String name = expression.getReferencedName(); return expression.getReferencedName()
return name.charAt(0) == '@' ? name.substring(1) + '$' : name; .replaceAll("^@", "")
.replaceAll("(?:^`(.*)`$)", "$1");
} }
private static String getTargetLabel(JetExpressionWithLabel expression, TranslationContext context) { private static String getTargetLabel(JetExpressionWithLabel expression, TranslationContext context) {
@@ -24,7 +24,7 @@ public abstract class CommonUnitTester extends JSTester {
@Override @Override
public void constructTestMethodInvocation(@NotNull JsExpression functionToTestCall, public void constructTestMethodInvocation(@NotNull JsExpression functionToTestCall,
@NotNull JsStringLiteral testName) { @NotNull JsStringLiteral testName) {
JsFunction functionToTest = new JsFunction(getContext().scope()); JsFunction functionToTest = new JsFunction(getContext().scope(), "test function");
functionToTest.setBody(new JsBlock(functionToTestCall.makeStmt())); functionToTest.setBody(new JsBlock(functionToTestCall.makeStmt()));
getBlock().getStatements().add(new JsInvocation(getTestMethodRef(), testName, functionToTest).makeStmt()); getBlock().getStatements().add(new JsInvocation(getTestMethodRef(), testName, functionToTest).makeStmt());
} }
@@ -278,7 +278,7 @@ public final class JsAstUtils {
@NotNull @NotNull
public static JsFunction createFunctionWithEmptyBody(@NotNull JsScope parent) { public static JsFunction createFunctionWithEmptyBody(@NotNull JsScope parent) {
return new JsFunction(parent, new JsBlock()); return new JsFunction(parent, new JsBlock(), "<anonymous>");
} }
@NotNull @NotNull
@@ -322,10 +322,10 @@ public final class JsAstUtils {
} }
@NotNull @NotNull
public static JsFunction createPackage(@NotNull List<JsStatement> to, @NotNull JsScope scope) { public static JsFunction createPackage(@NotNull List<JsStatement> to, @NotNull JsObjectScope scope) {
JsFunction packageBlockFunction = createFunctionWithEmptyBody(scope); JsFunction packageBlockFunction = createFunctionWithEmptyBody(scope);
JsName kotlinObjectAsParameter = packageBlockFunction.getScope().declareName(Namer.KOTLIN_NAME); JsName kotlinObjectAsParameter = packageBlockFunction.getScope().declareNameUnsafe(Namer.KOTLIN_NAME);
packageBlockFunction.getParameters().add(new JsParameter(kotlinObjectAsParameter)); packageBlockFunction.getParameters().add(new JsParameter(kotlinObjectAsParameter));
to.add(new JsInvocation(packageBlockFunction, Namer.KOTLIN_OBJECT_REF).makeStmt()); to.add(new JsInvocation(packageBlockFunction, Namer.KOTLIN_OBJECT_REF).makeStmt());
@@ -65,7 +65,7 @@ public final class TranslationUtils {
@NotNull @NotNull
public static JsFunction simpleReturnFunction(@NotNull JsScope functionScope, @NotNull JsExpression returnExpression) { public static JsFunction simpleReturnFunction(@NotNull JsScope functionScope, @NotNull JsExpression returnExpression) {
return new JsFunction(functionScope, new JsBlock(new JsReturn(returnExpression))); return new JsFunction(functionScope, new JsBlock(new JsReturn(returnExpression)), "<simpleReturnFunction>");
} }
@NotNull @NotNull