KT-3919 Automatic labeling of lambdas by receiving functions
#KT-3919 Fixed
This commit is contained in:
+46
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.descriptors.impl.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
|
||||
import org.jetbrains.jet.lang.resolve.name.LabelName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
@@ -99,6 +100,11 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression();
|
||||
if (bodyExpression == null) return null;
|
||||
|
||||
Name callerName = getCallerName(expression);
|
||||
if (callerName != null) {
|
||||
context.labelResolver.enterLabeledElement(new LabelName(callerName.asString()), expression);
|
||||
}
|
||||
|
||||
JetType expectedType = context.expectedType;
|
||||
boolean functionTypeExpected = expectedType != NO_EXPECTED_TYPE && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(
|
||||
expectedType);
|
||||
@@ -115,9 +121,49 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
// all checks were done before
|
||||
return JetTypeInfo.create(resultType, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
if (callerName != null) {
|
||||
context.labelResolver.exitLabeledElement(expression);
|
||||
}
|
||||
|
||||
return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Name getCallerName(@NotNull JetFunctionLiteralExpression expression) {
|
||||
JetCallExpression callExpression = getContainingCallExpression(expression);
|
||||
if (callExpression == null) return null;
|
||||
|
||||
JetExpression calleeExpression = callExpression.getCalleeExpression();
|
||||
if (calleeExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
|
||||
return nameExpression.getReferencedNameAsName();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetCallExpression getContainingCallExpression(JetFunctionLiteralExpression expression) {
|
||||
PsiElement parent = expression.getParent();
|
||||
if (parent instanceof JetCallExpression) {
|
||||
// f {}
|
||||
return (JetCallExpression) parent;
|
||||
}
|
||||
|
||||
if (parent instanceof JetValueArgument) {
|
||||
// f ({}) or f(p = {})
|
||||
JetValueArgument argument = (JetValueArgument) parent;
|
||||
PsiElement argList = argument.getParent();
|
||||
if (argList == null) return null;
|
||||
PsiElement call = argList.getParent();
|
||||
if (call instanceof JetCallExpression) {
|
||||
return (JetCallExpression) call;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static AnonymousFunctionDescriptor createFunctionDescriptor(
|
||||
@NotNull JetFunctionLiteralExpression expression,
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
fun box(): String {
|
||||
val a = 1
|
||||
val explicitlyReturned = run1 {(): String ->
|
||||
if (a > 0)
|
||||
return@run1 "OK"
|
||||
else "Fail 1"
|
||||
}
|
||||
if (explicitlyReturned != "OK") return explicitlyReturned
|
||||
|
||||
val implicitlyReturned = run1 {(): String ->
|
||||
if (a < 0)
|
||||
return@run1 "Fail 2"
|
||||
else "OK"
|
||||
}
|
||||
if (implicitlyReturned != "OK") return implicitlyReturned
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun run1<T>(f: () -> T): T { return f() }
|
||||
@@ -0,0 +1,23 @@
|
||||
fun f() {
|
||||
foo {(): Int ->
|
||||
return@foo 1
|
||||
}
|
||||
foo({(): Int ->
|
||||
return@foo 1
|
||||
}
|
||||
)
|
||||
foo(a = {(): Int ->
|
||||
return@foo 1
|
||||
})
|
||||
|
||||
foo {(): Int ->
|
||||
foo {
|
||||
(): Int ->
|
||||
return@foo 1
|
||||
}
|
||||
return@foo 1
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(<!UNUSED_PARAMETER!>a<!>: Any) {}
|
||||
|
||||
@@ -2432,6 +2432,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/functionLiterals/return"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("AutoLabels.kt")
|
||||
public void testAutoLabels() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/functionLiterals/return/AutoLabels.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ForbiddenNonLocalReturnNoType.kt")
|
||||
public void testForbiddenNonLocalReturnNoType() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/functionLiterals/return/ForbiddenNonLocalReturnNoType.kt");
|
||||
|
||||
@@ -1204,6 +1204,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest("compiler/testData/codegen/box/closures/localReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localReturnWithAutolabel.kt")
|
||||
public void testLocalReturnWithAutolabel() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/closures/localReturnWithAutolabel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveClosure.kt")
|
||||
public void testRecursiveClosure() throws Exception {
|
||||
doTest("compiler/testData/codegen/box/closures/recursiveClosure.kt");
|
||||
|
||||
Reference in New Issue
Block a user