diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/InlineCallResolverExtension.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/InlineCallResolverExtension.java index 3c649d60911..40fccf235d1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/InlineCallResolverExtension.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/InlineCallResolverExtension.java @@ -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) { diff --git a/compiler/testData/diagnostics/tests/inline/labeled.kt b/compiler/testData/diagnostics/tests/inline/labeled.kt new file mode 100644 index 00000000000..7e20c8e1747 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/labeled.kt @@ -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 bar1 + + @l2 bar1 { + 11 + } + + (@l3 bar1) { + 11 + } + + (@l5 (@l4 bar1)) { + 11 + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/parenthesized.kt b/compiler/testData/diagnostics/tests/inline/parenthesized.kt new file mode 100644 index 00000000000..2b86d3c4a0f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/parenthesized.kt @@ -0,0 +1,25 @@ +inline fun inlineFunWithInvoke(s: (p: Int) -> Unit) { + (s)(11) + (s).invoke(11) + (s) invoke 11 + (s) +} + +inline fun Function1.inlineExt() { + (this).invoke(11) + (this) invoke 11 + (this)(11) + (this) +} + +inline fun inlineFunWithInvoke2(s: (p: Int) -> Unit) { + (((s)))(11) + (((s))).invoke(11) + (((s))) invoke 11 + (((s))) +} + +inline fun propagation(s: (p: Int) -> Unit) { + inlineFunWithInvoke((@label (s: (p: Int) -> Unit))) + inlineFunWithInvoke((@label2 @label (s: (p: Int) -> Unit))) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/typed.kt b/compiler/testData/diagnostics/tests/inline/typed.kt new file mode 100644 index 00000000000..cbdba08de33 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/typed.kt @@ -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 + (s) +} + +inline fun Function1.inlineExt() { + (this: Function1).invoke(11) + (this: Function1) invoke 11 + (this: Function1)(11) + (this: Function1) +} + +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 + (((s: (p: Int) -> Unit))) +} diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index cc7d073627c..fa5e4f8de88 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -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");