diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/FunctionInlineMutator.java b/js/js.inliner/src/org/jetbrains/k2js/inline/FunctionInlineMutator.java index c088b6f1a17..532e9f18aeb 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/FunctionInlineMutator.java +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/FunctionInlineMutator.java @@ -19,6 +19,7 @@ package org.jetbrains.k2js.inline; import com.google.dart.compiler.backend.js.ast.*; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.k2js.inline.context.*; import static org.jetbrains.k2js.inline.util.UtilPackage.collectInstances; import static org.jetbrains.k2js.inline.util.UtilPackage.replaceReturns; import static org.jetbrains.k2js.inline.util.UtilPackage.replaceThisReference; @@ -32,10 +33,10 @@ class FunctionInlineMutator { private final JsInvocation call; private final InliningContext inliningContext; + private final FunctionContext functionContext; private final JsFunction invokedFunction; private final boolean isResultNeeded; - private final RenamingContext renamingContext; - private final InsertionPoint insertionPoint; + private final NamingContext namingContext; private JsBlock body; private JsExpression resultExpr = null; private JsLabel breakLabel = null; @@ -65,12 +66,11 @@ class FunctionInlineMutator { this.inliningContext = inliningContext; this.call = call; - FunctionContext functionContext = inliningContext.getFunctionContext(); + functionContext = inliningContext.getFunctionContext(); invokedFunction = functionContext.getFunctionDefinition(call); body = invokedFunction.getBody().deepCopy(); - isResultNeeded = inliningContext.isResultNeeded(call); - renamingContext = inliningContext.getRenamingContext(); - insertionPoint = inliningContext.getStatementContext().getInsertionPoint(); + isResultNeeded = isResultNeeded(call); + namingContext = inliningContext.newNamingContext(); } private void process() { @@ -79,15 +79,14 @@ class FunctionInlineMutator { replaceThis(); removeRedundantDefaultInitializers(arguments, parameters, body); - aliasArgumentsIfNeeded(renamingContext, arguments, parameters); - renameLocalNames(renamingContext, invokedFunction); + aliasArgumentsIfNeeded(namingContext, arguments, parameters); + renameLocalNames(namingContext, invokedFunction); if (canBeExpression(body)) { - applyRenaming(); doDirectInline(); } else { processReturns(); - applyRenaming(); + namingContext.applyRenameTo(body); } } @@ -98,21 +97,14 @@ class FunctionInlineMutator { if (thisReplacement == null) return; if (needToAlias(thisReplacement)) { - JsName thisName = renamingContext.getFreshName(getThisAlias()); - renamingContext.newVar(thisName, thisReplacement); + JsName thisName = namingContext.getFreshName(getThisAlias()); + namingContext.newVar(thisName, thisReplacement); thisReplacement = thisName.makeRef(); } replaceThisReference(body, thisReplacement); } - private void applyRenaming() { - RenamingResult renamingResult = renamingContext.applyRename(body); - body = renamingResult.getRenamed(); - Collection declarations = renamingResult.getDeclarations(); - insertionPoint.insertAllBefore(declarations); - } - private void processReturns() { int returnCount = collectInstances(JsReturn.class, body).size(); if (returnCount == 0) { @@ -133,8 +125,8 @@ class FunctionInlineMutator { boolean hasReturnOnTopLevel = returnOnTop != null; if (isResultNeeded) { - JsName resultName = renamingContext.getFreshName(getResultLabel()); - renamingContext.newVar(resultName, null); + JsName resultName = namingContext.getFreshName(getResultLabel()); + namingContext.newVar(resultName, null); resultExpr = resultName.makeRef(); } @@ -142,7 +134,7 @@ class FunctionInlineMutator { JsNameRef breakLabelRef = null; if (needBreakLabel) { - JsName breakName = renamingContext.getFreshName(getBreakLabel()); + JsName breakName = namingContext.getFreshName(getBreakLabel()); breakLabelRef = breakName.makeRef(); breakLabel = new JsLabel(breakName); } @@ -153,7 +145,19 @@ class FunctionInlineMutator { @NotNull private List getArguments() { - return inliningContext.getArguments(call); + List arguments = call.getArguments(); + if (isCallInvocation(call)) { + return arguments.subList(1, arguments.size()); + } + + return arguments; + } + + private boolean isResultNeeded(JsInvocation call) { + StatementContext statementContext = inliningContext.getStatementContext(); + JsStatement currentStatement = statementContext.getCurrentStatement(); + return !(currentStatement instanceof JsExpressionStatement) + || call != ((JsExpressionStatement) currentStatement).getExpression(); } @NotNull diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/InsertionPoint.java b/js/js.inliner/src/org/jetbrains/k2js/inline/InsertionPoint.java deleted file mode 100644 index 60bc1fccd4d..00000000000 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/InsertionPoint.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 org.jetbrains.k2js.inline; - -import com.google.dart.compiler.backend.js.ast.JsContext; -import com.google.dart.compiler.backend.js.ast.JsNode; -import com.intellij.util.containers.ContainerUtil; - -import java.util.Collection; -import java.util.List; - -class InsertionPoint { - - private final JsContext context; - - InsertionPoint(JsContext insertionContext) { - context = insertionContext; - } - - public void insertBefore(T node) { - context.insertBefore(node); - } - - public void insertAfter(T node) { - context.insertAfter(node); - } - - public void insertAllBefore(Collection nodes) { - for (T node : nodes) { - insertBefore(node); - } - } - - public void insertAllAfter(List nodes) { - for (T node : ContainerUtil.reverse(nodes)) { - insertAfter(node); - } - } -} diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/JsInliner.java b/js/js.inliner/src/org/jetbrains/k2js/inline/JsInliner.java index a1ea1451eb5..579a7fff7b1 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/JsInliner.java +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/JsInliner.java @@ -19,6 +19,7 @@ package org.jetbrains.k2js.inline; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.k2js.inline.context.*; import org.jetbrains.k2js.inline.exception.InlineRecursionException; import java.util.IdentityHashMap; diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/FunctionContext.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/context/FunctionContext.kt similarity index 80% rename from js/js.inliner/src/org/jetbrains/k2js/inline/FunctionContext.kt rename to js/js.inliner/src/org/jetbrains/k2js/inline/context/FunctionContext.kt index 733a128a11a..66f26341c43 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/FunctionContext.kt +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/context/FunctionContext.kt @@ -14,12 +14,24 @@ * limitations under the License. */ -package org.jetbrains.k2js.inline +package org.jetbrains.k2js.inline.context -import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.JsEmpty +import com.google.dart.compiler.backend.js.ast.JsExpression +import com.google.dart.compiler.backend.js.ast.JsFunction +import com.google.dart.compiler.backend.js.ast.JsInvocation +import com.google.dart.compiler.backend.js.ast.JsLiteral +import com.google.dart.compiler.backend.js.ast.JsName +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.JsStatement +import org.jetbrains.k2js.inline.util.aliasArgumentsIfNeeded +import org.jetbrains.k2js.inline.util.getInnerFunction +import org.jetbrains.k2js.inline.util.getSimpleName +import org.jetbrains.k2js.inline.util.isCallInvocation +import org.jetbrains.k2js.inline.util.isFunctionCreator import com.intellij.util.containers.ContainerUtil - import java.util.IdentityHashMap abstract class FunctionContext( @@ -55,14 +67,14 @@ abstract class FunctionContext( val calls = ContainerUtil.findAll(arguments, javaClass()) for (call in calls) { - val callName = InvocationUtil.getName(call) + val callName = getSimpleName(call) if (callName == null) continue val staticRef = callName.getStaticRef() if (staticRef !is JsFunction) continue val functionCalled = staticRef as JsFunction - if (InvocationUtil.getInnerFunction(functionCalled) != null) { + if (isFunctionCreator(functionCalled)) { declareFunctionConstructorCall(call) } } @@ -107,7 +119,7 @@ abstract class FunctionContext( var callQualifier = call.getQualifier() /** remove ending `.call()` */ - if (InvocationUtil.isCallInvocation(call)) { + if (isCallInvocation(call)) { callQualifier = (callQualifier as JsNameRef).getQualifier() } @@ -158,9 +170,9 @@ abstract class FunctionContext( if (constructed is JsFunction) return constructed - val name = InvocationUtil.getName(call)!! + val name = getSimpleName(call)!! val closureCreator = lookUpStaticFunction(name)!! - val innerFunction = InvocationUtil.getInnerFunction(closureCreator)!! + val innerFunction = closureCreator.getInnerFunction()!! val withCapturedArgs = applyCapturedArgs(call, innerFunction, closureCreator) functionsWithClosure.put(call, withCapturedArgs) @@ -171,15 +183,12 @@ abstract class FunctionContext( private fun applyCapturedArgs(call: JsInvocation, inner: JsFunction, outer: JsFunction): JsFunction { val innerClone = inner.deepCopy() - val renamingContext = inliningContext.getRenamingContext() - val arguments = call.getArguments()!! + val namingContext = inliningContext.newNamingContext() + val arguments = call.getArguments() val parameters = outer.getParameters() - aliasArgumentsIfNeeded(renamingContext, arguments, parameters) - val renamingResult = renamingContext.applyRename(innerClone) + aliasArgumentsIfNeeded(namingContext, arguments, parameters) + namingContext.applyRenameTo(innerClone) - val declarations = renamingResult.declarations - val insertionPoint = inliningContext.getStatementContext().getInsertionPoint() - insertionPoint.insertAllBefore(declarations) - return renamingResult.renamed + return innerClone } } \ No newline at end of file diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/InliningContext.java b/js/js.inliner/src/org/jetbrains/k2js/inline/context/InliningContext.kt similarity index 52% rename from js/js.inliner/src/org/jetbrains/k2js/inline/InliningContext.java rename to js/js.inliner/src/org/jetbrains/k2js/inline/context/InliningContext.kt index a5adce441bf..288858edec7 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/InliningContext.java +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/context/InliningContext.kt @@ -14,28 +14,14 @@ * limitations under the License. */ -package org.jetbrains.k2js.inline; +package org.jetbrains.k2js.inline.context -import com.google.dart.compiler.backend.js.ast.*; -import org.jetbrains.annotations.NotNull; +import com.google.dart.compiler.backend.js.ast.JsNode -import java.util.List; +trait InliningContext { + public val statementContext: StatementContext + public val functionContext: FunctionContext -interface InliningContext { - @NotNull - RenamingContext getRenamingContext(); - - @NotNull - StatementContext getStatementContext(); - - @NotNull - FunctionContext getFunctionContext(); - - @NotNull - JsExpression getThisReplacement(JsInvocation call); - - @NotNull - List getArguments(JsInvocation call); - - boolean isResultNeeded(JsInvocation call); + public fun newNamingContext(): NamingContext } + diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/context/InsertionPoint.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/context/InsertionPoint.kt new file mode 100644 index 00000000000..77421713479 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/context/InsertionPoint.kt @@ -0,0 +1,44 @@ +/* + * 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 org.jetbrains.k2js.inline.context + +import com.google.dart.compiler.backend.js.ast.JsContext +import com.google.dart.compiler.backend.js.ast.JsNode +import com.intellij.util.containers.ContainerUtil + +class InsertionPoint(private val context: JsContext) { + + public fun insertBefore(node: T) { + context.insertBefore(node) + } + + public fun insertAfter(node: T) { + context.insertAfter(node) + } + + public fun insertAllBefore(nodes: Collection) { + for (node in nodes) { + insertBefore(node) + } + } + + public fun insertAllAfter(nodes: List) { + for (node in ContainerUtil.reverse(nodes)) { + insertAfter(node) + } + } +} diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/RenamingContext.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/context/NamingContext.kt similarity index 72% rename from js/js.inliner/src/org/jetbrains/k2js/inline/RenamingContext.kt rename to js/js.inliner/src/org/jetbrains/k2js/inline/context/NamingContext.kt index 5d403d448ae..e8be1961929 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/RenamingContext.kt +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/context/NamingContext.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.k2js.inline +package org.jetbrains.k2js.inline.context import com.google.dart.compiler.backend.js.ast.* import com.google.dart.compiler.backend.js.ast.JsVars.JsVar @@ -23,18 +23,24 @@ import java.util.ArrayList import java.util.IdentityHashMap import org.jetbrains.k2js.translate.utils.JsAstUtils +import org.jetbrains.k2js.inline.util.replaceNames - -data class RenamingResult(val renamed: T, val declarations: Collection) - -class RenamingContext(scope: JsScope) { - private val scope = scope +class NamingContext( + private val scope: JsScope, + private val insertionPoint: InsertionPoint +) { private val renamings = IdentityHashMap() private val declarations = ArrayList() + private var renamingApplied = false - public fun applyRename(target : T): RenamingResult { - val renamed = RenamingVisitor.rename(target, renamings) - return RenamingResult(renamed, declarations) + public fun applyRenameTo(target: JsNode): JsNode { + if (renamingApplied) throw RuntimeException("RenamingContext has been applied already") + + val result = replaceNames(target, renamings) + insertionPoint.insertAllBefore(declarations) + renamingApplied = true + + return result } public fun replaceName(name: JsName, replacement: JsExpression) { diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/StatementContext.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/context/StatementContext.kt similarity index 94% rename from js/js.inliner/src/org/jetbrains/k2js/inline/StatementContext.kt rename to js/js.inliner/src/org/jetbrains/k2js/inline/context/StatementContext.kt index 9381309c5b8..ebc36ff2240 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/StatementContext.kt +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/context/StatementContext.kt @@ -14,11 +14,10 @@ * limitations under the License. */ -package org.jetbrains.k2js.inline +package org.jetbrains.k2js.inline.context import com.google.dart.compiler.backend.js.ast.JsContext import com.google.dart.compiler.backend.js.ast.JsStatement -import com.google.dart.compiler.backend.js.ast.JsNode abstract class StatementContext { public abstract fun getCurrentStatementContext(): JsContext @@ -45,4 +44,4 @@ abstract class StatementContext { } protected abstract fun getEmptyStatement(): JsStatement -} +} \ No newline at end of file