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;
|
package org.jetbrains.k2js.translate.expression;
|
||||||
|
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.JsFunction;
|
||||||
import com.google.dart.compiler.util.AstUtil;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
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.JetDeclarationWithBody;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||||
import org.jetbrains.k2js.translate.context.Namer;
|
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.context.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
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.JsDescriptorUtils;
|
||||||
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
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.ArrayList;
|
||||||
import java.util.List;
|
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.ErrorReportingUtils.message;
|
||||||
import static org.jetbrains.k2js.translate.utils.FunctionBodyTranslator.translateFunctionBody;
|
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.JsAstUtils.setParameters;
|
||||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
|
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
*/
|
*/
|
||||||
public final class FunctionTranslator extends AbstractTranslator {
|
public final class FunctionTranslator extends AbstractTranslator {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static FunctionTranslator newInstance(@NotNull JetDeclarationWithBody function,
|
public static FunctionTranslator newInstance(@NotNull JetDeclarationWithBody function,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
@@ -59,19 +57,14 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final TranslationContext functionBodyContext;
|
private final TranslationContext functionBodyContext;
|
||||||
@Nullable
|
|
||||||
private TemporaryVariable aliasForContainingClassThis = null;
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JetDeclarationWithBody functionDeclaration;
|
private final JetDeclarationWithBody functionDeclaration;
|
||||||
@Nullable
|
@Nullable
|
||||||
private JsName extensionFunctionReceiverName = null;
|
private JsName extensionFunctionReceiverName;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsFunction functionObject;
|
private final JsFunction functionObject;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final FunctionDescriptor descriptor;
|
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,
|
private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
@@ -81,33 +74,18 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
this.functionObject = context().getFunctionObject(descriptor);
|
this.functionObject = context().getFunctionObject(descriptor);
|
||||||
assert this.functionObject.getParameters().isEmpty()
|
assert this.functionObject.getParameters().isEmpty()
|
||||||
: message(bindingContext(), descriptor, "Function " + functionDeclaration.getText() + " processed for the second time.");
|
: 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
|
//NOTE: it's important we compute the context before we start the computation
|
||||||
this.functionBodyContext = getFunctionBodyContext();
|
this.functionBodyContext = getFunctionBodyContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TranslationContext getFunctionBodyContext() {
|
private TranslationContext getFunctionBodyContext() {
|
||||||
if (isLiteral()) {
|
|
||||||
return getFunctionBodyContextForLiteral();
|
|
||||||
}
|
|
||||||
if (isExtensionFunction()) {
|
if (isExtensionFunction()) {
|
||||||
return getFunctionBodyContextForExtensionFunction();
|
return getFunctionBodyContextForExtensionFunction();
|
||||||
}
|
}
|
||||||
return getContextWithFunctionBodyBlock();
|
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
|
@NotNull
|
||||||
private TranslationContext getFunctionBodyContextForExtensionFunction() {
|
private TranslationContext getFunctionBodyContextForExtensionFunction() {
|
||||||
TranslationContext contextWithFunctionBodyBlock = getContextWithFunctionBodyBlock();
|
TranslationContext contextWithFunctionBodyBlock = getContextWithFunctionBodyBlock();
|
||||||
@@ -119,10 +97,9 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TranslationContext getContextWithFunctionBodyBlock() {
|
private TranslationContext getContextWithFunctionBodyBlock() {
|
||||||
return context().newDeclaration(functionDeclaration).innerBlock(functionBody);
|
return context().newDeclaration(functionDeclaration).innerBlock(functionObject.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsFunction translateAsLocalFunction() {
|
public JsFunction translateAsLocalFunction() {
|
||||||
JsName functionName = context().getNameForElement(functionDeclaration);
|
JsName functionName = context().getNameForElement(functionDeclaration);
|
||||||
@@ -144,51 +121,6 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
return new JsPropertyInitializer(functionName.makeRef(), functionObject);
|
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() {
|
private void generateFunctionObject() {
|
||||||
setParameters(functionObject, translateParameters());
|
setParameters(functionObject, translateParameters());
|
||||||
translateBody();
|
translateBody();
|
||||||
@@ -200,24 +132,21 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
assert descriptor.getModality().equals(Modality.ABSTRACT);
|
assert descriptor.getModality().equals(Modality.ABSTRACT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
functionBody.getStatements().add(translateFunctionBody(descriptor, functionDeclaration, functionBodyContext));
|
functionObject.getBody().getStatements().addAll(translateFunctionBody(descriptor, functionDeclaration, functionBodyContext).getStatements());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<JsParameter> translateParameters() {
|
private List<JsParameter> translateParameters() {
|
||||||
List<JsParameter> jsParameters = new ArrayList<JsParameter>();
|
List<JsParameter> jsParameters = new ArrayList<JsParameter>();
|
||||||
mayBeAddThisParameterForExtensionFunction(jsParameters);
|
mayBeAddThisParameterForExtensionFunction(jsParameters);
|
||||||
for (ValueParameterDescriptor valueParameter : descriptor.getValueParameters()) {
|
addParameters(jsParameters, descriptor, context());
|
||||||
JsName parameterName = declareParameter(valueParameter);
|
|
||||||
jsParameters.add(new JsParameter(parameterName));
|
|
||||||
}
|
|
||||||
return jsParameters;
|
return jsParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
public static void addParameters(List<JsParameter> list, FunctionDescriptor descriptor, TranslationContext context) {
|
||||||
private JsName declareParameter(@NotNull ValueParameterDescriptor valueParameter) {
|
for (ValueParameterDescriptor valueParameter : descriptor.getValueParameters()) {
|
||||||
return context().getNameForDescriptor(valueParameter);
|
list.add(new JsParameter(context.getNameForDescriptor(valueParameter)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mayBeAddThisParameterForExtensionFunction(@NotNull List<JsParameter> jsParameters) {
|
private void mayBeAddThisParameterForExtensionFunction(@NotNull List<JsParameter> jsParameters) {
|
||||||
@@ -228,10 +157,6 @@ public final class FunctionTranslator extends AbstractTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isExtensionFunction() {
|
private boolean isExtensionFunction() {
|
||||||
return JsDescriptorUtils.isExtension(descriptor) && !isLiteral();
|
return JsDescriptorUtils.isExtension(descriptor) && !(functionDeclaration instanceof JetFunctionLiteralExpression);
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isLiteral() {
|
|
||||||
return functionDeclaration instanceof JetFunctionLiteralExpression;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user