diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt index 27881877d6a..0ed2f3f9655 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue import org.jetbrains.jet.lang.resolve.OverridingUtil import org.jetbrains.jet.lang.types.TypeUtils import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.LocalFunctionDeclarationInstruction fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean = pseudocode.getUsages(pseudocode.getElementValue(this)).isEmpty() @@ -129,6 +130,13 @@ fun getExpectedTypePredicate(value: PseudoValue, bindingContext: BindingContext) return and(typePredicates.filterNotNull()) } +public fun Instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext: BindingContext): DeclarationDescriptor? { + return when (this) { + is CallInstruction -> return resolvedCall.getResultingDescriptor() + else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext) + } +} + private fun Pseudocode.collectValueUsages(): Map> { val map = HashMap>() traverseFollowingInstructions(getEnterInstruction(), HashSet(), TraversalOrder.FORWARD) { diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/extractFunctionForDebuggerUtil.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/extractFunctionForDebuggerUtil.kt index a932c5024db..2b28584d04d 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/extractFunctionForDebuggerUtil.kt +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/extractFunctionForDebuggerUtil.kt @@ -58,7 +58,7 @@ fun getFunctionForExtractedFragment( ErrorMessage.DECLARATIONS_OUT_OF_SCOPE, ErrorMessage.OUTPUT_AND_EXIT_POINT, ErrorMessage.MULTIPLE_EXIT_POINTS, - ErrorMessage.VARIABLES_ARE_USED_OUTSIDE -> "Cannot perform an action for this expression" + ErrorMessage.DECLARATIONS_ARE_USED_OUTSIDE -> "Cannot perform an action for this expression" } if (errorMessage.additionalInfo == null) message else "$message: ${errorMessage.additionalInfo?.makeString(", ")}" }.makeString(", ") diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/declarations/DeclarationUtils.java b/idea/src/org/jetbrains/jet/plugin/intentions/declarations/DeclarationUtils.java index f87bae2a74a..e771141ef15 100644 --- a/idea/src/org/jetbrains/jet/plugin/intentions/declarations/DeclarationUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/intentions/declarations/DeclarationUtils.java @@ -130,6 +130,18 @@ public class DeclarationUtils { return newInitializer; } + @NotNull + public static JetProperty changePropertyInitializer(@NotNull JetProperty property, @Nullable JetExpression initializer) { + //noinspection ConstantConditions + return JetPsiFactory.createProperty( + property.getProject(), + property.getNameIdentifier().getText(), + JetPsiUtil.getNullableText(property.getTypeRef()), + property.isVar(), + JetPsiUtil.getNullableText(initializer) + ); + } + // Returns joined property @NotNull public static JetProperty joinPropertyDeclarationWithInitializer( @@ -141,14 +153,7 @@ public class DeclarationUtils { JetBinaryExpression assignment = propertyAndInitializer.second; assertNotNull(assignment); - //noinspection ConstantConditions - JetProperty newProperty = JetPsiFactory.createProperty( - property.getProject(), - property.getNameIdentifier().getText(), - JetPsiUtil.getNullableText(property.getTypeRef()), - property.isVar(), - JetPsiUtil.getNullableText(assignment.getRight()) - ); + JetProperty newProperty = changePropertyInitializer(property, assignment.getRight()); property.getParent().deleteChildRange(property.getNextSibling(), assignment); return (JetProperty) property.replace(newProperty); diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties index 6a6f680b914..b77fbf79a3e 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties @@ -10,7 +10,7 @@ extract.function=Extract Function cannot.extract.method=Cannot find statements to extract cannot.find.class.to.extract=Cannot find class to extract method selected.code.fragment.has.multiple.output.values=Selected code fragment has multiple output values: -variables.are.used.outside.of.selected.code.fragment=Following variables are used outside of selected code fragment: +declarations.are.used.outside.of.selected.code.fragment=Following declarations are used outside of selected code fragment: selected.code.fragment.has.multiple.exit.points=Selected code fragment has multiple exit points selected.code.fragment.has.output.values.and.exit.points=Selected code fragment has output values as well as alternative exit points parameter.types.are.not.denotable=Cannot extract method since following types are not denotable in the target scope: diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt index bb2ad696078..a524a03a57a 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt @@ -35,6 +35,8 @@ import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Statu import org.jetbrains.jet.plugin.refactoring.JetRefactoringBundle import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor +import org.jetbrains.jet.lang.psi.JetProperty +import org.jetbrains.jet.lang.psi.JetDeclaration trait Parameter { val argumentText: String @@ -96,9 +98,13 @@ class FqNameReplacement(val fqName: FqName): Replacement { trait ControlFlow { val returnType: JetType + val declarationsToCopy: List } -class DefaultControlFlow(override val returnType: JetType = DEFAULT_RETURN_TYPE): ControlFlow +class DefaultControlFlow( + override val returnType: JetType = DEFAULT_RETURN_TYPE, + override val declarationsToCopy: List +): ControlFlow trait JumpBasedControlFlow : ControlFlow { val elementsToReplace: List @@ -107,26 +113,43 @@ trait JumpBasedControlFlow : ControlFlow { class ConditionalJump( override val elementsToReplace: List, - override val elementToInsertAfterCall: JetElement + override val elementToInsertAfterCall: JetElement, + override val declarationsToCopy: List ): JumpBasedControlFlow { override val returnType: JetType get() = KotlinBuiltIns.getInstance().getBooleanType() } class UnconditionalJump( override val elementsToReplace: List, - override val elementToInsertAfterCall: JetElement + override val elementToInsertAfterCall: JetElement, + override val declarationsToCopy: List ): JumpBasedControlFlow { override val returnType: JetType get() = KotlinBuiltIns.getInstance().getUnitType() } -class ExpressionEvaluation(override val returnType: JetType): ControlFlow +class ExpressionEvaluation( + override val returnType: JetType, + override val declarationsToCopy: List +): ControlFlow -class ExpressionEvaluationWithCallSiteReturn(override val returnType: JetType): ControlFlow +class ExpressionEvaluationWithCallSiteReturn( + override val returnType: JetType, + override val declarationsToCopy: List +): ControlFlow -class ParameterUpdate(val parameter: Parameter): ControlFlow { +class ParameterUpdate( + val parameter: Parameter, + override val declarationsToCopy: List +): ControlFlow { override val returnType: JetType get() = parameter.parameterType } +class Initializer( + val initializedDeclaration: JetProperty, + override val returnType: JetType, + override val declarationsToCopy: List +): ControlFlow + data class ExtractionDescriptor( val extractionData: ExtractionData, val name: String, @@ -157,7 +180,7 @@ class AnalysisResult ( MULTIPLE_OUTPUT OUTPUT_AND_EXIT_POINT MULTIPLE_EXIT_POINTS - VARIABLES_ARE_USED_OUTSIDE + DECLARATIONS_ARE_USED_OUTSIDE DECLARATIONS_OUT_OF_SCOPE var additionalInfo: List? = null @@ -176,7 +199,7 @@ class AnalysisResult ( MULTIPLE_OUTPUT -> "selected.code.fragment.has.multiple.output.values" OUTPUT_AND_EXIT_POINT -> "selected.code.fragment.has.output.values.and.exit.points" MULTIPLE_EXIT_POINTS -> "selected.code.fragment.has.multiple.exit.points" - VARIABLES_ARE_USED_OUTSIDE -> "variables.are.used.outside.of.selected.code.fragment" + DECLARATIONS_ARE_USED_OUTSIDE -> "declarations.are.used.outside.of.selected.code.fragment" DECLARATIONS_OUT_OF_SCOPE -> "declarations.will.move.out.of.scope" })!! if (additionalInfo != null) { diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt index a72994e7634..f7ba32d51ee 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt @@ -66,6 +66,7 @@ import org.jetbrains.jet.lang.resolve.bindingContextUtil.getTargetFunctionDescri import com.intellij.psi.PsiWhiteSpace import org.jetbrains.jet.lang.resolve.OverridingUtil import org.jetbrains.jet.lang.psi.psiUtil.isAncestor +import org.jetbrains.jet.plugin.intentions.declarations.DeclarationUtils import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils private val DEFAULT_FUNCTION_NAME = "myFun" @@ -76,7 +77,7 @@ private fun JetType.isDefault(): Boolean = KotlinBuiltIns.getInstance().isUnit(t private fun List.getModifiedVarDescriptors(bindingContext: BindingContext): Set { return this - .map {if (it is WriteValueInstruction) PseudocodeUtil.extractVariableDescriptorIfAny(it, true, bindingContext) else null} + .map {if (it is WriteValueInstruction) PseudocodeUtil.extractVariableDescriptorIfAny(it, false, bindingContext) else null} .filterNotNullTo(HashSet()) } @@ -115,9 +116,30 @@ private fun JetType.isMeaningful(): Boolean { return KotlinBuiltIns.getInstance().let { builtins -> !builtins.isUnit(this) && !builtins.isNothing(this) } } -private fun List.analyzeControlFlow( +private fun ExtractionData.getLocalDeclarationsWithNonLocalUsages( + pseudocode: Pseudocode, + localInstructions: List, + bindingContext: BindingContext +): List { + val declarations = HashSet() + pseudocode.traverse(TraversalOrder.FORWARD) { instruction -> + if (instruction !in localInstructions) { + instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext)?.let { descriptor -> + val declaration = DescriptorToDeclarationUtil.getDeclaration(project, descriptor) + if (declaration is JetNamedDeclaration && declaration.isInsideOf(originalElements)) { + declarations.add(declaration) + } + } + } + } + return declarations.sortBy { it.getTextRange()!!.getStartOffset() } +} + +private fun ExtractionData.analyzeControlFlow( + localInstructions: List, pseudocode: Pseudocode, bindingContext: BindingContext, + modifiedVarDescriptors: Set, options: ExtractionOptions, parameters: Set ): Pair { @@ -127,7 +149,7 @@ private fun List.analyzeControlFlow( return currentDescriptor == functionDescriptor } - val exitPoints = getExitPoints() + val exitPoints = localInstructions.getExitPoints() val valuedReturnExits = ArrayList() val defaultExits = ArrayList() @@ -173,27 +195,40 @@ private fun List.analyzeControlFlow( } } + val nonLocallyUsedDeclarations = getLocalDeclarationsWithNonLocalUsages(pseudocode, localInstructions, bindingContext) + val (declarationsToCopy, declarationsToReport) = nonLocallyUsedDeclarations.partition { it is JetProperty && it.isLocal() } + val typeOfDefaultFlow = defaultExits.getResultType(pseudocode, bindingContext, options) val returnValueType = valuedReturnExits.getResultType(pseudocode, bindingContext, options) - val defaultControlFlow = DefaultControlFlow(if (returnValueType.isMeaningful()) returnValueType else typeOfDefaultFlow) + val defaultControlFlow = DefaultControlFlow(if (returnValueType.isMeaningful()) returnValueType else typeOfDefaultFlow, declarationsToCopy) + + if (declarationsToReport.isNotEmpty()) { + val localVarStr = declarationsToReport.map { it.getName()!! }.sort() + return Pair(defaultControlFlow, ErrorMessage.DECLARATIONS_ARE_USED_OUTSIDE.addAdditionalInfo(localVarStr)) + } + + val outDeclarations = + declarationsToCopy.filter { bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] in modifiedVarDescriptors } val outParameters = parameters.filterTo(HashSet()) { it.mirrorVarName != null } + val outValuesCount = outDeclarations.size + outParameters.size when { - outParameters.size > 1 -> { - val outValuesStr = outParameters.map { it.argumentText }.sort() - - return Pair( - defaultControlFlow, - ErrorMessage.MULTIPLE_OUTPUT.addAdditionalInfo(outValuesStr) - ) + outValuesCount > 1 -> { + val outValuesStr = (outParameters.map { it.argumentText } + outDeclarations.map { it.getName()!! }).sort() + return Pair(defaultControlFlow, ErrorMessage.MULTIPLE_OUTPUT.addAdditionalInfo(outValuesStr)) } - outParameters.size == 1 -> { + outValuesCount == 1 -> { if (returnValueType.isMeaningful() || typeOfDefaultFlow.isMeaningful() || jumpExits.isNotEmpty()) { return Pair(defaultControlFlow, ErrorMessage.OUTPUT_AND_EXIT_POINT) } - return Pair(ParameterUpdate(outParameters.first()), null) + val controlFlow = + outDeclarations.firstOrNull()?.let { + val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as? CallableDescriptor + Initializer(it as JetProperty, descriptor?.getReturnType() ?: DEFAULT_PARAMETER_TYPE, declarationsToCopy) + } ?: ParameterUpdate(outParameters.first(), declarationsToCopy) + return Pair(controlFlow, null) } } @@ -202,7 +237,7 @@ private fun List.analyzeControlFlow( if (typeOfDefaultFlow.isMeaningful()) { if (valuedReturnExits.isNotEmpty() || jumpExits.isNotEmpty()) return multipleExitsError - return Pair(ExpressionEvaluation(typeOfDefaultFlow), null) + return Pair(ExpressionEvaluation(typeOfDefaultFlow, declarationsToCopy), null) } if (valuedReturnExits.isNotEmpty()) { @@ -212,19 +247,19 @@ private fun List.analyzeControlFlow( if (valuedReturnExits.size != 1) return multipleExitsError val element = valuedReturnExits.first!!.element - return Pair(ConditionalJump(listOf(element), element), null) + return Pair(ConditionalJump(listOf(element), element, declarationsToCopy), null) } if (!valuedReturnExits.checkEquivalence(false)) return multipleExitsError - return Pair(ExpressionEvaluationWithCallSiteReturn(valuedReturnExits.getResultType(pseudocode, bindingContext, options)), null) + return Pair(ExpressionEvaluationWithCallSiteReturn(returnValueType, declarationsToCopy), null) } if (jumpExits.isNotEmpty()) { if (!jumpExits.checkEquivalence(true)) return multipleExitsError val elements = jumpExits.map { it.element } - if (defaultExits.isNotEmpty()) return Pair(ConditionalJump(elements, elements.first!!), null) - return Pair(UnconditionalJump(elements, elements.first!!), null) + if (defaultExits.isNotEmpty()) return Pair(ConditionalJump(elements, elements.first!!, declarationsToCopy), null) + return Pair(UnconditionalJump(elements, elements.first!!, declarationsToCopy), null) } return Pair(defaultControlFlow, null) @@ -364,8 +399,8 @@ private class DelegatingParameter( private fun ExtractionData.inferParametersInfo( commonParent: PsiElement, pseudocode: Pseudocode, - localInstructions: List, bindingContext: BindingContext, + modifiedVarDescriptors: Set, replacementMap: MutableMap, parameters: MutableSet, typeParameters: MutableSet, @@ -376,7 +411,6 @@ private fun ExtractionData.inferParametersInfo( originalElements.first, JetNameValidatorImpl.Target.PROPERTIES ) - val modifiedVarDescriptors = localInstructions.getModifiedVarDescriptors(bindingContext) val extractedDescriptorToParameter = HashMap() @@ -481,33 +515,6 @@ private fun ExtractionData.inferParametersInfo( return null } -private fun ExtractionData.checkLocalDeclarationsWithNonLocalUsages( - pseudocode: Pseudocode, - localInstructions: List, - bindingContext: BindingContext -): ErrorMessage? { - // todo: non-locally used declaration can be turned into the output value - - val declarations = ArrayList() - pseudocode.traverse(TraversalOrder.FORWARD) { instruction -> - if (instruction !in localInstructions) { - PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, bindingContext)?.let { descriptor -> - val declaration = DescriptorToDeclarationUtil.getDeclaration(project, descriptor) - if (declaration is JetNamedDeclaration && declaration.isInsideOf(originalElements)) { - declarations.add(declaration) - } - } - } - } - - if (declarations.isNotEmpty()) { - val localVarStr = declarations.map { it.getName()!! }.sort() - return ErrorMessage.VARIABLES_ARE_USED_OUTSIDE.addAdditionalInfo(localVarStr) - } - - return null -} - private fun ExtractionData.checkDeclarationsMovingOutOfScope(controlFlow: ControlFlow): ErrorMessage? { val declarationsOutOfScope = HashSet() if (controlFlow is JumpBasedControlFlow) { @@ -571,12 +578,14 @@ fun ExtractionData.performAnalysis(): AnalysisResult { val pseudocode = PseudocodeUtil.generatePseudocode(pseudocodeDeclaration, bindingContext) val localInstructions = getLocalInstructions(pseudocode) + val modifiedVarDescriptors = localInstructions.getModifiedVarDescriptors(bindingContext) + val replacementMap = HashMap() val parameters = HashSet() val typeParameters = HashSet() val nonDenotableTypes = HashSet() val parameterError = inferParametersInfo( - commonParent, pseudocode, localInstructions, bindingContext, replacementMap, parameters, typeParameters, nonDenotableTypes + commonParent, pseudocode, bindingContext, modifiedVarDescriptors, replacementMap, parameters, typeParameters, nonDenotableTypes ) if (parameterError != null) { return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(parameterError)) @@ -584,7 +593,8 @@ fun ExtractionData.performAnalysis(): AnalysisResult { val messages = ArrayList() - val (controlFlow, controlFlowMessage) = localInstructions.analyzeControlFlow(pseudocode, bindingContext, options, parameters) + val (controlFlow, controlFlowMessage) = + analyzeControlFlow(localInstructions, pseudocode, bindingContext, modifiedVarDescriptors, options, parameters) controlFlowMessage?.let { messages.add(it) } controlFlow.returnType.processTypeIfExtractable(typeParameters, nonDenotableTypes) @@ -598,7 +608,6 @@ fun ExtractionData.performAnalysis(): AnalysisResult { ) } - checkLocalDeclarationsWithNonLocalUsages(pseudocode, localInstructions, bindingContext)?.let { messages.add(it) } checkDeclarationsMovingOutOfScope(controlFlow)?.let { messages.add(it) } val functionNameValidator = @@ -659,7 +668,7 @@ fun ExtractionDescriptor.validate(): ExtractionDescriptorWithConflicts { && !ErrorUtils.isError(currentDescriptor) && !comparePossiblyOverridingDescriptors(currentDescriptor, resolveResult.descriptor))) { conflicts.putValue( - currentRefExpr, + resolveResult.originalRefExpr, JetRefactoringBundle.message( "0.will.no.longer.be.accessible.after.extraction", RefactoringUIUtil.getDescription(resolveResult.declaration, true) @@ -670,7 +679,7 @@ fun ExtractionDescriptor.validate(): ExtractionDescriptorWithConflicts { diagnostics.firstOrNull { it.getFactory() == Errors.INVISIBLE_MEMBER }?.let { conflicts.putValue( - currentRefExpr, + resolveResult.originalRefExpr, JetRefactoringBundle.message( "0.will.become.invisible.after.extraction", RefactoringUIUtil.getDescription(resolveResult.declaration, true) @@ -823,6 +832,9 @@ fun ExtractionDescriptor.generateFunction( is ParameterUpdate -> body.appendElement(JetPsiFactory.createReturn(project, controlFlow.parameter.nameForRef)) + is Initializer -> + body.appendElement(JetPsiFactory.createReturn(project, controlFlow.initializedDeclaration.getName()!!)) + is ConditionalJump -> body.appendElement(JetPsiFactory.createReturn(project, "false")) @@ -854,7 +866,12 @@ fun ExtractionDescriptor.generateFunction( } } - fun insertCall(anchor: PsiElement, wrappedCall: JetExpression) { + fun insertCall(anchor: PsiElement, wrappedCall: JetExpression?) { + if (wrappedCall == null) { + anchor.delete() + return + } + val firstExpression = extractionData.getExpressions().firstOrNull() val enclosingCall = firstExpression?.getParent() as? JetCallExpression if (enclosingCall == null || firstExpression !in enclosingCall.getFunctionLiteralArguments()) { @@ -879,16 +896,26 @@ fun ExtractionDescriptor.generateFunction( val anchor = extractionData.originalElements.first if (anchor == null) return function + val anchorParent = anchor.getParent()!! + anchor.getNextSibling()?.let { from -> val to = extractionData.originalElements.last if (to != anchor) { - anchor.getParent()!!.deleteChildRange(from, to); + anchorParent.deleteChildRange(from, to); } } val callText = parameters .map { it.argumentText } .joinToString(separator = ", ", prefix = "$name(", postfix = ")") + + val copiedDeclarations = HashMap() + for (decl in controlFlow.declarationsToCopy) { + val declCopy = JetPsiFactory.createDeclaration(project, decl.getText(), javaClass()) + copiedDeclarations[decl] = anchorParent.addBefore(declCopy, anchor) as JetDeclaration + anchorParent.addBefore(JetPsiFactory.createNewLine(project), anchor) + } + val wrappedCall = when (controlFlow) { is ExpressionEvaluationWithCallSiteReturn -> JetPsiFactory.createReturn(project, callText) @@ -896,11 +923,16 @@ fun ExtractionDescriptor.generateFunction( is ParameterUpdate -> JetPsiFactory.createExpression(project, "${controlFlow.parameter.argumentText} = $callText") + is Initializer -> { + val newDecl = copiedDeclarations[controlFlow.initializedDeclaration] as JetProperty + newDecl.replace(DeclarationUtils.changePropertyInitializer(newDecl, JetPsiFactory.createExpression(project, callText))) + null + } + is ConditionalJump -> JetPsiFactory.createExpression(project, "if ($callText) ${controlFlow.elementToInsertAfterCall.getText()}") is UnconditionalJump -> { - val anchorParent = anchor.getParent()!! anchorParent.addAfter( JetPsiFactory.createExpression(project, controlFlow.elementToInsertAfterCall.getText()), anchor diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java index 5719c659f45..a61580d2f76 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java @@ -195,7 +195,11 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { ControlFlow controlFlow = descriptor.getControlFlow(); if (controlFlow instanceof ParameterUpdate) { - controlFlow = new ParameterUpdate(oldToNewParameters.get(((ParameterUpdate) controlFlow).getParameter())); + ParameterUpdate parameterUpdate = (ParameterUpdate) controlFlow; + controlFlow = new ParameterUpdate( + oldToNewParameters.get(parameterUpdate.getParameter()), + parameterUpdate.getDeclarationsToCopy() + ); } Map replacementMap = ContainerUtil.newHashMap(); diff --git a/idea/testData/refactoring/extractFunction/basic/localClassExtraction.kt b/idea/testData/refactoring/extractFunction/basic/localClassExtraction.kt new file mode 100644 index 00000000000..dc5662c77e9 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localClassExtraction.kt @@ -0,0 +1,5 @@ +fun test(): Int { + class A(val n: Int = 1) + + return A().n + 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localClassExtraction.kt.conflicts b/idea/testData/refactoring/extractFunction/basic/localClassExtraction.kt.conflicts new file mode 100644 index 00000000000..bda13e9b848 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localClassExtraction.kt.conflicts @@ -0,0 +1 @@ +Following declarations are used outside of selected code fragment: final class A value-parameter val n: Int = ... \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localFunExtraction.kt b/idea/testData/refactoring/extractFunction/basic/localFunExtraction.kt new file mode 100644 index 00000000000..6b3c6882881 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunExtraction.kt @@ -0,0 +1,5 @@ +fun test(): Int { + fun bar(): Int = 1 + + return bar() + 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/localFunExtraction.kt.conflicts b/idea/testData/refactoring/extractFunction/basic/localFunExtraction.kt.conflicts new file mode 100644 index 00000000000..621332af095 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/basic/localFunExtraction.kt.conflicts @@ -0,0 +1 @@ +Following declarations are used outside of selected code fragment: local final fun bar(): Int \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfAndExtraVars.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfAndExtraVars.kt new file mode 100644 index 00000000000..2ae36919ed7 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfAndExtraVars.kt @@ -0,0 +1,18 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int +// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in foo +// PARAM_DESCRIPTOR: val b: kotlin.Int defined in foo +// SIBLING: +fun foo(a: Int): Int { + val b: Int = 1 + for (n in 1..a) { + if (a + b > 0) break + val c: Int + println(a - b) + if (a - b > 0) break + println(a + b) + c = 1 + println(c) + } + return 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfAndExtraVars.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfAndExtraVars.kt.after new file mode 100644 index 00000000000..40aa83df2cc --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfAndExtraVars.kt.after @@ -0,0 +1,24 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int +// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in foo +// PARAM_DESCRIPTOR: val b: kotlin.Int defined in foo +// SIBLING: +fun foo(a: Int): Int { + val b: Int = 1 + for (n in 1..a) { + val c: Int + if (b(a, b)) break + c = 1 + println(c) + } + return 1 +} + +fun b(a: Int, b: Int): Boolean { + if (a + b > 0) return true + val c: Int + println(a - b) + if (a - b > 0) return true + println(a + b) + return false +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithExtraVars.kt b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithExtraVars.kt new file mode 100644 index 00000000000..aae00c677f6 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithExtraVars.kt @@ -0,0 +1,17 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any +// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in foo +// PARAM_DESCRIPTOR: val b: kotlin.Int defined in foo +// SIBLING: +fun foo(a: Int) { + val b: Int = 1 + + if(a > 0) { + println(a) + } + val c: Int + println(b) + + c = 1 + println(c) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithExtraVars.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithExtraVars.kt.after new file mode 100644 index 00000000000..83018b34df5 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithExtraVars.kt.after @@ -0,0 +1,22 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any +// PARAM_DESCRIPTOR: value-parameter val a: kotlin.Int defined in foo +// PARAM_DESCRIPTOR: val b: kotlin.Int defined in foo +// SIBLING: +fun foo(a: Int) { + val b: Int = 1 + + val c: Int + unit(a, b) + + c = 1 + println(c) +} + +fun unit(a: Int, b: Int) { + if (a > 0) { + println(a) + } + val c: Int + println(b) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializer.kt b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializer.kt new file mode 100644 index 00000000000..5a2778de487 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializer.kt @@ -0,0 +1,5 @@ +// SIBLING: +fun foo() { + val a = 10 + println(a) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializer.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializer.kt.after new file mode 100644 index 00000000000..29251260dba --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializer.kt.after @@ -0,0 +1,10 @@ +// SIBLING: +fun foo() { + val a = i() + println(a) +} + +fun i(): Int { + val a = 10 + return a +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndExtraVars.kt b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndExtraVars.kt new file mode 100644 index 00000000000..89bfe55b107 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndExtraVars.kt @@ -0,0 +1,10 @@ +// SIBLING: +fun foo() { + val a: Int + val b = 10 + val c: Int + + a = 1 + c = 2 + println(a + b + c) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndExtraVars.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndExtraVars.kt.after new file mode 100644 index 00000000000..206b9589fb5 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndExtraVars.kt.after @@ -0,0 +1,17 @@ +// SIBLING: +fun foo() { + val a: Int + val b = i() + val c: Int + + a = 1 + c = 2 + println(a + b + c) +} + +fun i(): Int { + val a: Int + val b = 10 + val c: Int + return b +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndUnusedVars.kt b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndUnusedVars.kt new file mode 100644 index 00000000000..04a23b80c44 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndUnusedVars.kt @@ -0,0 +1,9 @@ +// SIBLING: +fun foo() { + val a: Int + val b = 10 + val c: Int = 1 + + a = 2 + println(a + b) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndUnusedVars.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndUnusedVars.kt.after new file mode 100644 index 00000000000..ad5c5686642 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndUnusedVars.kt.after @@ -0,0 +1,15 @@ +// SIBLING: +fun foo() { + val a: Int + val b = i() + + a = 2 + println(a + b) +} + +fun i(): Int { + val a: Int + val b = 10 + val c: Int = 1 + return b +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithSeparateInitializer.kt b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithSeparateInitializer.kt new file mode 100644 index 00000000000..0b8d532a956 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithSeparateInitializer.kt @@ -0,0 +1,6 @@ +// SIBLING: +fun foo() { + val a: Int + a = 10 + println(a) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithSeparateInitializer.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithSeparateInitializer.kt.after new file mode 100644 index 00000000000..b0f7df39a91 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithSeparateInitializer.kt.after @@ -0,0 +1,11 @@ +// SIBLING: +fun foo() { + val a: Int = i() + println(a) +} + +fun i(): Int { + val a: Int + a = 10 + return a +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInAnonymousObject.kt similarity index 100% rename from idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt rename to idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInAnonymousObject.kt diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInAnonymousObject.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInAnonymousObject.kt.after new file mode 100644 index 00000000000..b872eef2275 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInAnonymousObject.kt.after @@ -0,0 +1,16 @@ +// SIBLING: +fun main(args: Array) { + val a = i() + val t = object: T { + override fun foo(n: Int) = n + a + } +} + +fun i(): Int { + val a = 1 + return a +} + +trait T { + fun foo(n: Int): Int +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLambda.kt similarity index 100% rename from idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt rename to idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLambda.kt diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLambda.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLambda.kt.after new file mode 100644 index 00000000000..c2601d65dac --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLambda.kt.after @@ -0,0 +1,14 @@ +// SIBLING: +fun main(args: Array) { + val a = i() + lambda { + a + } +} + +fun i(): Int { + val a = 1 + return a +} + +fun lambda(f: () -> Unit) {} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLocalFunction.kt similarity index 100% rename from idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt rename to idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLocalFunction.kt diff --git a/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLocalFunction.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLocalFunction.kt.after new file mode 100644 index 00000000000..7bbff1dcba1 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLocalFunction.kt.after @@ -0,0 +1,10 @@ +// SIBLING: +fun main(args: Array) { + val a = i() + fun foo() = a +} + +fun i(): Int { + val a = 1 + return a +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleInitalizersWithNonLocalUsages.kt b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleInitalizersWithNonLocalUsages.kt new file mode 100644 index 00000000000..2cb993c53cb --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleInitalizersWithNonLocalUsages.kt @@ -0,0 +1,6 @@ +// SIBLING: +fun foo() { + val a = 1 + val b = 2 + println(a + b) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleInitalizersWithNonLocalUsages.kt.conflicts b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleInitalizersWithNonLocalUsages.kt.conflicts new file mode 100644 index 00000000000..a4c58b33e7a --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleInitalizersWithNonLocalUsages.kt.conflicts @@ -0,0 +1 @@ +Selected code fragment has multiple output values: a b \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt.conflicts b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt.conflicts deleted file mode 100644 index 87517ea9e65..00000000000 --- a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt.conflicts +++ /dev/null @@ -1 +0,0 @@ -Following variables are used outside of selected code fragment: a \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt.conflicts b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt.conflicts deleted file mode 100644 index 87517ea9e65..00000000000 --- a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt.conflicts +++ /dev/null @@ -1 +0,0 @@ -Following variables are used outside of selected code fragment: a \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt.conflicts b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt.conflicts deleted file mode 100644 index 87517ea9e65..00000000000 --- a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt.conflicts +++ /dev/null @@ -1 +0,0 @@ -Following variables are used outside of selected code fragment: a \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java index 8d9e8f1bcdd..71a0a0e78f2 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java @@ -230,6 +230,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt"); } + @TestMetadata("localClassExtraction.kt") + public void testLocalClassExtraction() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/basic/localClassExtraction.kt"); + } + @TestMetadata("localClassFunctionRef.kt") public void testLocalClassFunctionRef() throws Exception { doExtractFunctionTest("idea/testData/refactoring/extractFunction/basic/localClassFunctionRef.kt"); @@ -245,6 +250,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/basic/localExtraction.kt"); } + @TestMetadata("localFunExtraction.kt") + public void testLocalFunExtraction() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/basic/localFunExtraction.kt"); + } + @TestMetadata("localFunctionRef.kt") public void testLocalFunctionRef() throws Exception { doExtractFunctionTest("idea/testData/refactoring/extractFunction/basic/localFunctionRef.kt"); @@ -288,7 +298,7 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { } @TestMetadata("idea/testData/refactoring/extractFunction/controlFlow") - @InnerTestClasses({ControlFlow.ConditionalJumps.class, ControlFlow.Default.class, ControlFlow.DefiniteReturns.class, ControlFlow.EvaluateExpression.class, ControlFlow.OutputValues.class, ControlFlow.Throws.class, ControlFlow.Unextractable.class}) + @InnerTestClasses({ControlFlow.ConditionalJumps.class, ControlFlow.Default.class, ControlFlow.DefiniteReturns.class, ControlFlow.EvaluateExpression.class, ControlFlow.Initializer.class, ControlFlow.OutputValues.class, ControlFlow.Throws.class, ControlFlow.Unextractable.class}) public static class ControlFlow extends AbstractJetExtractionTest { public void testAllFilesPresentInControlFlow() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/refactoring/extractFunction/controlFlow"), Pattern.compile("^(.+)\\.kt$"), true); @@ -305,6 +315,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt"); } + @TestMetadata("conditionalBreakWithIfAndExtraVars.kt") + public void testConditionalBreakWithIfAndExtraVars() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfAndExtraVars.kt"); + } + @TestMetadata("conditionalBreakWithIfElse.kt") public void testConditionalBreakWithIfElse() throws Exception { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt"); @@ -358,6 +373,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt"); } + @TestMetadata("defaultCFWithExtraVars.kt") + public void testDefaultCFWithExtraVars() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithExtraVars.kt"); + } + @TestMetadata("defaultCFWithJumps.kt") public void testDefaultCFWithJumps() throws Exception { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt"); @@ -481,6 +501,49 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { } + @TestMetadata("idea/testData/refactoring/extractFunction/controlFlow/initializer") + public static class Initializer extends AbstractJetExtractionTest { + public void testAllFilesPresentInInitializer() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/refactoring/extractFunction/controlFlow/initializer"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("propertyWithInitializer.kt") + public void testPropertyWithInitializer() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializer.kt"); + } + + @TestMetadata("propertyWithInitializerAndExtraVars.kt") + public void testPropertyWithInitializerAndExtraVars() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndExtraVars.kt"); + } + + @TestMetadata("propertyWithInitializerAndUnusedVars.kt") + public void testPropertyWithInitializerAndUnusedVars() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithInitializerAndUnusedVars.kt"); + } + + @TestMetadata("propertyWithSeparateInitializer.kt") + public void testPropertyWithSeparateInitializer() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/initializer/propertyWithSeparateInitializer.kt"); + } + + @TestMetadata("valueUsedInAnonymousObject.kt") + public void testValueUsedInAnonymousObject() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInAnonymousObject.kt"); + } + + @TestMetadata("valueUsedInLambda.kt") + public void testValueUsedInLambda() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLambda.kt"); + } + + @TestMetadata("valueUsedInLocalFunction.kt") + public void testValueUsedInLocalFunction() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/initializer/valueUsedInLocalFunction.kt"); + } + + } + @TestMetadata("idea/testData/refactoring/extractFunction/controlFlow/outputValues") public static class OutputValues extends AbstractJetExtractionTest { public void testAllFilesPresentInOutputValues() throws Exception { @@ -588,6 +651,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/jumpsAndReturns.kt"); } + @TestMetadata("multipleInitalizersWithNonLocalUsages.kt") + public void testMultipleInitalizersWithNonLocalUsages() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleInitalizersWithNonLocalUsages.kt"); + } + @TestMetadata("multipleJumps.kt") public void testMultipleJumps() throws Exception { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/multipleJumps.kt"); @@ -608,21 +676,6 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/outputValueWithReturn.kt"); } - @TestMetadata("valueUsedInAnonymousObject.kt") - public void testValueUsedInAnonymousObject() throws Exception { - doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt"); - } - - @TestMetadata("valueUsedInLambda.kt") - public void testValueUsedInLambda() throws Exception { - doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt"); - } - - @TestMetadata("valueUsedInLocalFunction.kt") - public void testValueUsedInLocalFunction() throws Exception { - doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt"); - } - @TestMetadata("variablesOutOfScope.kt") public void testVariablesOutOfScope() throws Exception { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/variablesOutOfScope.kt"); @@ -637,6 +690,7 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { suite.addTestSuite(Default.class); suite.addTestSuite(DefiniteReturns.class); suite.addTestSuite(EvaluateExpression.class); + suite.addTestSuite(Initializer.class); suite.addTestSuite(OutputValues.class); suite.addTestSuite(Throws.class); suite.addTestSuite(Unextractable.class);