Remove functionality delegated to LiteralFunctionTranslator from FunctionTranslator.
Adapted from https://github.com/develar/kotlin/commit/a9e0a42fb1347fa8e21c86b5a073ef8a7c873da0.
This commit is contained in:
+18
-93
@@ -17,24 +17,24 @@
|
||||
package org.jetbrains.k2js.translate.expression;
|
||||
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.google.dart.compiler.backend.js.ast.JsFunction;
|
||||
import com.google.dart.compiler.backend.js.ast.JsName;
|
||||
import com.google.dart.compiler.backend.js.ast.JsParameter;
|
||||
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.Modality;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
import org.jetbrains.k2js.translate.context.TemporaryVariable;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
|
||||
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
|
||||
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.k2js.translate.utils.closure.ClosureContext;
|
||||
import org.jetbrains.k2js.translate.utils.closure.ClosureUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -43,14 +43,12 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescrip
|
||||
import static org.jetbrains.k2js.translate.utils.ErrorReportingUtils.message;
|
||||
import static org.jetbrains.k2js.translate.utils.FunctionBodyTranslator.translateFunctionBody;
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setParameters;
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public final class FunctionTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
public static FunctionTranslator newInstance(@NotNull JetDeclarationWithBody function,
|
||||
@NotNull TranslationContext context) {
|
||||
@@ -59,19 +57,14 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
private final TranslationContext functionBodyContext;
|
||||
@Nullable
|
||||
private TemporaryVariable aliasForContainingClassThis = null;
|
||||
@NotNull
|
||||
private final JetDeclarationWithBody functionDeclaration;
|
||||
@Nullable
|
||||
private JsName extensionFunctionReceiverName = null;
|
||||
private JsName extensionFunctionReceiverName;
|
||||
@NotNull
|
||||
private final JsFunction functionObject;
|
||||
@NotNull
|
||||
private final FunctionDescriptor descriptor;
|
||||
// function body needs to be explicitly created here to include it in the context
|
||||
@NotNull
|
||||
private final JsBlock functionBody;
|
||||
|
||||
private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration,
|
||||
@NotNull TranslationContext context) {
|
||||
@@ -81,33 +74,18 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
this.functionObject = context().getFunctionObject(descriptor);
|
||||
assert this.functionObject.getParameters().isEmpty()
|
||||
: message(bindingContext(), descriptor, "Function " + functionDeclaration.getText() + " processed for the second time.");
|
||||
this.functionBody = functionObject.getBody();
|
||||
//NOTE: it's important we compute the context before we start the computation
|
||||
this.functionBodyContext = getFunctionBodyContext();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TranslationContext getFunctionBodyContext() {
|
||||
if (isLiteral()) {
|
||||
return getFunctionBodyContextForLiteral();
|
||||
}
|
||||
if (isExtensionFunction()) {
|
||||
return getFunctionBodyContextForExtensionFunction();
|
||||
}
|
||||
return getContextWithFunctionBodyBlock();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TranslationContext getFunctionBodyContextForLiteral() {
|
||||
ClassDescriptor containingClass = getContainingClass(descriptor);
|
||||
if (containingClass == null) {
|
||||
return getContextWithFunctionBodyBlock();
|
||||
}
|
||||
JsExpression thisQualifier = TranslationUtils.getThisObject(context(), containingClass);
|
||||
aliasForContainingClassThis = context().declareTemporary(thisQualifier);
|
||||
return getContextWithFunctionBodyBlock().innerContextWithThisAliased(containingClass, aliasForContainingClassThis.name());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TranslationContext getFunctionBodyContextForExtensionFunction() {
|
||||
TranslationContext contextWithFunctionBodyBlock = getContextWithFunctionBodyBlock();
|
||||
@@ -119,10 +97,9 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
private TranslationContext getContextWithFunctionBodyBlock() {
|
||||
return context().newDeclaration(functionDeclaration).innerBlock(functionBody);
|
||||
return context().newDeclaration(functionDeclaration).innerBlock(functionObject.getBody());
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public JsFunction translateAsLocalFunction() {
|
||||
JsName functionName = context().getNameForElement(functionDeclaration);
|
||||
@@ -144,51 +121,6 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
return new JsPropertyInitializer(functionName.makeRef(), functionObject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression translateAsLiteral() {
|
||||
assert getExpectedThisDescriptor(descriptor) == null;
|
||||
generateFunctionObject();
|
||||
ClosureContext closureContext = ClosureUtils.captureClosure(context(), (JetElement) functionDeclaration);
|
||||
if (closureContext.getDescriptors().isEmpty()) {
|
||||
return mayBeWrapWithThisAlias();
|
||||
}
|
||||
return wrapInClosureCaptureExpression(functionObject, closureContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression mayBeWrapWithThisAlias() {
|
||||
if (!shouldAliasThisObject()) {
|
||||
return functionObject;
|
||||
}
|
||||
assert aliasForContainingClassThis != null;
|
||||
return AstUtil.newSequence(aliasForContainingClassThis.assignmentExpression(), functionObject);
|
||||
}
|
||||
|
||||
private boolean shouldAliasThisObject() {
|
||||
if (!isLiteral()) {
|
||||
return false;
|
||||
}
|
||||
ClassDescriptor containingClass = getContainingClass(descriptor);
|
||||
return containingClass != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression wrapInClosureCaptureExpression(@NotNull JsExpression wrappedExpression,
|
||||
@NotNull ClosureContext closureContext) {
|
||||
JsFunction dummyFunction = new JsFunction(context().scope());
|
||||
JsInvocation dummyFunctionInvocation = new JsInvocation(dummyFunction);
|
||||
for (VariableDescriptor variableDescriptor : closureContext.getDescriptors()) {
|
||||
dummyFunction.getParameters().add(new JsParameter(context().getNameForDescriptor(variableDescriptor)));
|
||||
dummyFunctionInvocation.getArguments().add(ReferenceTranslator.translateAsLocalNameReference(variableDescriptor, context()));
|
||||
if (aliasForContainingClassThis != null) {
|
||||
dummyFunction.getParameters().add(new JsParameter(aliasForContainingClassThis.name()));
|
||||
dummyFunctionInvocation.getArguments().add(aliasForContainingClassThis.initExpression());
|
||||
}
|
||||
}
|
||||
dummyFunction.setBody(new JsBlock(new JsReturn(wrappedExpression)));
|
||||
return dummyFunctionInvocation;
|
||||
}
|
||||
|
||||
private void generateFunctionObject() {
|
||||
setParameters(functionObject, translateParameters());
|
||||
translateBody();
|
||||
@@ -200,24 +132,21 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
assert descriptor.getModality().equals(Modality.ABSTRACT);
|
||||
return;
|
||||
}
|
||||
functionBody.getStatements().add(translateFunctionBody(descriptor, functionDeclaration, functionBodyContext));
|
||||
functionObject.getBody().getStatements().addAll(translateFunctionBody(descriptor, functionDeclaration, functionBodyContext).getStatements());
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private List<JsParameter> translateParameters() {
|
||||
List<JsParameter> jsParameters = new ArrayList<JsParameter>();
|
||||
mayBeAddThisParameterForExtensionFunction(jsParameters);
|
||||
for (ValueParameterDescriptor valueParameter : descriptor.getValueParameters()) {
|
||||
JsName parameterName = declareParameter(valueParameter);
|
||||
jsParameters.add(new JsParameter(parameterName));
|
||||
}
|
||||
addParameters(jsParameters, descriptor, context());
|
||||
return jsParameters;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsName declareParameter(@NotNull ValueParameterDescriptor valueParameter) {
|
||||
return context().getNameForDescriptor(valueParameter);
|
||||
public static void addParameters(List<JsParameter> list, FunctionDescriptor descriptor, TranslationContext context) {
|
||||
for (ValueParameterDescriptor valueParameter : descriptor.getValueParameters()) {
|
||||
list.add(new JsParameter(context.getNameForDescriptor(valueParameter)));
|
||||
}
|
||||
}
|
||||
|
||||
private void mayBeAddThisParameterForExtensionFunction(@NotNull List<JsParameter> jsParameters) {
|
||||
@@ -228,10 +157,6 @@ public final class FunctionTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
private boolean isExtensionFunction() {
|
||||
return JsDescriptorUtils.isExtension(descriptor) && !isLiteral();
|
||||
}
|
||||
|
||||
private boolean isLiteral() {
|
||||
return functionDeclaration instanceof JetFunctionLiteralExpression;
|
||||
return JsDescriptorUtils.isExtension(descriptor) && !(functionDeclaration instanceof JetFunctionLiteralExpression);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user