JS: use temporary names while translation, replace with fixed name during post-processing pass
This commit is contained in:
@@ -11,4 +11,6 @@ import com.google.dart.compiler.common.HasSymbol;
|
|||||||
*/
|
*/
|
||||||
public interface HasName extends HasSymbol {
|
public interface HasName extends HasSymbol {
|
||||||
JsName getName();
|
JsName getName();
|
||||||
|
|
||||||
|
void setName(JsName name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ public class JsCatchScope extends JsScope {
|
|||||||
private final JsName name;
|
private final JsName name;
|
||||||
|
|
||||||
public JsCatchScope(JsScope parent, @NotNull String ident) {
|
public JsCatchScope(JsScope parent, @NotNull String ident) {
|
||||||
super(parent, "Catch scope", null);
|
super(parent, "Catch scope");
|
||||||
name = new JsName(this, ident);
|
name = new JsName(this, ident, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public final class JsFunction extends JsLiteral implements HasName {
|
|||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setName(@Nullable JsName name) {
|
public void setName(@Nullable JsName name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* Represents a JavaScript label statement.
|
* Represents a JavaScript label statement.
|
||||||
*/
|
*/
|
||||||
public class JsLabel extends SourceInfoAwareJsNode implements JsStatement, HasName {
|
public class JsLabel extends SourceInfoAwareJsNode implements JsStatement, HasName {
|
||||||
private final JsName label;
|
private JsName label;
|
||||||
|
|
||||||
private JsStatement statement;
|
private JsStatement statement;
|
||||||
|
|
||||||
@@ -30,6 +30,11 @@ public class JsLabel extends SourceInfoAwareJsNode implements JsStatement, HasNa
|
|||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(JsName name) {
|
||||||
|
label = name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Symbol getSymbol() {
|
public Symbol getSymbol() {
|
||||||
return label;
|
return label;
|
||||||
|
|||||||
@@ -12,17 +12,35 @@ 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 JsScope enclosing;
|
||||||
|
private final int ordinal;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final String ident;
|
private final String ident;
|
||||||
|
|
||||||
|
private final boolean temporary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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) {
|
JsName(JsScope enclosing, @NotNull String ident, boolean temporary) {
|
||||||
this.enclosing = enclosing;
|
this.enclosing = enclosing;
|
||||||
this.ident = ident;
|
this.ident = ident;
|
||||||
|
this.temporary = temporary;
|
||||||
|
ordinal = temporary ? ordinalGenerator++ : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOrdinal() {
|
||||||
|
return ordinal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsScope getEnclosing() {
|
||||||
|
return enclosing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTemporary() {
|
||||||
|
return temporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -39,21 +57,4 @@ public class JsName extends HasMetadata implements Symbol {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return ident;
|
return ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return ident.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof JsName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
JsName other = (JsName) obj;
|
|
||||||
return ident.equals(other.ident) && enclosing == other.enclosing;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ public final class JsNameRef extends JsExpression implements HasName {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Symbol getSymbol() {
|
public Symbol getSymbol() {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
*/
|
*/
|
||||||
public final class JsParameter extends SourceInfoAwareJsNode implements HasName {
|
public final class JsParameter extends SourceInfoAwareJsNode implements HasName {
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsName name;
|
private JsName name;
|
||||||
|
|
||||||
public JsParameter(@NotNull JsName name) {
|
public JsParameter(@NotNull JsName name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -24,6 +24,11 @@ public final class JsParameter extends SourceInfoAwareJsNode implements HasName
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(@NotNull JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public Symbol getSymbol() {
|
public Symbol getSymbol() {
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ public final class JsProgram extends SourceInfoAwareJsNode {
|
|||||||
private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>();
|
private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>();
|
||||||
private final JsObjectScope topScope;
|
private final JsObjectScope topScope;
|
||||||
|
|
||||||
public JsProgram(String unitId) {
|
public JsProgram() {
|
||||||
rootScope = new JsRootScope(this);
|
rootScope = new JsRootScope(this);
|
||||||
topScope = new JsObjectScope(rootScope, "Global", unitId);
|
topScope = new JsObjectScope(rootScope, "Global");
|
||||||
setFragmentCount(1);
|
setFragmentCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,10 @@ import com.google.dart.compiler.util.Maps;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static com.google.dart.compiler.backend.js.ast.JsScopesKt.JsObjectScope;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A scope is a factory for creating and allocating
|
* A scope is a factory for creating and allocating
|
||||||
@@ -46,14 +43,13 @@ 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 int tempIndex = 0;
|
|
||||||
private final String scopeId;
|
|
||||||
|
|
||||||
private static final Pattern FRESH_NAME_SUFFIX = Pattern.compile("[\\$_]\\d+$");
|
private static final Pattern FRESH_NAME_SUFFIX = Pattern.compile("[\\$_]\\d+$");
|
||||||
|
|
||||||
public JsScope(JsScope parent, @NotNull String description, @Nullable String scopeId) {
|
public JsScope(JsScope parent, @NotNull String description) {
|
||||||
this.scopeId = scopeId;
|
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
@@ -61,12 +57,21 @@ public abstract class JsScope {
|
|||||||
protected JsScope(@NotNull String description) {
|
protected JsScope(@NotNull String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
parent = null;
|
parent = null;
|
||||||
scopeId = 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 JsObjectScope(this, scopeName);
|
return new JsObjectScope(this, scopeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,9 +102,15 @@ public abstract class JsScope {
|
|||||||
return doCreateName(ident);
|
return doCreateName(ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNextTempName() {
|
@NotNull
|
||||||
// introduced by the compiler
|
public JsName declareTemporaryName(@NotNull String suggestedName) {
|
||||||
return "tmp$" + (scopeId != null ? scopeId + "$" : "") + tempIndex++;
|
assert !suggestedName.isEmpty();
|
||||||
|
JsName name = new JsName(this, suggestedName, true);
|
||||||
|
if (temporaryNames == null) {
|
||||||
|
temporaryNames = new WeakHashMap<JsName, Object>();
|
||||||
|
}
|
||||||
|
temporaryNames.put(name, this);
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,7 +121,7 @@ public abstract class JsScope {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName declareTemporary() {
|
public JsName declareTemporary() {
|
||||||
return declareFreshName(getNextTempName());
|
return declareTemporaryName("tmp$");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +182,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);
|
JsName name = new JsName(this, ident, false);
|
||||||
names = Maps.put(names, ident, name);
|
names = Maps.put(names, ident, name);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class JsVars extends SourceInfoAwareJsNode implements JsStatement, Iterab
|
|||||||
* A var declared using the JavaScript <code>var</code> statement.
|
* A var declared using the JavaScript <code>var</code> statement.
|
||||||
*/
|
*/
|
||||||
public static class JsVar extends SourceInfoAwareJsNode implements HasName {
|
public static class JsVar extends SourceInfoAwareJsNode implements HasName {
|
||||||
private final JsName name;
|
private JsName name;
|
||||||
private JsExpression initExpression;
|
private JsExpression initExpression;
|
||||||
|
|
||||||
public JsVar(JsName name) {
|
public JsVar(JsName name) {
|
||||||
@@ -70,6 +70,11 @@ public class JsVars extends SourceInfoAwareJsNode implements JsStatement, Iterab
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Symbol getSymbol() {
|
public Symbol getSymbol() {
|
||||||
return name;
|
return name;
|
||||||
|
|||||||
@@ -18,15 +18,13 @@ package com.google.dart.compiler.backend.js.ast
|
|||||||
|
|
||||||
import java.util.Stack
|
import java.util.Stack
|
||||||
|
|
||||||
fun JsObjectScope(parent: JsScope, description: String): JsObjectScope = JsObjectScope(parent, description, null)
|
class JsObjectScope(parent: JsScope, description: String) : JsScope(parent, description)
|
||||||
|
|
||||||
class JsObjectScope(parent: JsScope, description: String, scopeId: String?) : JsScope(parent, description, scopeId)
|
object JsDynamicScope : JsScope(null, "Scope for dynamic declarations") {
|
||||||
|
override fun doCreateName(name: String) = JsName(this, name, false)
|
||||||
object JsDynamicScope : JsScope(null, "Scope for dynamic declarations", null) {
|
|
||||||
override fun doCreateName(name: String) = JsName(this, name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open class JsFunctionScope(parent: JsScope, description: String) : JsScope(parent, description, null) {
|
open class JsFunctionScope(parent: JsScope, description: String) : JsScope(parent, description) {
|
||||||
|
|
||||||
private val labelScopes = Stack<LabelScope>()
|
private val labelScopes = Stack<LabelScope>()
|
||||||
private val topLabelScope: LabelScope?
|
private val topLabelScope: LabelScope?
|
||||||
@@ -50,7 +48,7 @@ open class JsFunctionScope(parent: JsScope, description: String) : JsScope(paren
|
|||||||
open fun findLabel(label: String): JsName? =
|
open fun findLabel(label: String): JsName? =
|
||||||
topLabelScope?.findName(label)
|
topLabelScope?.findName(label)
|
||||||
|
|
||||||
private inner class LabelScope(parent: LabelScope?, val ident: String) : JsScope(parent, "Label scope for $ident", null) {
|
private inner class LabelScope(parent: LabelScope?, val ident: String) : JsScope(parent, "Label scope for $ident") {
|
||||||
val labelName: JsName
|
val labelName: JsName
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -60,7 +58,7 @@ open class JsFunctionScope(parent: JsScope, description: String) : JsScope(paren
|
|||||||
else -> ident
|
else -> ident
|
||||||
}
|
}
|
||||||
|
|
||||||
labelName = JsName(this@JsFunctionScope, freshIdent)
|
labelName = JsName(this@JsFunctionScope, freshIdent, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findOwnName(name: String): JsName? =
|
override fun findOwnName(name: String): JsName? =
|
||||||
|
|||||||
@@ -87,10 +87,10 @@ class JsCallChecker(
|
|||||||
val errorReporter = JsCodeErrorReporter(argument, code, context.trace)
|
val errorReporter = JsCodeErrorReporter(argument, code, context.trace)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val parserScope = JsFunctionScope(JsRootScope(JsProgram("<js checker>")), "<js fun>")
|
val parserScope = JsFunctionScope(JsRootScope(JsProgram()), "<js fun>")
|
||||||
val statements = parse(code, errorReporter, parserScope)
|
val statements = parse(code, errorReporter, parserScope)
|
||||||
|
|
||||||
if (statements.size == 0) {
|
if (statements.isEmpty()) {
|
||||||
context.trace.report(ErrorsJs.JSCODE_NO_JAVASCRIPT_PRODUCED.on(argument))
|
context.trace.report(ErrorsJs.JSCODE_NO_JAVASCRIPT_PRODUCED.on(argument))
|
||||||
}
|
}
|
||||||
} catch (e: AbortParsingException) {
|
} catch (e: AbortParsingException) {
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ class FunctionReader(private val context: TranslationContext) {
|
|||||||
offset++
|
offset++
|
||||||
}
|
}
|
||||||
|
|
||||||
val function = parseFunction(source, offset, ThrowExceptionOnErrorReporter, JsRootScope(JsProgram("<inline>")))
|
val function = parseFunction(source, offset, ThrowExceptionOnErrorReporter, JsRootScope(JsProgram()))
|
||||||
val moduleName = getExternalModuleName(descriptor)!!
|
val moduleName = getExternalModuleName(descriptor)!!
|
||||||
val moduleReference = context.getModuleExpressionFor(descriptor) ?: getRootPackage()
|
val moduleReference = context.getModuleExpressionFor(descriptor) ?: getRootPackage()
|
||||||
|
|
||||||
|
|||||||
@@ -35,12 +35,10 @@ class RedundantBindElimination(private val root: JsBlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun tryEliminate(invocation: JsInvocation) {
|
private fun tryEliminate(invocation: JsInvocation) {
|
||||||
val qualifier = invocation.qualifier
|
val qualifier = invocation.qualifier as? JsInvocation ?: return
|
||||||
if (qualifier !is JsInvocation) return
|
|
||||||
|
|
||||||
val outerQualifier = qualifier.qualifier
|
val outerQualifier = qualifier.qualifier as? JsNameRef ?: return
|
||||||
if (outerQualifier !is JsNameRef) return
|
val name = outerQualifier.ident
|
||||||
val name = outerQualifier.name?.ident ?: outerQualifier.ident
|
|
||||||
if (name != "bind") return
|
if (name != "bind") return
|
||||||
|
|
||||||
val qualifierReplacement = outerQualifier.qualifier ?: return
|
val qualifierReplacement = outerQualifier.qualifier ?: return
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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 org.jetbrains.kotlin.js.inline.clean
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.continuationInterfaceRef
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.interceptResumeRef
|
||||||
|
import com.google.dart.compiler.backend.js.ast.metadata.suspendObjectRef
|
||||||
|
import org.jetbrains.kotlin.js.inline.util.collectReferencedTemporaryNames
|
||||||
|
|
||||||
|
fun JsNode.resolveTemporaryNames() {
|
||||||
|
val scopeTree = ScopeCollector().let {
|
||||||
|
it.accept(this)
|
||||||
|
it.scopeTree
|
||||||
|
}
|
||||||
|
|
||||||
|
val renamings = scopeTree.resolveNames()
|
||||||
|
accept(object : RecursiveJsVisitor() {
|
||||||
|
override fun visitElement(node: JsNode) {
|
||||||
|
super.visitElement(node)
|
||||||
|
if (node is HasName) {
|
||||||
|
val name = node.name
|
||||||
|
if (name != null) {
|
||||||
|
renamings[name]?.let { node.name = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunction(x: JsFunction) {
|
||||||
|
x.continuationInterfaceRef?.let { accept(it) }
|
||||||
|
x.interceptResumeRef?.let { accept(it) }
|
||||||
|
x.suspendObjectRef?.let { accept(it) }
|
||||||
|
super.visitFunction(x)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Map<JsScope, Set<JsScope>>.resolveNames(): Map<JsName, JsName> {
|
||||||
|
val replacements = mutableMapOf<JsName, JsName>()
|
||||||
|
fun traverse(scope: JsScope) {
|
||||||
|
for (temporaryName in scope.temporaryNames.sortedBy { it.ordinal }) {
|
||||||
|
replacements[temporaryName] = scope.declareFreshName(temporaryName.ident).apply { copyMetadataFrom(temporaryName) }
|
||||||
|
}
|
||||||
|
this[scope]!!.forEach(::traverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
val roots = keys.toMutableSet()
|
||||||
|
values.forEach { roots -= it }
|
||||||
|
|
||||||
|
for (root in roots) {
|
||||||
|
traverse(root)
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScopeCollector() : RecursiveJsVisitor() {
|
||||||
|
val scopeTree = mutableMapOf<JsScope, MutableSet<JsScope>>()
|
||||||
|
|
||||||
|
override fun visitCatch(x: JsCatch) {
|
||||||
|
recordScope(x.scope)
|
||||||
|
super.visitCatch(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunction(x: JsFunction) {
|
||||||
|
recordScope(x.scope)
|
||||||
|
super.visitFunction(x)
|
||||||
|
}
|
||||||
|
override fun visitElement(node: JsNode) {
|
||||||
|
if (node is HasName) {
|
||||||
|
node.name?.let { recordScope(it.enclosing) }
|
||||||
|
}
|
||||||
|
super.visitElement(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun recordScope(scope: JsScope) {
|
||||||
|
if (scope !in scopeTree) {
|
||||||
|
scopeTree[scope] = mutableSetOf()
|
||||||
|
val parent = scope.parent
|
||||||
|
if (parent != null) {
|
||||||
|
recordScope(parent)
|
||||||
|
scopeTree[parent]!!.add(scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,7 +50,11 @@ class NamingContext(
|
|||||||
|
|
||||||
fun getFreshName(candidate: String): JsName = scope.declareFreshName(candidate)
|
fun getFreshName(candidate: String): JsName = scope.declareFreshName(candidate)
|
||||||
|
|
||||||
fun getFreshName(candidate: JsName): JsName = getFreshName(candidate.ident)
|
|
||||||
|
fun getTemporaryName(candidate: String): JsName = scope.declareTemporaryName(candidate)
|
||||||
|
|
||||||
|
fun getFreshName(candidate: JsName) = if (candidate.isTemporary) getTemporaryName(candidate.ident) else getFreshName(candidate.ident)
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -18,12 +18,9 @@ package org.jetbrains.kotlin.js.inline.util
|
|||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*
|
import com.google.dart.compiler.backend.js.ast.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.staticRef
|
import com.google.dart.compiler.backend.js.ast.metadata.staticRef
|
||||||
|
|
||||||
import org.jetbrains.kotlin.js.inline.util.collectors.InstanceCollector
|
import org.jetbrains.kotlin.js.inline.util.collectors.InstanceCollector
|
||||||
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
|
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.name
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
fun collectFunctionReferencesInside(scope: JsNode): List<JsName> =
|
fun collectFunctionReferencesInside(scope: JsNode): List<JsName> =
|
||||||
collectReferencedNames(scope).filter { it.staticRef is JsFunction }
|
collectReferencedNames(scope).filter { it.staticRef is JsFunction }
|
||||||
@@ -87,7 +84,7 @@ fun collectUsedNames(scope: JsNode): Set<JsName> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun collectDefinedNames(scope: JsNode): Set<JsName> {
|
fun collectDefinedNames(scope: JsNode): Set<JsName> {
|
||||||
val names: MutableMap<String, JsName> = HashMap()
|
val names = mutableSetOf<JsName>()
|
||||||
|
|
||||||
object : RecursiveJsVisitor() {
|
object : RecursiveJsVisitor() {
|
||||||
override fun visit(x: JsVars.JsVar) {
|
override fun visit(x: JsVars.JsVar) {
|
||||||
@@ -95,7 +92,7 @@ fun collectDefinedNames(scope: JsNode): Set<JsName> {
|
|||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
accept(initializer)
|
accept(initializer)
|
||||||
}
|
}
|
||||||
addNameIfNeeded(x.name)
|
names += x.name
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitExpressionStatement(x: JsExpressionStatement) {
|
override fun visitExpressionStatement(x: JsExpressionStatement) {
|
||||||
@@ -103,7 +100,7 @@ fun collectDefinedNames(scope: JsNode): Set<JsName> {
|
|||||||
if (expression is JsFunction) {
|
if (expression is JsFunction) {
|
||||||
val name = expression.name
|
val name = expression.name
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
addNameIfNeeded(name)
|
names += name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.visitExpressionStatement(x)
|
super.visitExpressionStatement(x)
|
||||||
@@ -112,16 +109,9 @@ fun collectDefinedNames(scope: JsNode): Set<JsName> {
|
|||||||
// Skip function expression, since it does not introduce name in scope of containing function.
|
// Skip function expression, since it does not introduce name in scope of containing function.
|
||||||
// The only exception is function statement, that is handled with the code above.
|
// The only exception is function statement, that is handled with the code above.
|
||||||
override fun visitFunction(x: JsFunction) { }
|
override fun visitFunction(x: JsFunction) { }
|
||||||
|
|
||||||
private fun addNameIfNeeded(name: JsName) {
|
|
||||||
val ident = name.ident
|
|
||||||
val nameCollected = names[ident]
|
|
||||||
assert(nameCollected == null || nameCollected === name) { "ambiguous identifier $name" }
|
|
||||||
names[ident] = name
|
|
||||||
}
|
|
||||||
}.accept(scope)
|
}.accept(scope)
|
||||||
|
|
||||||
return names.values.toSet()
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsFunction.collectFreeVariables() = collectUsedNames(body) - collectDefinedNames(body) - parameters.map { it.name }
|
fun JsFunction.collectFreeVariables() = collectUsedNames(body) - collectDefinedNames(body) - parameters.map { it.name }
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ fun renameLocalNames(
|
|||||||
function: JsFunction
|
function: JsFunction
|
||||||
) {
|
) {
|
||||||
for (name in collectDefinedNames(function.body)) {
|
for (name in collectDefinedNames(function.body)) {
|
||||||
val freshName = context.getFreshName(name).apply { staticRef = name.staticRef }
|
val temporaryName = context.getTemporaryName(name.ident).apply { staticRef = name.staticRef }
|
||||||
context.replaceName(name, freshName.makeRef())
|
context.replaceName(name, temporaryName.makeRef())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ abstract class BasicOptimizerTest(private var basePath: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkOptimizer(unoptimizedCode: String, optimizedCode: String) {
|
private fun checkOptimizer(unoptimizedCode: String, optimizedCode: String) {
|
||||||
val parserScope = JsFunctionScope(JsRootScope(JsProgram("<js checker>")), "<js fun>")
|
val parserScope = JsFunctionScope(JsRootScope(JsProgram()), "<js fun>")
|
||||||
val unoptimizedAst = parse(unoptimizedCode, errorReporter, parserScope)
|
val unoptimizedAst = parse(unoptimizedCode, errorReporter, parserScope)
|
||||||
|
|
||||||
updateMetadata(unoptimizedCode, unoptimizedAst)
|
updateMetadata(unoptimizedCode, unoptimizedAst)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
|||||||
import org.jetbrains.kotlin.js.inline.JsInliner;
|
import org.jetbrains.kotlin.js.inline.JsInliner;
|
||||||
import org.jetbrains.kotlin.js.translate.context.StaticContext;
|
import org.jetbrains.kotlin.js.translate.context.StaticContext;
|
||||||
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
||||||
|
import org.jetbrains.kotlin.js.inline.clean.ResolveTemporaryNamesKt;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation;
|
import org.jetbrains.kotlin.js.translate.general.Translation;
|
||||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||||
@@ -85,6 +86,7 @@ public final class K2JSTranslator {
|
|||||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||||
|
|
||||||
JsProgram program = JsInliner.process(context);
|
JsProgram program = JsInliner.process(context);
|
||||||
|
ResolveTemporaryNamesKt.resolveTemporaryNames(program);
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.context;
|
package org.jetbrains.kotlin.js.translate.context;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import gnu.trove.THashMap;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
@@ -32,10 +31,10 @@ public class AliasingContext {
|
|||||||
return new AliasingContext(null, null, null);
|
return new AliasingContext(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nullable
|
||||||
private final Map<DeclarationDescriptor, JsExpression> aliasesForDescriptors;
|
private final Map<DeclarationDescriptor, JsExpression> aliasesForDescriptors;
|
||||||
|
|
||||||
@NotNull
|
@Nullable
|
||||||
private final Map<KtExpression, JsExpression> aliasesForExpressions;
|
private final Map<KtExpression, JsExpression> aliasesForExpressions;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -47,8 +46,8 @@ public class AliasingContext {
|
|||||||
@Nullable Map<KtExpression, JsExpression> aliasesForExpressions
|
@Nullable Map<KtExpression, JsExpression> aliasesForExpressions
|
||||||
) {
|
) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.aliasesForDescriptors = aliasesForDescriptors == null ? Collections.<DeclarationDescriptor, JsExpression>emptyMap() : aliasesForDescriptors;
|
this.aliasesForDescriptors = aliasesForDescriptors;
|
||||||
this.aliasesForExpressions = aliasesForExpressions == null ? Collections.<KtExpression, JsExpression>emptyMap() : aliasesForExpressions;
|
this.aliasesForExpressions = aliasesForExpressions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -74,13 +73,13 @@ public class AliasingContext {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
// these aliases cannot be shared and applicable only in current context
|
// these aliases cannot be shared and applicable only in current context
|
||||||
JsExpression alias = aliasesForDescriptors.get(descriptor.getOriginal());
|
JsExpression alias = aliasesForDescriptors != null ? aliasesForDescriptors.get(descriptor.getOriginal()) : null;
|
||||||
return alias != null || parent == null ? alias : parent.getAliasForDescriptor(descriptor);
|
return alias != null || parent == null ? alias : parent.getAliasForDescriptor(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JsExpression getAliasForExpression(@NotNull KtExpression element) {
|
public JsExpression getAliasForExpression(@NotNull KtExpression element) {
|
||||||
JsExpression alias = aliasesForExpressions.get(element);
|
JsExpression alias = aliasesForExpressions != null ? aliasesForExpressions.get(element) : null;
|
||||||
return alias != null || parent == null ? alias : parent.getAliasForExpression(element);
|
return alias != null || parent == null ? alias : parent.getAliasForExpression(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -105,7 +105,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.rootFunction.scope, JsBlock(statements), "$declaration setter")
|
val function = JsFunction(context.rootFunction.scope, JsBlock(statements), "$declaration setter")
|
||||||
val valueName = function.scope.declareFreshName("value")
|
val valueName = function.scope.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
|
||||||
@@ -125,7 +125,7 @@ internal class DeclarationExporter(val context: StaticContext) {
|
|||||||
}
|
}
|
||||||
var name = localPackageNames[packageName]
|
var name = localPackageNames[packageName]
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = context.rootFunction.scope.declareFreshName("package$" + packageName.shortName().asString())
|
name = context.rootFunction.scope.declareTemporaryName("package$" + packageName.shortName().asString())
|
||||||
localPackageNames.put(packageName, name)
|
localPackageNames.put(packageName, name)
|
||||||
|
|
||||||
val parentRef = getLocalPackageReference(packageName.parent())
|
val parentRef = getLocalPackageReference(packageName.parent())
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.dart.compiler.backend.js.ast.JsScopesKt.JsObjectScope;
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName;
|
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName;
|
||||||
|
|
||||||
@@ -127,7 +126,9 @@ public final class Namer {
|
|||||||
qualifier = fqNameParent.asString();
|
qualifier = fqNameParent.asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
String mangledName = new NameSuggestion().suggest(functionDescriptor).getNames().get(0);
|
SuggestedName suggestedName = new NameSuggestion().suggest(functionDescriptor);
|
||||||
|
assert suggestedName != null : "Suggested name can be null only for module descriptors: " + functionDescriptor;
|
||||||
|
String mangledName = suggestedName.getNames().get(0);
|
||||||
return StringUtil.join(Arrays.asList(moduleName, qualifier, mangledName), ".");
|
return StringUtil.join(Arrays.asList(moduleName, qualifier, mangledName), ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +227,7 @@ public final class Namer {
|
|||||||
private final JsName isTypeName;
|
private final JsName isTypeName;
|
||||||
|
|
||||||
private Namer(@NotNull JsScope rootScope) {
|
private Namer(@NotNull JsScope rootScope) {
|
||||||
kotlinScope = JsObjectScope(rootScope, "Kotlin standard object");
|
kotlinScope = new JsObjectScope(rootScope, "Kotlin standard object");
|
||||||
|
|
||||||
callGetProperty = kotlin("callGetter");
|
callGetProperty = kotlin("callGetter");
|
||||||
callSetProperty = kotlin("callSetter");
|
callSetProperty = kotlin("callSetter");
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public final class StaticContext {
|
|||||||
@NotNull BindingTrace bindingTrace,
|
@NotNull BindingTrace bindingTrace,
|
||||||
@NotNull JsConfig config,
|
@NotNull JsConfig config,
|
||||||
@NotNull ModuleDescriptor moduleDescriptor) {
|
@NotNull ModuleDescriptor moduleDescriptor) {
|
||||||
JsProgram program = new JsProgram("main");
|
JsProgram program = new JsProgram();
|
||||||
Namer namer = Namer.newInstance(program.getRootScope());
|
Namer namer = Namer.newInstance(program.getRootScope());
|
||||||
JsFunction rootFunction = JsAstUtils.createFunctionWithEmptyBody(program.getScope());
|
JsFunction rootFunction = JsAstUtils.createFunctionWithEmptyBody(program.getScope());
|
||||||
return new StaticContext(program, rootFunction, bindingTrace, namer, program.getRootScope(), config, moduleDescriptor);
|
return new StaticContext(program, rootFunction, bindingTrace, namer, program.getRootScope(), config, moduleDescriptor);
|
||||||
@@ -146,6 +146,9 @@ public final class StaticContext {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final Set<ClassDescriptor> classes = new LinkedHashSet<ClassDescriptor>();
|
private final Set<ClassDescriptor> classes = new LinkedHashSet<ClassDescriptor>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Map<FqName, JsScope> packageScopes = new HashMap<FqName, JsScope>();
|
||||||
|
|
||||||
//TODO: too many parameters in constructor
|
//TODO: too many parameters in constructor
|
||||||
private StaticContext(
|
private StaticContext(
|
||||||
@NotNull JsProgram program,
|
@NotNull JsProgram program,
|
||||||
@@ -165,7 +168,7 @@ public final class StaticContext {
|
|||||||
this.config = config;
|
this.config = config;
|
||||||
this.currentModule = moduleDescriptor;
|
this.currentModule = moduleDescriptor;
|
||||||
this.rootFunction = rootFunction;
|
this.rootFunction = rootFunction;
|
||||||
rootPackageScope = new JsObjectScope(rootScope, "<root package>", "root-package");
|
rootPackageScope = new JsObjectScope(rootScope, "<root package>");
|
||||||
|
|
||||||
JsName kotlinName = rootScope.declareName(Namer.KOTLIN_NAME);
|
JsName kotlinName = rootScope.declareName(Namer.KOTLIN_NAME);
|
||||||
importedModules.put(new ImportedModuleKey(Namer.KOTLIN_LOWER_NAME, null),
|
importedModules.put(new ImportedModuleKey(Namer.KOTLIN_LOWER_NAME, null),
|
||||||
@@ -362,10 +365,15 @@ public final class StaticContext {
|
|||||||
JsName name = nameCache.get(suggested.getDescriptor());
|
JsName name = nameCache.get(suggested.getDescriptor());
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
String baseName = suggested.getNames().get(0);
|
String baseName = suggested.getNames().get(0);
|
||||||
if (!DescriptorUtils.isDescriptorWithLocalVisibility(suggested.getDescriptor())) {
|
if (suggested.getDescriptor() instanceof LocalVariableDescriptor) {
|
||||||
baseName += "_0";
|
name = scope.declareTemporaryName(baseName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!DescriptorUtils.isDescriptorWithLocalVisibility(suggested.getDescriptor())) {
|
||||||
|
baseName += "_0";
|
||||||
|
}
|
||||||
|
name = scope.declareFreshName(baseName);
|
||||||
}
|
}
|
||||||
name = scope.declareFreshName(baseName);
|
|
||||||
}
|
}
|
||||||
nameCache.put(suggested.getDescriptor(), name);
|
nameCache.put(suggested.getDescriptor(), name);
|
||||||
names.add(name);
|
names.add(name);
|
||||||
@@ -425,7 +433,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 = rootFunction.getScope().declareFreshName("imported$" + suggestedName);
|
JsName result = rootFunction.getScope().declareTemporaryName(suggestedName);
|
||||||
MetadataProperties.setImported(result, true);
|
MetadataProperties.setImported(result, true);
|
||||||
importStatements.add(JsAstUtils.newVar(result, declaration));
|
importStatements.add(JsAstUtils.newVar(result, declaration));
|
||||||
return result;
|
return result;
|
||||||
@@ -436,7 +444,7 @@ public final class StaticContext {
|
|||||||
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
|
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
|
||||||
return module != currentModule ?
|
return module != currentModule ?
|
||||||
importDeclaration(suggestedName, getQualifiedReference(descriptor)) :
|
importDeclaration(suggestedName, getQualifiedReference(descriptor)) :
|
||||||
rootFunction.getScope().declareFreshName(suggestedName);
|
rootFunction.getScope().declareTemporaryName(suggestedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class InnerNameGenerator extends Generator<JsName> {
|
private final class InnerNameGenerator extends Generator<JsName> {
|
||||||
@@ -529,6 +537,21 @@ public final class StaticContext {
|
|||||||
return suggestedName;
|
return suggestedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JsScope getScopeForPackage(FqName fqName) {
|
||||||
|
JsScope scope = packageScopes.get(fqName);
|
||||||
|
if (scope == null) {
|
||||||
|
if (fqName.isRoot()) {
|
||||||
|
scope = new JsRootScope(program);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JsScope parentScope = getScopeForPackage(fqName.parent());
|
||||||
|
scope = parentScope.innerObjectScope(fqName.shortName().asString());
|
||||||
|
}
|
||||||
|
packageScopes.put(fqName, scope);
|
||||||
|
}
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
private final class ScopeGenerator extends Generator<JsScope> {
|
private final class ScopeGenerator extends Generator<JsScope> {
|
||||||
|
|
||||||
public ScopeGenerator() {
|
public ScopeGenerator() {
|
||||||
@@ -539,7 +562,7 @@ public final class StaticContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (getSuperclass((ClassDescriptor) descriptor) == null) {
|
if (getSuperclass((ClassDescriptor) descriptor) == null) {
|
||||||
JsFunction function = new JsFunction(rootFunction.getScope(), new JsBlock(), descriptor.toString());
|
JsFunction function = new JsFunction(new JsRootScope(program), new JsBlock(), descriptor.toString());
|
||||||
scopeToFunction.put(function.getScope(), function);
|
scopeToFunction.put(function.getScope(), function);
|
||||||
return function.getScope();
|
return function.getScope();
|
||||||
}
|
}
|
||||||
@@ -585,6 +608,17 @@ public final class StaticContext {
|
|||||||
return correspondingFunction.getScope();
|
return correspondingFunction.getScope();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Rule<JsScope> scopeForPackage = new Rule<JsScope>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public JsScope apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
if (!(descriptor instanceof PackageFragmentDescriptor)) return null;
|
||||||
|
|
||||||
|
PackageFragmentDescriptor packageDescriptor = (PackageFragmentDescriptor) descriptor;
|
||||||
|
return getScopeForPackage(packageDescriptor.getFqName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addRule(scopeForPackage);
|
||||||
addRule(createFunctionObjectsForCallableDescriptors);
|
addRule(createFunctionObjectsForCallableDescriptors);
|
||||||
addRule(generateNewScopesForClassesWithNoAncestors);
|
addRule(generateNewScopesForClassesWithNoAncestors);
|
||||||
addRule(generateInnerScopesForDerivedClasses);
|
addRule(generateInnerScopesForDerivedClasses);
|
||||||
@@ -625,7 +659,7 @@ public final class StaticContext {
|
|||||||
|
|
||||||
ImportedModule module = importedModules.get(key);
|
ImportedModule module = importedModules.get(key);
|
||||||
if (module == null) {
|
if (module == null) {
|
||||||
JsName internalName = rootScope.declareFreshName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(baseName));
|
JsName internalName = rootScope.declareTemporaryName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(baseName));
|
||||||
JsName plainName = descriptor != null ? rootScope.declareName(getPlainId(descriptor)) : null;
|
JsName plainName = descriptor != null ? rootScope.declareName(getPlainId(descriptor)) : null;
|
||||||
module = new ImportedModule(baseName, internalName, plainName != null ? pureFqn(plainName, null) : null);
|
module = new ImportedModule(baseName, internalName, plainName != null ? pureFqn(plainName, null) : null);
|
||||||
importedModules.put(key, module);
|
importedModules.put(key, module);
|
||||||
|
|||||||
+1
-1
@@ -607,7 +607,7 @@ public class TranslationContext {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName createGlobalName(@NotNull String suggestedName) {
|
public JsName createGlobalName(@NotNull String suggestedName) {
|
||||||
return staticContext.getRootFunction().getScope().declareFreshName(suggestedName);
|
return staticContext.getRootFunction().getScope().declareTemporaryName(suggestedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ class UsageTracker(
|
|||||||
|
|
||||||
// local named function
|
// local named function
|
||||||
if (descriptor is FunctionDescriptor && descriptor.visibility == Visibilities.LOCAL) {
|
if (descriptor is FunctionDescriptor && descriptor.visibility == Visibilities.LOCAL) {
|
||||||
assert(descriptor.isCoroutineLambda || !descriptor.getName().isSpecial) {
|
|
||||||
"Function with special name can not be captured, descriptor: $descriptor"
|
|
||||||
}
|
|
||||||
captureIfNeed(descriptor)
|
captureIfNeed(descriptor)
|
||||||
}
|
}
|
||||||
// local variable
|
// local variable
|
||||||
|
|||||||
+4
-4
@@ -150,8 +150,8 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addEnumClassParameters(constructorFunction: JsFunction) {
|
private fun addEnumClassParameters(constructorFunction: JsFunction) {
|
||||||
val nameParamName = constructorFunction.scope.declareFreshName("name")
|
val nameParamName = constructorFunction.scope.declareTemporaryName("name")
|
||||||
val ordinalParamName = constructorFunction.scope.declareFreshName("ordinal")
|
val ordinalParamName = constructorFunction.scope.declareTemporaryName("ordinal")
|
||||||
constructorFunction.parameters.addAll(0, listOf(JsParameter(nameParamName), JsParameter(ordinalParamName)))
|
constructorFunction.parameters.addAll(0, listOf(JsParameter(nameParamName), JsParameter(ordinalParamName)))
|
||||||
|
|
||||||
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef())
|
constructorFunction.body.statements += JsAstUtils.assignmentToThisField(Namer.ENUM_NAME_FIELD, nameParamName.makeRef())
|
||||||
@@ -232,8 +232,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.declareFreshName("name")
|
val nameParamName = constructorInitializer.scope.declareTemporaryName("name")
|
||||||
val ordinalParamName = constructorInitializer.scope.declareFreshName("ordinal")
|
val ordinalParamName = constructorInitializer.scope.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())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ class EnumTranslator(
|
|||||||
private fun generateValueOfFunction() {
|
private fun generateValueOfFunction() {
|
||||||
val function = createFunction(getEnumFunction(DescriptorUtils.ENUM_VALUE_OF))
|
val function = createFunction(getEnumFunction(DescriptorUtils.ENUM_VALUE_OF))
|
||||||
|
|
||||||
val nameParam = function.scope.declareFreshName("name")
|
val nameParam = function.scope.declareTemporaryName("name")
|
||||||
function.parameters += JsParameter(nameParam)
|
function.parameters += JsParameter(nameParam)
|
||||||
|
|
||||||
val clauses = entries.map { entry ->
|
val clauses = entries.map { entry ->
|
||||||
|
|||||||
+9
-8
@@ -17,13 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.declaration;
|
package org.jetbrains.kotlin.js.translate.declaration;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
|
||||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationRuntimeException;
|
import org.jetbrains.kotlin.js.facade.exceptions.TranslationRuntimeException;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@@ -42,13 +42,14 @@ public final class PackageDeclarationTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
private void translate() {
|
private void translate() {
|
||||||
for (KtFile file : files) {
|
for (KtFile file : files) {
|
||||||
PackageFragmentDescriptor packageFragment =
|
FileDeclarationVisitor fileVisitor = new FileDeclarationVisitor(context());
|
||||||
BindingContextUtils.getNotNull(context().bindingContext(), BindingContext.FILE_TO_PACKAGE_FRAGMENT, file);
|
|
||||||
|
|
||||||
PackageTranslator translator = PackageTranslator.create(packageFragment, context());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
translator.translate(file);
|
for (KtDeclaration declaration : file.getDeclarations()) {
|
||||||
|
if (!AnnotationsUtils.isPredefinedObject(BindingUtils.getDescriptorForElement(bindingContext(), declaration))) {
|
||||||
|
declaration.accept(fileVisitor, context());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (TranslationRuntimeException e) {
|
catch (TranslationRuntimeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
-55
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 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 org.jetbrains.kotlin.js.translate.declaration;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
|
||||||
|
|
||||||
final class PackageTranslator extends AbstractTranslator {
|
|
||||||
static PackageTranslator create(
|
|
||||||
@NotNull PackageFragmentDescriptor descriptor,
|
|
||||||
@NotNull TranslationContext context
|
|
||||||
) {
|
|
||||||
TranslationContext newContext = context.newDeclaration(descriptor);
|
|
||||||
FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext);
|
|
||||||
return new PackageTranslator(newContext, visitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final FileDeclarationVisitor visitor;
|
|
||||||
|
|
||||||
private PackageTranslator(
|
|
||||||
@NotNull TranslationContext context,
|
|
||||||
@NotNull FileDeclarationVisitor visitor
|
|
||||||
) {
|
|
||||||
super(context);
|
|
||||||
this.visitor = visitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void translate(KtFile file) {
|
|
||||||
for (KtDeclaration declaration : file.getDeclarations()) {
|
|
||||||
if (!AnnotationsUtils.isPredefinedObject(BindingUtils.getDescriptorForElement(bindingContext(), declaration))) {
|
|
||||||
declaration.accept(visitor, context());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+5
-7
@@ -460,13 +460,14 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
JsExpression alias = new LiteralFunctionTranslator(context).translate(expression, null, null);
|
JsExpression alias = new LiteralFunctionTranslator(context).translate(expression, null, null);
|
||||||
|
|
||||||
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
||||||
JsName name = context.getNameForDescriptor(descriptor);
|
JsNameRef nameRef = (JsNameRef) ReferenceTranslator.translateAsValueReference(descriptor, context);
|
||||||
|
assert nameRef.getName() != null;
|
||||||
if (InlineUtil.isInline(descriptor)) {
|
if (InlineUtil.isInline(descriptor)) {
|
||||||
MetadataProperties.setStaticRef(name, alias);
|
MetadataProperties.setStaticRef(nameRef.getName(), alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isExpression = BindingContextUtilsKt.isUsedAsExpression(expression, context.bindingContext());
|
boolean isExpression = BindingContextUtilsKt.isUsedAsExpression(expression, context.bindingContext());
|
||||||
JsNode result = isExpression ? alias : JsAstUtils.newVar(name, alias);
|
JsNode result = isExpression ? alias : JsAstUtils.newVar(nameRef.getName(), alias);
|
||||||
|
|
||||||
return result.source(expression);
|
return result.source(expression);
|
||||||
}
|
}
|
||||||
@@ -552,10 +553,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
|||||||
ResolvedCall<FunctionDescriptor> superCall = BindingUtils.getSuperCall(context.bindingContext(),
|
ResolvedCall<FunctionDescriptor> superCall = BindingUtils.getSuperCall(context.bindingContext(),
|
||||||
expression.getObjectDeclaration());
|
expression.getObjectDeclaration());
|
||||||
if (superCall != null) {
|
if (superCall != null) {
|
||||||
assert context.getDeclarationDescriptor() != null : "This expression should be inside declaration: " +
|
closureArgs.addAll(CallArgumentTranslator.translate(superCall, null, context).getTranslateArguments());
|
||||||
PsiUtilsKt.getTextWithLocation(expression);
|
|
||||||
TranslationContext superCallContext = context.newDeclaration(context.getDeclarationDescriptor());
|
|
||||||
closureArgs.addAll(CallArgumentTranslator.translate(superCall, null, superCallContext).getTranslateArguments());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JsNew(constructor, closureArgs);
|
return new JsNew(constructor, closureArgs);
|
||||||
|
|||||||
+15
-4
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.translate.context.AliasingContext;
|
|||||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
import org.jetbrains.kotlin.js.translate.context.Namer;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
|
import org.jetbrains.kotlin.psi.KtDeclarationWithBody;
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||||
@@ -78,17 +79,27 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TranslationContext getFunctionBodyContext() {
|
private TranslationContext getFunctionBodyContext() {
|
||||||
AliasingContext aliasingContext;
|
Map<DeclarationDescriptor, JsExpression> aliases = new HashMap<DeclarationDescriptor, JsExpression>();
|
||||||
if (isExtensionFunction()) {
|
if (isExtensionFunction()) {
|
||||||
DeclarationDescriptor expectedReceiverDescriptor = descriptor.getExtensionReceiverParameter();
|
DeclarationDescriptor expectedReceiverDescriptor = descriptor.getExtensionReceiverParameter();
|
||||||
assert expectedReceiverDescriptor != null;
|
assert expectedReceiverDescriptor != null;
|
||||||
extensionFunctionReceiverName = functionObject.getScope().declareName(Namer.getReceiverParameterName());
|
extensionFunctionReceiverName = functionObject.getScope().declareName(Namer.getReceiverParameterName());
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
aliasingContext = context().aliasingContext().inner(expectedReceiverDescriptor, extensionFunctionReceiverName.makeRef());
|
aliases.put(expectedReceiverDescriptor, extensionFunctionReceiverName.makeRef());
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
aliasingContext = null;
|
LocalFunctionCollector functionCollector = new LocalFunctionCollector(context().bindingContext());
|
||||||
|
functionDeclaration.acceptChildren(functionCollector, null);
|
||||||
|
for (FunctionDescriptor localFunction : functionCollector.getFunctions()) {
|
||||||
|
String localIdent = localFunction.getName().isSpecial() ? "lambda" : localFunction.getName().asString();
|
||||||
|
JsName localName = functionObject.getScope().getParent().declareTemporaryName(localIdent);
|
||||||
|
JsExpression alias = JsAstUtils.pureFqn(localName, null);
|
||||||
|
aliases.put(localFunction, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AliasingContext aliasingContext = !aliases.isEmpty() ? context().aliasingContext().withDescriptorsAliased(aliases) : null;
|
||||||
|
|
||||||
|
|
||||||
return context().newFunctionBody(functionObject, aliasingContext, descriptor);
|
return context().newFunctionBody(functionObject, aliasingContext, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -264,7 +264,7 @@ private fun moveCapturedLocalInside(capturingFunction: JsFunction, capturedName:
|
|||||||
val capturedArgs = localFunAlias.arguments
|
val capturedArgs = localFunAlias.arguments
|
||||||
|
|
||||||
val scope = capturingFunction.getInnerFunction()?.scope!!
|
val scope = capturingFunction.getInnerFunction()?.scope!!
|
||||||
val freshNames = getFreshNamesInScope(scope, capturedArgs)
|
val freshNames = getTemporaryNamesInScope(scope, capturedArgs)
|
||||||
|
|
||||||
val aliasCallArguments = freshNames.map { it.makeRef() }
|
val aliasCallArguments = freshNames.map { it.makeRef() }
|
||||||
val alias = JsInvocation(localFunAlias.qualifier, aliasCallArguments)
|
val alias = JsInvocation(localFunAlias.qualifier, aliasCallArguments)
|
||||||
@@ -279,7 +279,7 @@ private fun declareAliasInsideFunction(function: JsFunction, name: JsName, alias
|
|||||||
function.getInnerFunction()?.addDeclaration(name, alias)
|
function.getInnerFunction()?.addDeclaration(name, alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFreshNamesInScope(scope: JsScope, suggested: List<JsExpression>): List<JsName> {
|
private fun getTemporaryNamesInScope(scope: JsScope, suggested: List<JsExpression>): List<JsName> {
|
||||||
val freshNames = arrayListOf<JsName>()
|
val freshNames = arrayListOf<JsName>()
|
||||||
|
|
||||||
for (suggestion in suggested) {
|
for (suggestion in suggested) {
|
||||||
@@ -288,7 +288,7 @@ private fun getFreshNamesInScope(scope: JsScope, suggested: List<JsExpression>):
|
|||||||
}
|
}
|
||||||
|
|
||||||
val ident = suggestion.ident
|
val ident = suggestion.ident
|
||||||
val name = scope.declareFreshName(ident)
|
val name = scope.declareTemporaryName(ident)
|
||||||
freshNames.add(name)
|
freshNames.add(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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 org.jetbrains.kotlin.js.translate.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
|
class LocalFunctionCollector(val bindingContext: BindingContext) : KtVisitorVoid() {
|
||||||
|
val functions = mutableSetOf<FunctionDescriptor>()
|
||||||
|
|
||||||
|
override fun visitExpression(expression: KtExpression) {
|
||||||
|
if (expression is KtDeclarationWithBody) {
|
||||||
|
functions += BindingUtils.getFunctionDescriptor(bindingContext, expression)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expression.acceptChildren(this, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||||
|
// skip
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -122,7 +122,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
|||||||
// but no new global ones.
|
// but no new global ones.
|
||||||
JsScope currentScope = context().scope();
|
JsScope currentScope = context().scope();
|
||||||
assert currentScope instanceof JsFunctionScope : "Usage of js outside of function is unexpected";
|
assert currentScope instanceof JsFunctionScope : "Usage of js outside of function is unexpected";
|
||||||
JsScope temporaryRootScope = new JsRootScope(new JsProgram("<js code>"));
|
JsScope temporaryRootScope = new JsRootScope(new JsProgram());
|
||||||
JsScope scope = new DelegatingJsFunctionScopeWithTemporaryParent((JsFunctionScope) currentScope, temporaryRootScope);
|
JsScope scope = new DelegatingJsFunctionScopeWithTemporaryParent((JsFunctionScope) currentScope, temporaryRootScope);
|
||||||
return ParserUtilsKt.parse(jsCode, ThrowExceptionOnErrorReporter.INSTANCE, scope);
|
return ParserUtilsKt.parse(jsCode, ThrowExceptionOnErrorReporter.INSTANCE, scope);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -153,7 +153,7 @@ object CallableReferenceTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val function = context.createRootScopedFunction(setter)
|
val function = context.createRootScopedFunction(setter)
|
||||||
val valueParam = function.scope.declareFreshName("value")
|
val valueParam = function.scope.declareTemporaryName("value")
|
||||||
function.parameters += JsParameter(valueParam)
|
function.parameters += JsParameter(valueParam)
|
||||||
|
|
||||||
val expression = if (TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
val expression = if (TranslationUtils.shouldAccessViaFunctions(descriptor)) {
|
||||||
|
|||||||
@@ -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.declareFreshName(identifier)
|
val name = scope.declareTemporaryName(identifier)
|
||||||
val parameter = JsParameter(name)
|
val parameter = JsParameter(name)
|
||||||
|
|
||||||
if (index == null) {
|
if (index == null) {
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ fun generateDelegateCall(
|
|||||||
val functionScope = context.getScopeForDescriptor(fromDescriptor)
|
val functionScope = context.getScopeForDescriptor(fromDescriptor)
|
||||||
|
|
||||||
if (DescriptorUtils.isExtension(fromDescriptor)) {
|
if (DescriptorUtils.isExtension(fromDescriptor)) {
|
||||||
val extensionFunctionReceiverName = functionScope.declareFreshName(Namer.getReceiverParameterName())
|
val extensionFunctionReceiverName = functionScope.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.declareFreshName(paramName)
|
val jsParamName = functionScope.declareTemporaryName(paramName)
|
||||||
parameters.add(JsParameter(jsParamName))
|
parameters.add(JsParameter(jsParamName))
|
||||||
args.add(JsNameRef(jsParamName))
|
args.add(JsNameRef(jsParamName))
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -6,29 +6,29 @@ fun fail(message: String? = null): Nothing = js("throw new Error(message)")
|
|||||||
|
|
||||||
fun <T> assertEquals(expected: T, actual: T, message: String? = null) {
|
fun <T> assertEquals(expected: T, actual: T, message: String? = null) {
|
||||||
if (expected != actual) {
|
if (expected != actual) {
|
||||||
val msg = if (message == null) "" else (" message = '" + message + "',")
|
val msg = if (message == null) "" else ", message = '$message'"
|
||||||
fail("Unexpected value:$msg expected = '$expected', actual = '$actual'")
|
fail("Unexpected value: expected = '$expected', actual = '$actual'$msg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> assertNotEquals(illegal: T, actual: T, message: String? = null) {
|
fun <T> assertNotEquals(illegal: T, actual: T, message: String? = null) {
|
||||||
if (illegal == actual) {
|
if (illegal == actual) {
|
||||||
val msg = if (message == null) "" else (" message = '" + message + "',")
|
val msg = if (message == null) "" else ", message = '$message'"
|
||||||
fail("Illegal value:$msg illegal = '$illegal', actual = '$actual'")
|
fail("Illegal value: illegal = '$illegal', actual = '$actual'$msg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> assertSame(expected: T, actual: T, message: String? = null) {
|
fun <T> assertSame(expected: T, actual: T, message: String? = null) {
|
||||||
if (expected !== actual) {
|
if (expected !== actual) {
|
||||||
val msg = if (message == null) "" else (" message = '" + message + "',")
|
val msg = if (message == null) "" else ", message = '$message'"
|
||||||
fail("Expected same instances, got expected = '$expected', actual = '$actual'")
|
fail("Expected same instances: expected = '$expected', actual = '$actual'$msg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> assertArrayEquals(expected: Array<out T>, actual: Array<out T>, message: String? = null) {
|
fun <T> assertArrayEquals(expected: Array<out T>, actual: Array<out T>, message: String? = null) {
|
||||||
if (!arraysEqual(expected, actual)) {
|
if (!arraysEqual(expected, actual)) {
|
||||||
val msg = if (message == null) "" else (" message = '" + message + "',")
|
val msg = if (message == null) "" else ", message = '$message'"
|
||||||
fail("Unexpected array:$msg expected = '$expected', actual = '$actual'")
|
fail("Unexpected array: expected = '$expected', actual = '$actual'$msg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user