From beb5d5e2716eb9004d1be51b79d909c3ec5bd23c Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 14 Apr 2016 14:30:58 +0300 Subject: [PATCH] Create from Usage: Suggest "Create secondary constructor" on NONE_APPLICABLE error #KT-11866 Fixed --- ChangeLog.md | 1 + .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 1 + .../CreateCallableFromCallActionFactory.kt | 13 +++++++++---- .../createSecondaryConstructor/noneApplicable.kt | 11 +++++++++++ .../noneApplicable.kt.after | 13 +++++++++++++ .../kotlin/idea/quickfix/QuickFixTestGenerated.java | 6 ++++++ 6 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt create mode 100644 idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt.after diff --git a/ChangeLog.md b/ChangeLog.md index ac6b0f3abad..8cdda60f86a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -21,6 +21,7 @@ Issues fixed: - [KT-11155](https://youtrack.jetbrains.com/issue/KT-11155) Allow running multiple Kotlin classes as well as running mixtures of Kotlin and Java classes - [KT-11495](https://youtrack.jetbrains.com/issue/KT-11495) Show recursion line markers for extension function calls with different receiver - [KT-11659](https://youtrack.jetbrains.com/issue/KT-11659) Generate abstract overrides for Any members inside of Kotlin interfaces +- [KT-11866](https://youtrack.jetbrains.com/issue/KT-11866) Suggest "Create secondary constructor" when constructors exist but are not applicable #### Debugger diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 99a0e2749b6..7b3960f0428 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -264,6 +264,7 @@ class QuickFixRegistrar : QuickFixContributor { NO_VALUE_FOR_PARAMETER.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES) TOO_MANY_ARGUMENTS.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES) EXPRESSION_EXPECTED_PACKAGE_FOUND.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES) + NONE_APPLICABLE.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES) NO_VALUE_FOR_PARAMETER.registerFactory(CreateConstructorFromDelegationCallActionFactory) TOO_MANY_ARGUMENTS.registerFactory(CreateConstructorFromDelegationCallActionFactory) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt index 3d207fceb73..b670457ec7a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createCallable/CreateCallableFromCallActionFactory.kt @@ -36,8 +36,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets import org.jetbrains.kotlin.resolve.calls.callUtil.getCall -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType import org.jetbrains.kotlin.resolve.scopes.receivers.* @@ -71,7 +71,8 @@ sealed class CreateCallableFromCallActionFactory( } Errors.NO_VALUE_FOR_PARAMETER, - Errors.TOO_MANY_ARGUMENTS -> diagElement.getNonStrictParentOfType() + Errors.TOO_MANY_ARGUMENTS, + Errors.NONE_APPLICABLE -> diagElement.getNonStrictParentOfType() else -> throw AssertionError("Unexpected diagnostic: ${diagnostic.factory}") } as? KtExpression @@ -182,8 +183,12 @@ sealed class CreateCallableFromCallActionFactory( ): CallableInfo? { if (expression.typeArguments.isNotEmpty()) return null - val constructorDescriptor = expression.getResolvedCall(context)?.resultingDescriptor as? ConstructorDescriptor - val classDescriptor = constructorDescriptor?.containingDeclaration as? ClassDescriptor + val classDescriptor = expression + .calleeExpression + ?.getReferenceTargets(context) + ?.mapNotNull { (it as? ConstructorDescriptor)?.containingDeclaration } + ?.distinct() + ?.singleOrNull() as? ClassDescriptor val klass = classDescriptor?.source?.getPsi() if ((klass !is KtClass && klass !is PsiClass) || !klass.canRefactor()) return null diff --git a/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt new file mode 100644 index 00000000000..2773a9416e0 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt @@ -0,0 +1,11 @@ +// "Create secondary constructor" "true" +// ERROR: Primary constructor call expected + +class CtorSecondary() { + constructor(p: Int) : this() +} + +fun construct() { + // todo: add this() + val vA = CtorSecondary(2, 3) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt.after b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt.after new file mode 100644 index 00000000000..9059e4164f1 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt.after @@ -0,0 +1,13 @@ +// "Create secondary constructor" "true" +// ERROR: Primary constructor call expected + +class CtorSecondary() { + constructor(p: Int) : this() + + constructor(i: Int, i1: Int) +} + +fun construct() { + // todo: add this() + val vA = CtorSecondary(2, 3) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index b258c008fdb..43f164bd46d 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -2701,6 +2701,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("noneApplicable.kt") + public void testNoneApplicable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createSecondaryConstructor/noneApplicable.kt"); + doTest(fileName); + } + @TestMetadata("superCall.kt") public void testSuperCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createSecondaryConstructor/superCall.kt");