From 0075e900428ea90461de0b222d270f0e3ddfb1be Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Wed, 23 Jan 2019 14:20:48 +0900 Subject: [PATCH] Convert to lambda: report at INFORMATION level if anonymous object super type does not match function parameter type exactly #KT-28081 Fixed --- .../ObjectLiteralToLambdaIntention.kt | 17 ++++++++++++----- .../objectLiteralToLambda/.inspection | 1 + .../notMatchFunctionParameterType.1.java | 11 +++++++++++ .../notMatchFunctionParameterType.1.java.after | 11 +++++++++++ .../notMatchFunctionParameterType.kt | 9 +++++++++ .../notMatchFunctionParameterType.kt.after | 6 ++++++ .../LocalInspectionTestGenerated.java | 18 ++++++++++++++++++ 7 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 idea/testData/inspectionsLocal/objectLiteralToLambda/.inspection create mode 100644 idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java create mode 100644 idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java.after create mode 100644 idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt create mode 100644 idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt index d5d90e5ec6c..597e3abe338 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt @@ -25,6 +25,7 @@ import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.canMoveLambdaOutsideParentheses @@ -37,13 +38,11 @@ import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType -import org.jetbrains.kotlin.psi.psiUtil.contentRange -import org.jetbrains.kotlin.psi.psiUtil.endOffset -import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue @@ -51,8 +50,16 @@ import org.jetbrains.kotlin.types.KotlinType class ObjectLiteralToLambdaInspection : IntentionBasedInspection(ObjectLiteralToLambdaIntention::class) { override fun problemHighlightType(element: KtObjectLiteralExpression): ProblemHighlightType { - val (_, _, singleFunction) = extractData(element) ?: return super.problemHighlightType(element) + val (_, baseType, singleFunction) = extractData(element) ?: return super.problemHighlightType(element) if (singleFunction.bodyExpression?.anyDescendantOfType { true } == true) return ProblemHighlightType.INFORMATION + + val valueArgument = element.parent as? KtValueArgument + val call = valueArgument?.getStrictParentOfType() + if (call != null) { + val argumentMatch = call.resolveToCall()?.getArgumentMapping(valueArgument) as? ArgumentMatch + if (baseType.constructor != argumentMatch?.valueParameter?.type?.constructor) return ProblemHighlightType.INFORMATION + } + return super.problemHighlightType(element) } } diff --git a/idea/testData/inspectionsLocal/objectLiteralToLambda/.inspection b/idea/testData/inspectionsLocal/objectLiteralToLambda/.inspection new file mode 100644 index 00000000000..c882a76574a --- /dev/null +++ b/idea/testData/inspectionsLocal/objectLiteralToLambda/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.intentions.ObjectLiteralToLambdaInspection \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java new file mode 100644 index 00000000000..c481d470d98 --- /dev/null +++ b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java @@ -0,0 +1,11 @@ +@FunctionalInterface +public interface Foo { + void foo(); +} + +public interface Bar { +} + +@FunctionalInterface +public interface FooBar extends Foo, Bar { +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java.after b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java.after new file mode 100644 index 00000000000..c481d470d98 --- /dev/null +++ b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.1.java.after @@ -0,0 +1,11 @@ +@FunctionalInterface +public interface Foo { + void foo(); +} + +public interface Bar { +} + +@FunctionalInterface +public interface FooBar extends Foo, Bar { +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt new file mode 100644 index 00000000000..6c3c3631d37 --- /dev/null +++ b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt @@ -0,0 +1,9 @@ +// HIGHLIGHT: INFORMATION +fun main() { + test("", object : FooBar { + override fun foo() { + } + }, 1) +} + +fun test(s: String, foo: Foo, i: Int) {} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt.after b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt.after new file mode 100644 index 00000000000..fc164d9c202 --- /dev/null +++ b/idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt.after @@ -0,0 +1,6 @@ +// HIGHLIGHT: INFORMATION +fun main() { + test("", FooBar { }, 1) +} + +fun test(s: String, foo: Foo, i: Int) {} \ 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 8570c73a1f7..08564c78715 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -4416,6 +4416,24 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { } } + @TestMetadata("idea/testData/inspectionsLocal/objectLiteralToLambda") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ObjectLiteralToLambda extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInObjectLiteralToLambda() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/objectLiteralToLambda"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("notMatchFunctionParameterType.kt") + public void testNotMatchFunctionParameterType() throws Exception { + runTest("idea/testData/inspectionsLocal/objectLiteralToLambda/notMatchFunctionParameterType.kt"); + } + } + @TestMetadata("idea/testData/inspectionsLocal/recursiveEqualsCall") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)