JS inline refactor: moved invocation and function utils to separate files
This commit is contained in:
committed by
Zalim Bashorov
parent
7fbed5ee86
commit
17a78dd522
@@ -1,113 +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.*;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
class InvocationUtil {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if result of call is being used in containing statement
|
|
||||||
*/
|
|
||||||
public static boolean isResultUsed(JsStatement containingStatement, JsInvocation call) {
|
|
||||||
return !(containingStatement instanceof JsExpressionStatement)
|
|
||||||
|| call != ((JsExpressionStatement) containingStatement).getExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static JsName getName(@NotNull JsInvocation call) {
|
|
||||||
JsExpression qualifier = call.getQualifier();
|
|
||||||
if (qualifier instanceof JsNameRef) {
|
|
||||||
return ((JsNameRef) qualifier).getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets inner function from function, that creates closure
|
|
||||||
*
|
|
||||||
* For example:
|
|
||||||
* function(a) {
|
|
||||||
* return function() { return a; }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* Inner functions can only be generated when lambda
|
|
||||||
* with closure is created
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public static JsFunction getInnerFunction(@NotNull JsFunction outer) {
|
|
||||||
List<JsStatement> statements = outer.getBody().getStatements();
|
|
||||||
if (statements.size() != 1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsStatement statement = statements.get(0);
|
|
||||||
if (!(statement instanceof JsReturn)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsExpression returnExpr = ((JsReturn) statement).getExpression();
|
|
||||||
if (!(returnExpr instanceof JsFunction)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (JsFunction) returnExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if invocation is JavaScript call function
|
|
||||||
*
|
|
||||||
* @return true if invocation is something like `x.call(thisReplacement)`
|
|
||||||
* false otherwise
|
|
||||||
*/
|
|
||||||
public static boolean isCallInvocation(JsInvocation invocation) {
|
|
||||||
JsExpression qualifier = invocation.getQualifier();
|
|
||||||
if (!(qualifier instanceof JsNameRef)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsNameRef qualifierNameRef = (JsNameRef) qualifier;
|
|
||||||
return qualifierNameRef.getIdent().equals("call")
|
|
||||||
&& invocation.getArguments().size() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean hasReceiver(@NotNull JsInvocation invocation) {
|
|
||||||
return getReceiverImpl(invocation) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsExpression getReceiver(@NotNull JsInvocation invocation) {
|
|
||||||
JsExpression receiver = getReceiverImpl(invocation);
|
|
||||||
assert receiver != null;
|
|
||||||
return receiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static JsExpression getReceiverImpl(@NotNull JsInvocation invocation) {
|
|
||||||
JsExpression qualifier = invocation.getQualifier();
|
|
||||||
if (!(qualifier instanceof JsNameRef)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((JsNameRef) qualifier).getQualifier();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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.util
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsFunction
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsReturn
|
||||||
|
|
||||||
|
public fun isFunctionCreator(outer: JsFunction): Boolean =
|
||||||
|
outer.getInnerFunction() != null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets inner function from function, that creates closure
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* function(a) {
|
||||||
|
* return function() { return a; }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Inner functions can only be generated when lambda
|
||||||
|
* with closure is created
|
||||||
|
*/
|
||||||
|
public fun JsFunction.getInnerFunction(): JsFunction? {
|
||||||
|
val statements = getBody().getStatements()
|
||||||
|
if (statements.size() != 1) return null
|
||||||
|
|
||||||
|
val statement = statements.get(0)
|
||||||
|
val returnExpr = (statement as? JsReturn)?.getExpression()
|
||||||
|
|
||||||
|
return returnExpr as? JsFunction
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* 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.util
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsStatement
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsInvocation
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExpressionStatement
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsName
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsNameRef
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsFunction
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsReturn
|
||||||
|
import org.jetbrains.k2js.translate.context.Namer
|
||||||
|
import com.google.dart.compiler.backend.js.ast.HasName
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsNode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets invocation qualifier name.
|
||||||
|
*
|
||||||
|
* @returns `f` for `_.foo.f()` call
|
||||||
|
*/
|
||||||
|
public fun getSimpleName(call: JsInvocation): JsName? {
|
||||||
|
val qualifier = call.getQualifier()
|
||||||
|
return (qualifier as? JsNameRef)?.getName()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to get ident for call.
|
||||||
|
*
|
||||||
|
* @returns first name ident (iterating through qualifier chain)
|
||||||
|
*/
|
||||||
|
public fun getSimpleIdent(call: JsInvocation): String? {
|
||||||
|
var qualifier = call.getQualifier()
|
||||||
|
|
||||||
|
while (qualifier != null) {
|
||||||
|
when (qualifier) {
|
||||||
|
is JsInvocation -> {
|
||||||
|
val callableQualifier = qualifier as JsInvocation
|
||||||
|
qualifier = callableQualifier.getQualifier()
|
||||||
|
|
||||||
|
if (isCallInvocation(callableQualifier)) {
|
||||||
|
qualifier = (qualifier as? JsNameRef)?.getQualifier()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is HasName -> return (qualifier as HasName).getName()?.getIdent()
|
||||||
|
else -> break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if JsInvocation is function creator call.
|
||||||
|
*
|
||||||
|
* Function creator is a function, that creates closure.
|
||||||
|
*/
|
||||||
|
public fun isFunctionCreatorInvocation(invocation: JsInvocation): Boolean {
|
||||||
|
val staticRef = getStaticRef(invocation)
|
||||||
|
return when (staticRef) {
|
||||||
|
is JsFunction -> isFunctionCreator(staticRef)
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if invocation is JavaScript call function
|
||||||
|
*
|
||||||
|
* @return true if invocation is something like `x.call(thisReplacement)`
|
||||||
|
* false otherwise
|
||||||
|
*/
|
||||||
|
public fun isCallInvocation(invocation: JsInvocation): Boolean {
|
||||||
|
val qualifier = invocation.getQualifier() as? JsNameRef
|
||||||
|
val arguments = invocation.getArguments()
|
||||||
|
|
||||||
|
return qualifier?.getIdent() == Namer.CALL_FUNCTION && arguments.notEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if invocation has qualifier before call.
|
||||||
|
*
|
||||||
|
* @return true, if invocation is similar to `something.f()`
|
||||||
|
* false, if invocation is similar to `f()`
|
||||||
|
*/
|
||||||
|
public fun hasCallerQualifier(invocation: JsInvocation): Boolean {
|
||||||
|
return getCallerQualifierImpl(invocation) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets qualifier preceding call.
|
||||||
|
*
|
||||||
|
* @return caller for invocation of type `caller.f()`,
|
||||||
|
* where caller is any JsNameRef (for example a.b.c. etc.)
|
||||||
|
*
|
||||||
|
* @throws AssertionError, if invocation does not have caller qualifier.
|
||||||
|
*/
|
||||||
|
public fun getCallerQualifier(invocation: JsInvocation): JsExpression {
|
||||||
|
return getCallerQualifierImpl(invocation) ?:
|
||||||
|
throw AssertionError("must check hasQualifier() before calling getQualifier")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCallerQualifierImpl(invocation: JsInvocation): JsExpression? {
|
||||||
|
return (invocation.getQualifier() as? JsNameRef)?.getQualifier()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getStaticRef(invocation: JsInvocation): JsNode? {
|
||||||
|
val qualifier = invocation.getQualifier()
|
||||||
|
val qualifierName = (qualifier as? HasName)?.getName()
|
||||||
|
return qualifierName?.getStaticRef()
|
||||||
|
}
|
||||||
+1
-5
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.descriptors.Visibilities
|
|||||||
import com.google.dart.compiler.backend.js.ast.JsVars.JsVar
|
import com.google.dart.compiler.backend.js.ast.JsVars.JsVar
|
||||||
import org.jetbrains.k2js.translate.utils.JsAstUtils
|
import org.jetbrains.k2js.translate.utils.JsAstUtils
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
|
import org.jetbrains.k2js.inline.util.getInnerFunction
|
||||||
import org.jetbrains.jet.lang.types.lang.InlineUtil
|
import org.jetbrains.jet.lang.types.lang.InlineUtil
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||||
|
|
||||||
@@ -177,12 +178,7 @@ private fun getFreshNamesInScope(scope: JsScope, suggested: List<JsName?>): List
|
|||||||
return freshNames.toList()
|
return freshNames.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JsFunction.getInnerFunction(): JsFunction? {
|
|
||||||
val outerStatements = this.getBody().getStatements()
|
|
||||||
val outerReturn = outerStatements.get(0) as? JsReturn
|
|
||||||
val innerFunction = outerReturn?.getExpression() as? JsFunction
|
|
||||||
|
|
||||||
return innerFunction
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JsFunction.addDeclaration(name: JsName, value: JsExpression?) {
|
private fun JsFunction.addDeclaration(name: JsName, value: JsExpression?) {
|
||||||
|
|||||||
Reference in New Issue
Block a user