Support parenthesized, typed and labeled expressions

This commit is contained in:
Mikhael Bogdanov
2013-11-25 16:31:35 +04:00
parent ceda72e0ca
commit 1391676281
5 changed files with 127 additions and 4 deletions
@@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.InlineUtil;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
@@ -79,10 +80,7 @@ public class InlineCallResolverExtension implements CallResolverExtension {
boolean isInlinableClosure = inlinableParameters.contains(targetDescriptor);
if (isInlinableClosure) {
PsiElement parent = expression.getParent();
if (parent instanceof JetValueArgument || parent instanceof JetBinaryExpression || parent instanceof JetDotQualifiedExpression || parent instanceof JetCallExpression) {
//check that it's in inlineable call would be in resolve call of parent
} else {
if (!couldAccessVariable(expression)) {
context.trace.report(Errors.USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor));
}
}
@@ -99,6 +97,30 @@ public class InlineCallResolverExtension implements CallResolverExtension {
checkVisibility(targetDescriptor, expression, context);
}
private boolean couldAccessVariable(JetExpression expression) {
PsiElement parent = expression.getParent();
while (parent != null) {
if (parent instanceof JetValueArgument ||
parent instanceof JetBinaryExpression ||
parent instanceof JetDotQualifiedExpression ||
parent instanceof JetCallExpression) {
//check that it's in inlineable call would be in resolve call of parent
return true;
}
else if (parent instanceof JetParenthesizedExpression || parent instanceof JetBinaryExpressionWithTypeRHS) {
parent = parent.getParent();
} else if (parent instanceof JetPrefixExpression) {
boolean isLabeled = JetTokens.LABELS.contains(((JetPrefixExpression) parent).getOperationReference().getReferencedNameElementType());
if (isLabeled) {
parent = parent.getParent();
}
} else {
return false;
}
}
return false;
}
private void checkValueParameter(BasicCallResolutionContext context, CallableDescriptor targetDescriptor, ValueArgument argument, boolean isVararg) {
JetExpression jetExpression = argument.getArgumentExpression();
if (jetExpression == null) {
@@ -0,0 +1,40 @@
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
inline fun foo(bar1: (String.() -> Int) -> Int, bar2: (()->Int) -> Int) {
bar1 @label {
this@label.length
}
bar1 {
this.length
}
//unmute after KT-4247 fix
//bar1 {
// this@bar1.length
//}
bar2 @l {
11
}
bar2 {
12
}
}
inline fun foo2(bar1: (String.() -> Int) -> Int) {
@l1 <!USAGE_IS_NOT_INLINABLE!>bar1<!>
@l2 bar1 {
11
}
(@l3 bar1) {
11
}
(@l5 (@l4 bar1)) {
11
}
}
@@ -0,0 +1,25 @@
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit) {
(s)(11)
(s).invoke(11)
(s) invoke 11
(<!USAGE_IS_NOT_INLINABLE!>s<!>)
}
inline fun Function1<Int, Unit>.inlineExt() {
(this).invoke(11)
(this) invoke 11
(this)(11)
(<!USAGE_IS_NOT_INLINABLE!>this<!>)
}
inline fun inlineFunWithInvoke2(s: (p: Int) -> Unit) {
(((s)))(11)
(((s))).invoke(11)
(((s))) invoke 11
(((<!USAGE_IS_NOT_INLINABLE!>s<!>)))
}
inline fun propagation(s: (p: Int) -> Unit) {
inlineFunWithInvoke((@label (s: (p: Int) -> Unit)))
inlineFunWithInvoke((@label2 @label (s: (p: Int) -> Unit)))
}
@@ -0,0 +1,21 @@
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit) {
(s: (p: Int) -> Unit)(11)
(s: (p: Int) -> Unit).invoke(11)
(s: (p: Int) -> Unit) invoke 11
(<!USAGE_IS_NOT_INLINABLE!>s<!>)
}
inline fun Function1<Int, Unit>.inlineExt() {
(this: Function1<Int, Unit>).invoke(11)
(this: Function1<Int, Unit>) invoke 11
(this: Function1<Int, Unit>)(11)
(<!USAGE_IS_NOT_INLINABLE!>this<!>: Function1<Int, Unit>)
}
inline fun inlineFunWithInvoke2(s: (p: Int) -> Unit) {
(((s: (p: Int) -> Unit)))(11)
(((s: (p: Int) -> Unit): (p: Int) -> Unit): (p: Int) -> Unit)(11)
(((s: (p: Int) -> Unit): (p: Int) -> Unit): (p: Int) -> Unit).invoke(11)
(((s: (p: Int) -> Unit): (p: Int) -> Unit): (p: Int) -> Unit) invoke 11
(((<!USAGE_IS_NOT_INLINABLE!>s<!>: (p: Int) -> Unit)))
}
@@ -3786,6 +3786,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
public void testNonVirtualMembersWithInline() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/nonVirtualMembersWithInline.kt");
}
@TestMetadata("labeled.kt")
public void testLabeled() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/labeled.kt");
}
@TestMetadata("nothingToInline.kt")
public void testNothingToInline() throws Exception {
@@ -3797,6 +3802,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/inline/nullableFunction.kt");
}
@TestMetadata("parenthesized.kt")
public void testParenthesized() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/parenthesized.kt");
}
@TestMetadata("propagation.kt")
public void testPropagation() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/propagation.kt");
@@ -3807,6 +3817,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/inline/returns.kt");
}
@TestMetadata("typed.kt")
public void testTyped() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/typed.kt");
}
@TestMetadata("unsupportedConstruction.kt")
public void testUnsupportedConstruction() throws Exception {
doTest("compiler/testData/diagnostics/tests/inline/unsupportedConstruction.kt");