[JS BE] Fix the crash on compound operations with a qualified call on left side
#KT-22001 Fixed
This commit is contained in:
@@ -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"
|
||||
}
|
||||
+48
@@ -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"
|
||||
}
|
||||
Generated
+12
@@ -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");
|
||||
|
||||
+12
@@ -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");
|
||||
|
||||
+12
@@ -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");
|
||||
|
||||
+12
@@ -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
-8
@@ -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);
|
||||
}
|
||||
|
||||
+29
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user