[JS BE] Fix the crash on compound operations with a qualified call on left side

#KT-22001 Fixed
This commit is contained in:
Zalim Bashorov
2018-03-27 16:59:30 +03:00
parent c3b6abfb1f
commit 9349b9bc67
9 changed files with 174 additions and 18 deletions
@@ -0,0 +1,31 @@
var log = ""
class A(p: String) {
var pp = p
init {
log += "init($p);"
}
}
operator fun A.plusAssign(s: String) {
pp += s
log += "pp = $pp;"
}
inline fun <T, R> T.foo(f: (T) -> R) = f(this)
fun <T, R> T.bar(f: (T) -> R) = f(this)
fun box(): String {
"rrr".foo { A(it) } += "aaa"
if (log != "init(rrr);pp = rrraaa;") return "1: log = \"$log\""
log = ""
"foo".bar { A(it) } += "baaar"
if (log != "init(foo);pp = foobaaar;") return "2: log = \"$log\""
return "OK"
}
@@ -0,0 +1,48 @@
var log = ""
class A(p: String) {
var pp = p
init {
log += "init($p);"
}
}
operator fun A.plusAssign(s: String) {
pp += s
log += "pp = $pp;"
}
class D {
val a = A("D")
}
object E {
val t = A("E")
}
fun box(): String {
log = ""
val d = D()
d.a += "foo"
if (log != "init(D);pp = Dfoo;") return "1: log = \"$log\""
log = ""
E.t += "ET"
if (log != "init(E);pp = EET;") return "2: log = \"$log\""
log = ""
val c = object { val b = object { val a = A("xcv") } }
c.b.a += "eee"
if (log != "init(xcv);pp = xcveee;") return "3: log = \"$log\""
val b = object { val a = A("qwe") }
b.a.pp += "ui"
if (b.a.pp != "qweui") return "4: b.a.pp = \"${b.a.pp}\""
return "OK"
}
@@ -13451,12 +13451,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("compoundAssignmentToObjectFromCall.kt")
public void testCompoundAssignmentToObjectFromCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToObjectFromCall.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt")
public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyWithQualifier.kt")
public void testCompoundAssignmentToPropertyWithQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyWithQualifier.kt");
doTest(fileName);
}
@TestMetadata("flist.kt")
public void testFlist() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt");
@@ -13451,12 +13451,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("compoundAssignmentToObjectFromCall.kt")
public void testCompoundAssignmentToObjectFromCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToObjectFromCall.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt")
public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyWithQualifier.kt")
public void testCompoundAssignmentToPropertyWithQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyWithQualifier.kt");
doTest(fileName);
}
@TestMetadata("flist.kt")
public void testFlist() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt");
@@ -13451,12 +13451,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("compoundAssignmentToObjectFromCall.kt")
public void testCompoundAssignmentToObjectFromCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToObjectFromCall.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt")
public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyWithQualifier.kt")
public void testCompoundAssignmentToPropertyWithQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyWithQualifier.kt");
doTest(fileName);
}
@TestMetadata("flist.kt")
public void testFlist() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt");
@@ -15979,12 +15979,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("compoundAssignmentToObjectFromCall.kt")
public void testCompoundAssignmentToObjectFromCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToObjectFromCall.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyImportedFromObject.kt")
public void testCompoundAssignmentToPropertyImportedFromObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyImportedFromObject.kt");
doTest(fileName);
}
@TestMetadata("compoundAssignmentToPropertyWithQualifier.kt")
public void testCompoundAssignmentToPropertyWithQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/compoundAssignmentToPropertyWithQualifier.kt");
doTest(fileName);
}
@TestMetadata("flist.kt")
public void testFlist() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt");
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.js.translate.reference;
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.kotlin.js.backend.ast.JsNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.kotlin.js.backend.ast.JsNode;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils;
import org.jetbrains.kotlin.psi.*;
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getNotNullSimpleNameSelector;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getSelector;
public final class QualifiedExpressionTranslator {
@@ -45,7 +44,16 @@ public final class QualifiedExpressionTranslator {
if (forceOrderOfEvaluation && receiver != null) {
receiver = context.defineTemporary(receiver);
}
return VariableAccessTranslator.newInstance(context, getNotNullSimpleNameSelector(expression), receiver);
KtExpression selector = getSelector(expression);
if (selector instanceof KtSimpleNameExpression) {
return VariableAccessTranslator.newInstance(context, (KtSimpleNameExpression) selector, receiver);
}
if (selector instanceof KtCallExpression) {
return new QualifiedExpressionWithCallSelectorAccessTranslator((KtCallExpression) selector, receiver, context);
}
throw new AssertionError("Unexpected qualified expression: " + expression.getText());
}
@NotNull
@@ -73,7 +81,7 @@ public final class QualifiedExpressionTranslator {
return VariableAccessTranslator.newInstance(context, (KtSimpleNameExpression)selector, receiver).translateAsGet();
}
if (selector instanceof KtCallExpression) {
return invokeCallExpressionTranslator(receiver, selector, context);
return invokeCallExpressionTranslator(receiver, (KtCallExpression) selector, context);
}
//TODO: never get there
if (selector instanceof KtSimpleNameExpression) {
@@ -83,13 +91,13 @@ public final class QualifiedExpressionTranslator {
}
@NotNull
private static JsNode invokeCallExpressionTranslator(
static JsNode invokeCallExpressionTranslator(
@Nullable JsExpression receiver,
@NotNull KtExpression selector,
@NotNull KtCallExpression selector,
@NotNull TranslationContext context
) {
try {
return CallExpressionTranslator.translate((KtCallExpression) selector, receiver, context);
return CallExpressionTranslator.translate(selector, receiver, context);
} catch (RuntimeException e) {
throw ErrorReportingUtils.reportErrorWithLocation(selector, e);
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.reference
import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.psi.KtCallExpression
class QualifiedExpressionWithCallSelectorAccessTranslator(
private val selector: KtCallExpression,
private val receiver: JsExpression?,
private val context: TranslationContext
) : AccessTranslator {
override fun translateAsGet(): JsExpression {
return QualifiedExpressionTranslator.invokeCallExpressionTranslator(receiver, selector, context) as JsExpression
}
override fun translateAsSet(setTo: JsExpression): JsExpression {
throw IllegalStateException("Set access is not supported for " + this::class.java.simpleName)
}
override fun getCached(): AccessTranslator {
throw IllegalStateException("Cashed access is not supported for " + this::class.java.simpleName)
}
}
@@ -31,11 +31,10 @@ import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
import java.io.*;
import java.nio.charset.Charset;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
public final class PsiUtils {
@@ -71,13 +70,6 @@ public final class PsiUtils {
return selectorExpression;
}
@NotNull
public static KtSimpleNameExpression getNotNullSimpleNameSelector(@NotNull KtQualifiedExpression expression) {
KtSimpleNameExpression selectorAsSimpleName = getSelectorAsSimpleName(expression);
assert selectorAsSimpleName != null;
return selectorAsSimpleName;
}
@NotNull
public static KtToken getOperationToken(@NotNull KtOperationExpression expression) {
KtSimpleNameExpression operationExpression = expression.getOperationReference();