From bb8091a6ca6d5556e87a2bea6bb46a7b7e5fb32b Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 26 Apr 2017 17:12:56 +0300 Subject: [PATCH] KT-17503 add check whether callable reference is acceptable in lambda --- ...lableReferenceIntoParenthesesInspection.kt | 19 +++++++++++++++++++ .../expectedFunction.kt | 8 ++++++++ .../LocalInspectionTestGenerated.java | 6 ++++++ 3 files changed, 33 insertions(+) create mode 100644 idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/expectedFunction.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/MoveSuspiciousCallableReferenceIntoParenthesesInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/MoveSuspiciousCallableReferenceIntoParenthesesInspection.kt index f184077ce36..b229e01c241 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/MoveSuspiciousCallableReferenceIntoParenthesesInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/MoveSuspiciousCallableReferenceIntoParenthesesInspection.kt @@ -21,12 +21,18 @@ import com.intellij.codeInspection.LocalInspectionToolSession import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiElementVisitor +import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType +import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType +import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.intentions.ConvertLambdaToReferenceIntention import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.psi.KtVisitorVoid +import org.jetbrains.kotlin.psi.ValueArgument +import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument +import org.jetbrains.kotlin.resolve.calls.callUtil.getParentResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall class MoveSuspiciousCallableReferenceIntoParenthesesInspection : AbstractKotlinInspection() { @@ -35,6 +41,19 @@ class MoveSuspiciousCallableReferenceIntoParenthesesInspection : AbstractKotlinI override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) { val callableReference = lambdaExpression.bodyExpression?.statements?.singleOrNull() as? KtCallableReferenceExpression if (callableReference != null) { + val context = lambdaExpression.analyze() + val parentResolvedCall = lambdaExpression.getParentResolvedCall(context) + if (parentResolvedCall != null) { + val originalParameterDescriptor = + parentResolvedCall.getParameterForArgument(lambdaExpression.parent as? ValueArgument)?.original + if (originalParameterDescriptor != null) { + val expectedType = originalParameterDescriptor.type + if (expectedType.isBuiltinFunctionalType) { + val returnType = expectedType.getReturnTypeFromFunctionType() + if (returnType.isBuiltinFunctionalTypeOrSubtype) return + } + } + } holder.registerProblem( lambdaExpression, "Suspicious callable reference as the only lambda element", diff --git a/idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/expectedFunction.kt b/idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/expectedFunction.kt new file mode 100644 index 00000000000..6e6302be35f --- /dev/null +++ b/idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/expectedFunction.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME +// PROBLEM: none + +fun foo(arg: Int) = arg.toString() + +fun bar(f: () -> (Int) -> String) {} + +val someFun = bar { ::foo } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 8f2e62c1fa0..291737a678c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -50,6 +50,12 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { doTest(fileName); } + @TestMetadata("expectedFunction.kt") + public void testExpectedFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/expectedFunction.kt"); + doTest(fileName); + } + @TestMetadata("it.kt") public void testIt() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/it.kt");