Fix labeling processing on inlining: suport labeled literals
#KT-7273 Fixed
This commit is contained in:
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
@@ -44,6 +45,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.types.expressions.LabelResolver;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
@@ -551,14 +553,14 @@ public class InlineCodegen extends CallGenerator {
|
||||
@NotNull
|
||||
protected static Set<String> getDeclarationLabels(@Nullable PsiElement lambdaOrFun, @NotNull DeclarationDescriptor descriptor) {
|
||||
Set<String> result = new HashSet<String>();
|
||||
|
||||
if (lambdaOrFun != null) {
|
||||
PsiElement parent = lambdaOrFun.getParent();
|
||||
if (parent instanceof JetLabeledExpression) {
|
||||
String labelName = ((JetLabeledExpression) parent).getLabelName();
|
||||
assert labelName != null : "Labeled expression should have not nul label " + parent.getText();
|
||||
result.add(labelName);
|
||||
Name label = LabelResolver.INSTANCE.getLabelNameIfAny(lambdaOrFun);
|
||||
if (label != null) {
|
||||
result.add(label.asString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!isFunctionLiteral(descriptor)) {
|
||||
if (!descriptor.getName().isSpecial()) {
|
||||
result.add(descriptor.getName().asString());
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.kotlin.types.expressions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -28,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.LABEL_NAME_CLASH;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.UNRESOLVED_REFERENCE;
|
||||
@@ -41,8 +44,8 @@ public class LabelResolver {
|
||||
private LabelResolver() {}
|
||||
|
||||
@NotNull
|
||||
private List<JetElement> getElementsByLabelName(@NotNull Name labelName, @NotNull JetSimpleNameExpression labelExpression) {
|
||||
List<JetElement> elements = Lists.newArrayList();
|
||||
private Set<JetElement> getElementsByLabelName(@NotNull Name labelName, @NotNull JetSimpleNameExpression labelExpression) {
|
||||
Set<JetElement> elements = Sets.newLinkedHashSet();
|
||||
PsiElement parent = labelExpression.getParent();
|
||||
while (parent != null) {
|
||||
Name name = getLabelNameIfAny(parent);
|
||||
@@ -55,24 +58,35 @@ public class LabelResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Name getLabelNameIfAny(@NotNull PsiElement element) {
|
||||
public Name getLabelNameIfAny(@NotNull PsiElement element) {
|
||||
if (element instanceof JetLabeledExpression) {
|
||||
Name labelName = ((JetLabeledExpression) element).getLabelNameAsName();
|
||||
if (labelName != null) {
|
||||
return labelName;
|
||||
}
|
||||
return ((JetLabeledExpression) element).getLabelNameAsName();
|
||||
}
|
||||
|
||||
if (element instanceof JetFunctionLiteral) {
|
||||
return getLabelNameIfAny(element.getParent());
|
||||
}
|
||||
|
||||
if (element instanceof JetFunctionLiteralExpression) {
|
||||
return getCallerName((JetFunctionLiteralExpression) element);
|
||||
return getLabelForFunctionalExpression((JetExpression) element);
|
||||
}
|
||||
|
||||
if (element instanceof JetNamedFunction) {
|
||||
Name name = ((JetNamedFunction) element).getNameAsName();
|
||||
if (name != null) return name;
|
||||
return getCallerName((JetNamedFunction) element);
|
||||
return getLabelForFunctionalExpression((JetExpression) element);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Name getLabelForFunctionalExpression(@NotNull JetExpression element) {
|
||||
if (element.getParent() instanceof JetLabeledExpression) {
|
||||
return getLabelNameIfAny(element.getParent());
|
||||
}
|
||||
return getCallerName(element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JetExpression getExpressionUnderLabel(@NotNull JetExpression labeledExpression) {
|
||||
JetExpression expression = JetPsiUtil.safeDeparenthesize(labeledExpression, true);
|
||||
@@ -160,14 +174,14 @@ public class LabelResolver {
|
||||
@NotNull JetSimpleNameExpression labelExpression,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
List<JetElement> list = getElementsByLabelName(labelName, labelExpression);
|
||||
Set<JetElement> list = getElementsByLabelName(labelName, labelExpression);
|
||||
if (list.isEmpty()) return null;
|
||||
|
||||
if (list.size() > 1) {
|
||||
trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
}
|
||||
|
||||
JetElement result = list.get(0);
|
||||
JetElement result = list.iterator().next();
|
||||
trace.record(LABEL_TARGET, labelExpression, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
//NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import test.*
|
||||
|
||||
fun test1() : String {
|
||||
return a {
|
||||
test {
|
||||
return@a "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun test2() : String {
|
||||
return test z@ {
|
||||
return@z "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun test3() : String {
|
||||
return test {
|
||||
return@test "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun test4() : String {
|
||||
return a z@ {
|
||||
test {
|
||||
return@z "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun box() : String {
|
||||
if (test1() != "OK") return "fail 1: ${test1()}"
|
||||
|
||||
if (test2() != "OK") return "fail 2: ${test2()}"
|
||||
|
||||
if (test3() != "OK") return "fail 3: ${test3()}"
|
||||
|
||||
if (test4() != "OK") return "fail 4: ${test4()}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
fun a(b: () -> String) : String {
|
||||
return b()
|
||||
}
|
||||
|
||||
inline fun test(l: () -> String): String {
|
||||
return l()
|
||||
}
|
||||
Vendored
+67
@@ -0,0 +1,67 @@
|
||||
//NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import test.*
|
||||
|
||||
fun test1(): String {
|
||||
return a {
|
||||
try {
|
||||
test {
|
||||
return@a "OK"
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun test2(): String {
|
||||
|
||||
return test z@ {
|
||||
try {
|
||||
return@z "OK"
|
||||
}
|
||||
finally {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun test3(): String {
|
||||
return test {
|
||||
try {
|
||||
return@test "OK"
|
||||
}
|
||||
finally {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun test4(): String {
|
||||
return a z@ {
|
||||
try {
|
||||
test {
|
||||
return@z "OK"
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
if (test1() != "OK") return "fail 1: ${test1()}"
|
||||
|
||||
if (test2() != "OK") return "fail 2: ${test2()}"
|
||||
|
||||
if (test3() != "OK") return "fail 3: ${test3()}"
|
||||
|
||||
if (test4() != "OK") return "fail 4: ${test4()}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
fun a(b: () -> String) : String {
|
||||
return b()
|
||||
}
|
||||
|
||||
inline fun test(l: () -> String): String {
|
||||
return l()
|
||||
}
|
||||
+12
@@ -487,6 +487,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnFromOuterLambda.1.kt")
|
||||
public void testNonLocalReturnFromOuterLambda() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/nonLocalReturnFromOuterLambda.1.kt");
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.1.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.1.kt");
|
||||
@@ -552,6 +558,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnFromOuterLambda.1.kt")
|
||||
public void testNonLocalReturnFromOuterLambda() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromOuterLambda.1.kt");
|
||||
doTestMultiFileWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/callSite")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+12
@@ -487,6 +487,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnFromOuterLambda.1.kt")
|
||||
public void testNonLocalReturnFromOuterLambda() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/nonLocalReturnFromOuterLambda.1.kt");
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccessors.1.kt")
|
||||
public void testPropertyAccessors() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/propertyAccessors.1.kt");
|
||||
@@ -552,6 +558,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnFromOuterLambda.1.kt")
|
||||
public void testNonLocalReturnFromOuterLambda() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/nonLocalReturnFromOuterLambda.1.kt");
|
||||
doBoxTestWithInlineCheck(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/callSite")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user