/*
* Copyright 2010-2015 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.kotlin.js.translate.operation;
import org.jetbrains.annotations.
NotNull;
import org.jetbrains.kotlin.descriptors.
FunctionDescriptor;
import org.jetbrains.kotlin.js.backend.ast.
JsBlock;
import org.jetbrains.kotlin.js.backend.ast.
JsExpression;
import org.jetbrains.kotlin.js.translate.callTranslator.
CallTranslator;
import org.jetbrains.kotlin.js.translate.context.
TranslationContext;
import org.jetbrains.kotlin.js.translate.general.
Translation;
import org.jetbrains.kotlin.js.translate.reference.
AccessTranslationUtils;
import org.jetbrains.kotlin.js.translate.reference.
AccessTranslator;
import org.jetbrains.kotlin.psi.
KtBinaryExpression;
import org.jetbrains.kotlin.psi.
KtExpression;
import org.jetbrains.kotlin.resolve.calls.callUtil.
CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.
ResolvedCall;
import java.util.
HashMap;
import java.util.
Map;
public final class
OverloadedAssignmentTranslator extends
AssignmentTranslator {
@
NotNull
public static
JsExpression doTranslate(@
NotNull KtBinaryExpression expression, @
NotNull TranslationContext context) {
return (new
OverloadedAssignmentTranslator(
expression,
context)).
translate();
}
@
NotNull
private final
ResolvedCall<? extends
FunctionDescriptor>
resolvedCall;
private
OverloadedAssignmentTranslator(@
NotNull KtBinaryExpression expression, @
NotNull TranslationContext context) {
super(
expression,
context);
resolvedCall =
CallUtilKt.
getFunctionResolvedCallWithAssert(
expression,
context.
bindingContext());
}
@
NotNull
private
JsExpression translate() {
if (
isVariableReassignment) {
return
reassignment();
}
KtExpression left =
expression.
getLeft();
assert
left != null;
return
overloadedMethodInvocation(
AccessTranslationUtils.
getAccessTranslator(
left,
context()));
}
@
NotNull
private
JsExpression reassignment() {
KtExpression left =
expression.
getLeft();
assert
left != null;
AccessTranslator accessTranslator =
AccessTranslationUtils.
getAccessTranslator(
left,
context()).
getCached();
JsExpression newValue =
overloadedMethodInvocation(
accessTranslator);
return
accessTranslator.
translateAsSet(
newValue);
}
@
NotNull
private
JsExpression overloadedMethodInvocation(
AccessTranslator accessTranslator) {
JsBlock innerBlock = new
JsBlock();
TranslationContext innerContext =
context().
innerBlock(
innerBlock);
JsExpression oldValue =
accessTranslator.
translateAsGet();
JsBlock argumentBlock = new
JsBlock();
TranslationContext argumentContext =
innerContext.
innerBlock(
argumentBlock);
KtExpression argumentPsi =
expression.
getRight();
assert
argumentPsi != null;
JsExpression argument =
Translation.
translateAsExpression(
argumentPsi,
argumentContext);
if (!
argumentBlock.
isEmpty()) {
oldValue =
innerContext.
defineTemporary(
oldValue);
innerContext.
addStatementsToCurrentBlockFrom(
argumentBlock);
}
Map<
KtExpression,
JsExpression>
aliases = new
HashMap<>();
aliases.
put(
argumentPsi,
argument);
innerContext =
innerContext.
innerContextWithAliasesForExpressions(
aliases);
JsExpression result =
CallTranslator.
translate(
innerContext,
resolvedCall,
oldValue);
context().
addStatementsToCurrentBlockFrom(
innerBlock);
return
result;
}
}