From da14222c4a73735d2d434998edec5e7c02b33a29 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 9 Apr 2015 20:37:37 +0300 Subject: [PATCH] Introduce Parameter: Do not apply to expressions of type Unit or Nothing --- .../jetbrains/kotlin/idea/util/TypeUtils.kt | 1 + .../JetRefactoringBundle.properties | 1 + .../KotlinIntroduceParameterHandler.kt | 20 ++++++++--- .../introduceParameter/assignment.kt | 6 ++++ .../assignment.kt.conflicts | 1 + .../refactoring/introduceParameter/fun.kt | 5 +++ .../introduceParameter/fun.kt.conflicts | 1 + .../introduceParameter/localVar.kt | 5 +++ .../introduceParameter/localVar.kt.conflicts | 1 + .../refactoring/introduceParameter/return.kt | 3 ++ .../introduceParameter/return.kt.conflicts | 1 + .../refactoring/introduceParameter/throw.kt | 3 ++ .../introduceParameter/throw.kt.conflicts | 1 + .../refactoring/introduceParameter/while.kt | 5 +++ .../introduceParameter/while.kt.conflicts | 1 + .../introduce/JetExtractionTestGenerated.java | 36 +++++++++++++++++++ 16 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 idea/testData/refactoring/introduceParameter/assignment.kt create mode 100644 idea/testData/refactoring/introduceParameter/assignment.kt.conflicts create mode 100644 idea/testData/refactoring/introduceParameter/fun.kt create mode 100644 idea/testData/refactoring/introduceParameter/fun.kt.conflicts create mode 100644 idea/testData/refactoring/introduceParameter/localVar.kt create mode 100644 idea/testData/refactoring/introduceParameter/localVar.kt.conflicts create mode 100644 idea/testData/refactoring/introduceParameter/return.kt create mode 100644 idea/testData/refactoring/introduceParameter/return.kt.conflicts create mode 100644 idea/testData/refactoring/introduceParameter/throw.kt create mode 100644 idea/testData/refactoring/introduceParameter/throw.kt.conflicts create mode 100644 idea/testData/refactoring/introduceParameter/while.kt create mode 100644 idea/testData/refactoring/introduceParameter/while.kt.conflicts diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt index 7240b9e6efe..2293c1fd352 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt @@ -32,6 +32,7 @@ fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this) fun JetType.supertypes(): Set = TypeUtils.getAllSupertypes(this) +fun JetType.isNothing(): Boolean = KotlinBuiltIns.isNothing(this) fun JetType.isUnit(): Boolean = KotlinBuiltIns.isUnit(this) fun JetType.isAny(): Boolean = KotlinBuiltIns.isAnyOrNullableAny(this) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/JetRefactoringBundle.properties b/idea/src/org/jetbrains/kotlin/idea/refactoring/JetRefactoringBundle.properties index f90d10d3703..3025b467b02 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/JetRefactoringBundle.properties +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/JetRefactoringBundle.properties @@ -21,6 +21,7 @@ cannot.extract.super.call=Cannot extract super-call cannot.refactor.expression.should.have.inferred.type=Expression should have inferred type cannot.refactor.synthesized.function=Cannot refactor synthesized function ''{0}'' error.types.in.generated.function=Cannot generate function with erroneous return type +cannot.introduce.parameter.of.0.type=Cannot introduce parameter of type ''{0}'' 0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.declaration={0} has detected {1} code {1,choice,1#fragment|2#fragments} in this file that can be replaced with a call to extracted declaration. Would you like to review and replace {1,choice,1#it|2#them}? diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt index d62674b9c23..6e40f75c224 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt @@ -36,14 +36,14 @@ import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle import org.jetbrains.kotlin.idea.refactoring.changeSignature.* import org.jetbrains.kotlin.idea.refactoring.introduce.KotlinIntroduceHandlerBase import org.jetbrains.kotlin.idea.refactoring.introduce.selectElementsWithTargetParent +import org.jetbrains.kotlin.idea.refactoring.introduce.showErrorHint import org.jetbrains.kotlin.idea.refactoring.introduce.showErrorHintByKey import org.jetbrains.kotlin.idea.search.usagesSearch.DefaultSearchHelper import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchTarget import org.jetbrains.kotlin.idea.search.usagesSearch.search -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.idea.util.application.executeCommand import org.jetbrains.kotlin.idea.util.application.runWriteAction -import org.jetbrains.kotlin.idea.util.approximateWithResolvableType import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiUnifier import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange import org.jetbrains.kotlin.psi.* @@ -139,11 +139,20 @@ public open class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() e is JetObjectDeclaration || (e is JetClass && !e.isInner()) fun invoke(project: Project, editor: Editor, expression: JetExpression, targetParent: JetNamedDeclaration) { - val psiFactory = JetPsiFactory(project) + val context = expression.analyze() + + val expressionType = context[BindingContext.EXPRESSION_TYPE, expression] + if (expressionType.isUnit() || expressionType.isNothing()) { + val message = JetRefactoringBundle.message( + "cannot.introduce.parameter.of.0.type", + IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(expressionType) + ) + showErrorHint(project, editor, message, INTRODUCE_PARAMETER) + return + } val parameterList = targetParent.getValueParameterList() - val context = expression.analyze() val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, targetParent] val functionDescriptor: FunctionDescriptor = when (descriptor) { @@ -151,7 +160,6 @@ public open class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() is ClassDescriptor -> descriptor.getUnsubstitutedPrimaryConstructor() else -> null } ?: throw AssertionError("Unexpected element type: ${JetPsiUtil.getElementTextWithContext(targetParent)}") - val expressionType = context[BindingContext.EXPRESSION_TYPE, expression] ?: KotlinBuiltIns.getInstance().getAnyType() val parameterType = expressionType.approximateWithResolvableType(JetScopeUtils.getResolutionScope(targetParent, context), false) val body = when (targetParent) { @@ -197,6 +205,8 @@ public open class KotlinIntroduceParameterHandler: KotlinIntroduceHandlerBase() .filterNotNull() project.executeCommand(INTRODUCE_PARAMETER) { + val psiFactory = JetPsiFactory(project) + val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(parameterType) val newParameter = psiFactory.createParameter("${suggestedNames.first()}: $renderedType") diff --git a/idea/testData/refactoring/introduceParameter/assignment.kt b/idea/testData/refactoring/introduceParameter/assignment.kt new file mode 100644 index 00000000000..2ee0c7cccad --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/assignment.kt @@ -0,0 +1,6 @@ +fun foo(): Int { + var x = 1 + x = x + 1 + + return 1 + x +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/assignment.kt.conflicts b/idea/testData/refactoring/introduceParameter/assignment.kt.conflicts new file mode 100644 index 00000000000..58668cdaac7 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/assignment.kt.conflicts @@ -0,0 +1 @@ +Cannot introduce parameter of type 'Unit' \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/fun.kt b/idea/testData/refactoring/introduceParameter/fun.kt new file mode 100644 index 00000000000..88fc5d22443 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/fun.kt @@ -0,0 +1,5 @@ +fun foo(): Int { + fun bar() = 1 + + return 1 + bar() +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/fun.kt.conflicts b/idea/testData/refactoring/introduceParameter/fun.kt.conflicts new file mode 100644 index 00000000000..58668cdaac7 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/fun.kt.conflicts @@ -0,0 +1 @@ +Cannot introduce parameter of type 'Unit' \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/localVar.kt b/idea/testData/refactoring/introduceParameter/localVar.kt new file mode 100644 index 00000000000..bd833f4e00b --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/localVar.kt @@ -0,0 +1,5 @@ +fun foo(): Int { + val x = 1 + + return 1 + x +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/localVar.kt.conflicts b/idea/testData/refactoring/introduceParameter/localVar.kt.conflicts new file mode 100644 index 00000000000..58668cdaac7 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/localVar.kt.conflicts @@ -0,0 +1 @@ +Cannot introduce parameter of type 'Unit' \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/return.kt b/idea/testData/refactoring/introduceParameter/return.kt new file mode 100644 index 00000000000..0d2f5259ebc --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/return.kt @@ -0,0 +1,3 @@ +fun foo(): Int { + return 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/return.kt.conflicts b/idea/testData/refactoring/introduceParameter/return.kt.conflicts new file mode 100644 index 00000000000..7d5b983958e --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/return.kt.conflicts @@ -0,0 +1 @@ +Cannot introduce parameter of type 'Nothing' \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/throw.kt b/idea/testData/refactoring/introduceParameter/throw.kt new file mode 100644 index 00000000000..ed75c76934a --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/throw.kt @@ -0,0 +1,3 @@ +fun foo(): Int { + throw Exception() +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/throw.kt.conflicts b/idea/testData/refactoring/introduceParameter/throw.kt.conflicts new file mode 100644 index 00000000000..7d5b983958e --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/throw.kt.conflicts @@ -0,0 +1 @@ +Cannot introduce parameter of type 'Nothing' \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/while.kt b/idea/testData/refactoring/introduceParameter/while.kt new file mode 100644 index 00000000000..5e9200553d1 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/while.kt @@ -0,0 +1,5 @@ +fun foo(): Int { + while (false) {} + + return 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceParameter/while.kt.conflicts b/idea/testData/refactoring/introduceParameter/while.kt.conflicts new file mode 100644 index 00000000000..58668cdaac7 --- /dev/null +++ b/idea/testData/refactoring/introduceParameter/while.kt.conflicts @@ -0,0 +1 @@ +Cannot introduce parameter of type 'Unit' \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java index a22ccd2a8af..0044f3c5b6c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java @@ -2149,6 +2149,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/introduceParameter"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("assignment.kt") + public void testAssignment() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/assignment.kt"); + doIntroduceParameterTest(fileName); + } + @TestMetadata("classInAnonymousInitializer.kt") public void testClassInAnonymousInitializer() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/classInAnonymousInitializer.kt"); @@ -2233,6 +2239,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doIntroduceParameterTest(fileName); } + @TestMetadata("fun.kt") + public void testFun() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/fun.kt"); + doIntroduceParameterTest(fileName); + } + @TestMetadata("functionMultipleUnusedParameters.kt") public void testFunctionMultipleUnusedParameters() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/functionMultipleUnusedParameters.kt"); @@ -2275,18 +2287,36 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doIntroduceParameterTest(fileName); } + @TestMetadata("localVar.kt") + public void testLocalVar() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/localVar.kt"); + doIntroduceParameterTest(fileName); + } + @TestMetadata("propertyAccessor.kt") public void testPropertyAccessor() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/propertyAccessor.kt"); doIntroduceParameterTest(fileName); } + @TestMetadata("return.kt") + public void testReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/return.kt"); + doIntroduceParameterTest(fileName); + } + @TestMetadata("secondaryConstructorWithDefaultValue.kt") public void testSecondaryConstructorWithDefaultValue() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/secondaryConstructorWithDefaultValue.kt"); doIntroduceParameterTest(fileName); } + @TestMetadata("throw.kt") + public void testThrow() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/throw.kt"); + doIntroduceParameterTest(fileName); + } + @TestMetadata("valueAtCallSite.kt") public void testValueAtCallSite() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/valueAtCallSite.kt"); @@ -2298,5 +2328,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/valueAtCallSiteMultipleUsages.kt"); doIntroduceParameterTest(fileName); } + + @TestMetadata("while.kt") + public void testWhile() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceParameter/while.kt"); + doIntroduceParameterTest(fileName); + } } }