Introduce Parameter: Do not apply to expressions of type Unit or Nothing

This commit is contained in:
Alexey Sedunov
2015-04-09 20:37:37 +03:00
parent 54392e7064
commit da14222c4a
16 changed files with 86 additions and 5 deletions
@@ -32,6 +32,7 @@ fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this)
fun JetType.supertypes(): Set<JetType> = TypeUtils.getAllSupertypes(this)
fun JetType.isNothing(): Boolean = KotlinBuiltIns.isNothing(this)
fun JetType.isUnit(): Boolean = KotlinBuiltIns.isUnit(this)
fun JetType.isAny(): Boolean = KotlinBuiltIns.isAnyOrNullableAny(this)
@@ -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}?
@@ -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")
@@ -0,0 +1,6 @@
fun foo(): Int {
var x = 1
<selection>x = x + 1</selection>
return 1 + x
}
@@ -0,0 +1 @@
Cannot introduce parameter of type 'Unit'
@@ -0,0 +1,5 @@
fun foo(): Int {
<selection>fun bar() = 1</selection>
return 1 + bar()
}
@@ -0,0 +1 @@
Cannot introduce parameter of type 'Unit'
@@ -0,0 +1,5 @@
fun foo(): Int {
<selection>val x = 1</selection>
return 1 + x
}
@@ -0,0 +1 @@
Cannot introduce parameter of type 'Unit'
@@ -0,0 +1,3 @@
fun foo(): Int {
<selection>return 1</selection>
}
@@ -0,0 +1 @@
Cannot introduce parameter of type 'Nothing'
@@ -0,0 +1,3 @@
fun foo(): Int {
<selection>throw Exception()</selection>
}
@@ -0,0 +1 @@
Cannot introduce parameter of type 'Nothing'
@@ -0,0 +1,5 @@
fun foo(): Int {
<selection>while (false) {}</selection>
return 1
}
@@ -0,0 +1 @@
Cannot introduce parameter of type 'Unit'
@@ -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);
}
}
}