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 org.jetbrains.k2js.translate.utils.JsAstUtils
|
||||
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.descriptors.FunctionDescriptor
|
||||
|
||||
@@ -177,12 +178,7 @@ private fun getFreshNamesInScope(scope: JsScope, suggested: List<JsName?>): List
|
||||
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?) {
|
||||
|
||||
Reference in New Issue
Block a user