KT-17503 add check whether callable reference is acceptable in lambda

This commit is contained in:
Mikhail Glukhikh
2017-04-26 17:12:56 +03:00
parent 0eceef1519
commit bb8091a6ca
3 changed files with 33 additions and 0 deletions
@@ -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",
@@ -0,0 +1,8 @@
// WITH_RUNTIME
// PROBLEM: none
fun foo(arg: Int) = arg.toString()
fun bar(f: () -> (Int) -> String) {}
val someFun = bar { <caret>::foo }
@@ -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");