KT-17503 add check whether callable reference is acceptable in lambda
This commit is contained in:
+19
@@ -21,12 +21,18 @@ import com.intellij.codeInspection.LocalInspectionToolSession
|
|||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
import com.intellij.psi.PsiElementVisitor
|
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.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.intentions.ConvertLambdaToReferenceIntention
|
import org.jetbrains.kotlin.idea.intentions.ConvertLambdaToReferenceIntention
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
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
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
|
||||||
class MoveSuspiciousCallableReferenceIntoParenthesesInspection : AbstractKotlinInspection() {
|
class MoveSuspiciousCallableReferenceIntoParenthesesInspection : AbstractKotlinInspection() {
|
||||||
@@ -35,6 +41,19 @@ class MoveSuspiciousCallableReferenceIntoParenthesesInspection : AbstractKotlinI
|
|||||||
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
|
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
|
||||||
val callableReference = lambdaExpression.bodyExpression?.statements?.singleOrNull() as? KtCallableReferenceExpression
|
val callableReference = lambdaExpression.bodyExpression?.statements?.singleOrNull() as? KtCallableReferenceExpression
|
||||||
if (callableReference != null) {
|
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(
|
holder.registerProblem(
|
||||||
lambdaExpression,
|
lambdaExpression,
|
||||||
"Suspicious callable reference as the only lambda element",
|
"Suspicious callable reference as the only lambda element",
|
||||||
|
|||||||
Vendored
+8
@@ -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);
|
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")
|
@TestMetadata("it.kt")
|
||||||
public void testIt() throws Exception {
|
public void testIt() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/it.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/moveSuspiciousCallableReferenceIntoParentheses/it.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user