diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java index a21e41301f9..eeb4b62f663 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java @@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.LocalTimeCounter; +import kotlin.KotlinPackage; import kotlin.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.plugin.JetFileType; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -526,8 +528,10 @@ public class JetPsiFactory { static enum State { MODIFIERS, NAME, + RECEIVER, FIRST_PARAM, REST_PARAMS, + TYPE_CONSTRAINTS, BODY, DONE } @@ -543,7 +547,7 @@ public class JetPsiFactory { sb.append(")"); - state = State.BODY; + state = State.TYPE_CONSTRAINTS; } private void placeFun() { @@ -554,7 +558,7 @@ public class JetPsiFactory { } sb.append("fun "); - state = State.NAME; + state = State.RECEIVER; } @NotNull @@ -567,23 +571,28 @@ public class JetPsiFactory { } @NotNull - public FunctionBuilder receiver(@NotNull String receiverType) { + public FunctionBuilder typeParams(@NotNull Collection values) { placeFun(); - sb.append(receiverType).append("."); + if (!values.isEmpty()) { + sb.append(KotlinPackage.makeString(values, ", ", "<", "> ", -1, "")); + } return this; } @NotNull - public FunctionBuilder noReceiver() { - placeFun(); + public FunctionBuilder receiver(@NotNull String receiverType) { + assert state == State.RECEIVER; + + sb.append(receiverType).append("."); + state = State.NAME; return this; } @NotNull public FunctionBuilder name(@NotNull String name) { - assert state == State.NAME; + assert state == State.NAME || state == State.RECEIVER; sb.append(name).append("("); state = State.FIRST_PARAM; @@ -621,9 +630,21 @@ public class JetPsiFactory { return this; } + @NotNull + public FunctionBuilder typeConstraints(@NotNull Collection values) { + assert state == State.TYPE_CONSTRAINTS; + + if (!values.isEmpty()) { + sb.append(KotlinPackage.makeString(values, ", ", " where ", "", -1, "")); + } + state = State.BODY; + + return this; + } + @NotNull public FunctionBuilder simpleBody(@NotNull String body) { - assert state == State.BODY; + assert state == State.BODY || state == State.TYPE_CONSTRAINTS; sb.append(" = ").append(body); state = State.DONE; @@ -633,7 +654,7 @@ public class JetPsiFactory { @NotNull public FunctionBuilder blockBody(@NotNull String body) { - assert state == State.BODY; + assert state == State.BODY || state == State.TYPE_CONSTRAINTS; sb.append(" {\n").append(body).append("\n}"); state = State.DONE; diff --git a/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java b/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java index d2926ddb926..648b0215d5c 100644 --- a/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java +++ b/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java @@ -125,17 +125,27 @@ public class DFS { } } - public static abstract class NodeHandlerWithListResult extends AbstractNodeHandler> { + public static abstract class CollectingNodeHandler> extends AbstractNodeHandler { @NotNull - protected final LinkedList result = new LinkedList(); + protected final C result; + + protected CollectingNodeHandler(@NotNull C result) { + this.result = result; + } @Override @NotNull - public List result() { + public C result() { return result; } } + public static abstract class NodeHandlerWithListResult extends CollectingNodeHandler> { + protected NodeHandlerWithListResult() { + super(new LinkedList()); + } + } + public static class TopologicalOrder extends NodeHandlerWithListResult { @Override public void afterChildren(N current) { 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 62f9eedc8a8..23e4c22ac77 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt @@ -29,6 +29,8 @@ import org.jetbrains.jet.lang.resolve.name.FqName import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode import org.jetbrains.jet.lang.psi.psiUtil.replaced import org.jetbrains.jet.lang.psi.JetQualifiedExpression +import org.jetbrains.jet.lang.psi.JetTypeParameter +import org.jetbrains.jet.lang.psi.JetTypeConstraint data class Parameter( val argumentText: String, @@ -40,6 +42,11 @@ data class Parameter( val nameForRef: String get() = mirrorVarName ?: name } +data class TypeParameter( + val originalDeclaration: JetTypeParameter, + val originalConstraints: List +) + trait Replacement: Function1 trait ParameterReplacement : Replacement { @@ -120,6 +127,7 @@ data class ExtractionDescriptor( val visibility: String, val parameters: List, val receiverParameter: Parameter?, + val typeParameters: List, val replacementMap: Map, val controlFlow: ControlFlow ) 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 bd699f4c177..8a6140f5a40 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt @@ -86,9 +86,20 @@ import java.util.Collections import com.intellij.psi.PsiNamedElement import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor import org.jetbrains.jet.lang.types.ErrorUtils +import org.jetbrains.jet.lang.psi.JetTypeParameter +import org.jetbrains.jet.lang.psi.JetTypeConstraint +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.utils.DFS +import org.jetbrains.jet.utils.DFS.Neighbors +import org.jetbrains.jet.utils.DFS.VisitedWithSet +import org.jetbrains.jet.utils.DFS.AbstractNodeHandler +import org.jetbrains.jet.utils.DFS.CollectingNodeHandler +import org.jetbrains.jet.lang.resolve.BindingContextUtils import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache import org.jetbrains.jet.lang.diagnostics.Errors +import org.jetbrains.jet.lang.psi.JetTypeReference +import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner import org.jetbrains.jet.lang.descriptors.FunctionDescriptor private val DEFAULT_FUNCTION_NAME = "myFun" @@ -227,13 +238,75 @@ private fun ExtractionData.createTemporaryCodeBlock(): JetBlockExpression { return tmpFunction.getBodyExpression() as JetBlockExpression } +private fun JetType.collectReferencedTypes(): List { + return DFS.dfsFromNode( + this, + object: Neighbors { + override fun getNeighbors(current: JetType): Iterable = current.getArguments().map { it.getType() } + }, + VisitedWithSet(), + object: CollectingNodeHandler>(ArrayList()) { + override fun afterChildren(current: JetType) { + result.add(current) + } + } + )!! +} + +fun JetTypeParameter.collectRelevantConstraints(): List { + val typeConstraints = getParentByType(javaClass())?.getTypeConstraints() + if (typeConstraints == null) return Collections.emptyList() + return typeConstraints.filter { it.getSubjectTypeParameterName()?.getReference()?.resolve() == this} +} + +fun TypeParameter.collectReferencedTypes(bindingContext: BindingContext): List { + val typeRefs = ArrayList() + originalDeclaration.getExtendsBound()?.let { typeRefs.add(it) } + originalConstraints + .map { it.getBoundTypeReference() } + .filterNotNullTo(typeRefs) + + return typeRefs + .map { bindingContext[BindingContext.TYPE, it] } + .filterNotNull() +} + +private fun JetType.processTypeIfExtractable( + bindingContext: BindingContext, + typeParameters: MutableSet, + nonDenotableTypes: HashSet +): Boolean { + return collectReferencedTypes().fold(true) { (extractable, typeToCheck) -> + val parameterTypeDescriptor = typeToCheck.getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor + val typeParameter = parameterTypeDescriptor?.let { + BindingContextUtils.descriptorToDeclaration(bindingContext, it) + } as? JetTypeParameter + + when { + typeParameter != null -> { + typeParameters.add(TypeParameter(typeParameter, typeParameter.collectRelevantConstraints())) + extractable + } + + typeToCheck.canBeReferencedViaImport() -> + extractable + + else -> { + nonDenotableTypes.add(typeToCheck) + false + } + } + } +} + private fun ExtractionData.inferParametersInfo( commonParent: PsiElement, localInstructions: List, bindingContext: BindingContext, resultType: JetType?, replacementMap: MutableMap, - parameters: MutableSet + parameters: MutableSet, + typeParameters: MutableSet ): MaybeError? { val varNameValidator = JetNameValidatorImpl( commonParent.getParentByType(javaClass()), @@ -244,6 +317,7 @@ private fun ExtractionData.inferParametersInfo( val extractedDescriptorToParameter = HashMap() val nonDenotableTypes = HashSet() + for (refInfo in getBrokenReferencesInfo(createTemporaryCodeBlock())) { val (originalRef, originalDeclaration, originalDescriptor, resolvedCall) = refInfo.resolveResult val ref = refInfo.refExpr @@ -439,8 +513,10 @@ fun ExtractionData.performAnalysis(): Maybe { val replacementMap = HashMap() val parameters = HashSet() - val parameterError = - inferParametersInfo(commonParent, localInstructions, bindingContext, inferredResultType, replacementMap, parameters) + val typeParameters = HashSet() + val parameterError = inferParametersInfo( + commonParent, localInstructions, bindingContext, inferredResultType, replacementMap, parameters, typeParameters + ) if (parameterError != null) return parameterError val controlFlowInfo = localInstructions.analyzeControlFlow(bindingContext, parameters, inferredResultType) @@ -465,7 +541,16 @@ fun ExtractionData.performAnalysis(): Maybe { receiverParameter?.let { parameters.remove(it) } return MaybeValue( - ExtractionDescriptor(this, functionName, "", parameters.sortBy { it.name }, receiverParameter, replacementMap, controlFlow) + ExtractionDescriptor( + this, + functionName, + "", + parameters.sortBy { it.name }, + receiverParameter, + typeParameters.sortBy { it.originalDeclaration.getName()!! }, + replacementMap, + controlFlow + ) ) } 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 7d14d286379..03311349d02 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 @@ -212,6 +212,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { getVisibility(), ContainerUtil.newArrayList(oldToNewParameters.values()), descriptor.getReceiverParameter(), + descriptor.getTypeParameters(), replacementMap, controlFlow ); diff --git a/idea/testData/refactoring/extractFunction/typeParameters/localClassInBound.kt b/idea/testData/refactoring/extractFunction/typeParameters/localClassInBound.kt new file mode 100644 index 00000000000..a2cc8e14f66 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/localClassInBound.kt @@ -0,0 +1,8 @@ +// NEXT_SIBLING: +fun foo() { + open class X(val x: Int) + + fun bar(t: T): Int { + return t.x + 1 + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/localClassInBound.kt.conflicts b/idea/testData/refactoring/extractFunction/typeParameters/localClassInBound.kt.conflicts new file mode 100644 index 00000000000..eb6536d308e --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/localClassInBound.kt.conflicts @@ -0,0 +1 @@ +Cannot extract method since following types are not denotable in the target scope: foo.X \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/localClassInTypeConstraint.kt b/idea/testData/refactoring/extractFunction/typeParameters/localClassInTypeConstraint.kt new file mode 100644 index 00000000000..af669e9c67a --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/localClassInTypeConstraint.kt @@ -0,0 +1,8 @@ +// NEXT_SIBLING: +fun foo() { + open class X(val x: Int) + + fun bar(t: T): Int where T: X { + return t.x + 1 + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/localClassInTypeConstraint.kt.conflicts b/idea/testData/refactoring/extractFunction/typeParameters/localClassInTypeConstraint.kt.conflicts new file mode 100644 index 00000000000..eb6536d308e --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/localClassInTypeConstraint.kt.conflicts @@ -0,0 +1 @@ +Cannot extract method since following types are not denotable in the target scope: foo.X \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt new file mode 100644 index 00000000000..145b31bea9a --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt @@ -0,0 +1,8 @@ +open class Data(val x: Int) + +class Pair(val a: A, val b: B) + +// NEXT_SIBLING: +fun foo(v: V): Pair { + return Pair(v.x + 10, v) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt.after new file mode 100644 index 00000000000..251a1dce0d2 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt.after @@ -0,0 +1,12 @@ +open class Data(val x: Int) + +class Pair(val a: A, val b: B) + +// NEXT_SIBLING: +fun pair(v: V): Pair { + return Pair(v.x + 10, v) +} + +fun foo(v: V): Pair { + return pair(v) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt new file mode 100644 index 00000000000..b64ae61c7cf --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt @@ -0,0 +1,9 @@ +open class Data(val x: Int) +trait DataEx + +class Pair(val a: A, val b: B) + +// NEXT_SIBLING: +fun foo(v: V): Pair where V: DataEx { + return Pair(v.x + 10, v) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt.after new file mode 100644 index 00000000000..660e5aa0453 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt.after @@ -0,0 +1,13 @@ +open class Data(val x: Int) +trait DataEx + +class Pair(val a: A, val b: B) + +// NEXT_SIBLING: +fun pair(v: V): Pair where V : DataEx { + return Pair(v.x + 10, v) +} + +fun foo(v: V): Pair where V: DataEx { + return pair(v) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt new file mode 100644 index 00000000000..b50daca10ac --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt @@ -0,0 +1,8 @@ +class Data(val t: Int) + +// NEXT_SIBLING: +class A { + fun foo(d: Data): Int { + return d.t + 1 + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt.after new file mode 100644 index 00000000000..673dbda999f --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt.after @@ -0,0 +1,12 @@ +class Data(val t: Int) + +// NEXT_SIBLING: +fun i(d: Data): Int { + return d.t + 1 +} + +class A { + fun foo(d: Data): Int { + return i(d) + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt new file mode 100644 index 00000000000..7e47fcddb6c --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt @@ -0,0 +1,12 @@ +open class Data(val x: Int) +trait DataEx +trait DataExEx + +// NEXT_SIBLING: +class A(val t: T) where T: DataEx { + inner class B(val u: U) where U: DataExEx { + fun foo(v: V): Int where V: DataEx { + return t.x + u.x + v.x + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt.after new file mode 100644 index 00000000000..ff862ccb9f6 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt.after @@ -0,0 +1,16 @@ +open class Data(val x: Int) +trait DataEx +trait DataExEx + +// NEXT_SIBLING: +fun i(a: A, b: A.B, v: V): Int where T : DataEx, U : DataExEx, V : DataEx { + return a.t.x + b.u.x + v.x +} + +class A(val t: T) where T: DataEx { + inner class B(val u: U) where U: DataExEx { + fun foo(v: V): Int where V: DataEx { + return i(this@A, this@B, v) + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt new file mode 100644 index 00000000000..110cc19cba3 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt @@ -0,0 +1,12 @@ +open class Data(val x: Int) +trait DataEx +trait DataExEx + +class A(val t: T) where T: DataEx { + // NEXT_SIBLING: + inner class B(val u: U) where U: DataExEx { + fun foo(v: V): Int where V: DataEx { + return t.x + u.x + v.x + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt.after new file mode 100644 index 00000000000..dd7518e2dcc --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt.after @@ -0,0 +1,16 @@ +open class Data(val x: Int) +trait DataEx +trait DataExEx + +class A(val t: T) where T: DataEx { + // NEXT_SIBLING: + fun B.i(v: V): Int where U : DataExEx, V : DataEx { + return t.x + u.x + v.x + } + + inner class B(val u: U) where U: DataExEx { + fun foo(v: V): Int where V: DataEx { + return i(v) + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt new file mode 100644 index 00000000000..97af228c58e --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt @@ -0,0 +1,12 @@ +open class Data(val x: Int) +trait DataEx +trait DataExEx + +class A(val t: T) where T: DataEx { + inner class B(val u: U) where U: DataExEx { + // NEXT_SIBLING: + fun foo(v: V): Int where V: DataEx { + return t.x + u.x + v.x + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt.after new file mode 100644 index 00000000000..d73dd694eb7 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt.after @@ -0,0 +1,16 @@ +open class Data(val x: Int) +trait DataEx +trait DataExEx + +class A(val t: T) where T: DataEx { + inner class B(val u: U) where U: DataExEx { + // NEXT_SIBLING: + fun i(v: V): Int where V : DataEx { + return t.x + u.x + v.x + } + + fun foo(v: V): Int where V: DataEx { + return i(v) + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt new file mode 100644 index 00000000000..9ef2b678ac9 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt @@ -0,0 +1,10 @@ +open class Data(val x: Int) + +// NEXT_SIBLING: +class A(val t: T) { + inner class B(val u: U) { + fun foo(v: V): Int { + return t.x + u.x + v.x + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt.after new file mode 100644 index 00000000000..894182f0224 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt.after @@ -0,0 +1,14 @@ +open class Data(val x: Int) + +// NEXT_SIBLING: +fun i(a: A, b: A.B, v: V): Int { + return a.t.x + b.u.x + v.x +} + +class A(val t: T) { + inner class B(val u: U) { + fun foo(v: V): Int { + return i(this@A, this@B, v) + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt new file mode 100644 index 00000000000..0f439383434 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt @@ -0,0 +1,10 @@ +open class Data(val x: Int) + +class A(val t: T) { + // NEXT_SIBLING: + inner class B(val u: U) { + fun foo(v: V): Int { + return t.x + u.x + v.x + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt.after new file mode 100644 index 00000000000..5f9cc06b77c --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt.after @@ -0,0 +1,14 @@ +open class Data(val x: Int) + +class A(val t: T) { + // NEXT_SIBLING: + fun B.i(v: V): Int { + return t.x + u.x + v.x + } + + inner class B(val u: U) { + fun foo(v: V): Int { + return i(v) + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt new file mode 100644 index 00000000000..84acd275329 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt @@ -0,0 +1,10 @@ +open class Data(val x: Int) + +class A(val t: T) { + inner class B(val u: U) { + // NEXT_SIBLING: + fun foo(v: V): Int { + return t.x + u.x + v.x + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt.after new file mode 100644 index 00000000000..02b4223d62b --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt.after @@ -0,0 +1,14 @@ +open class Data(val x: Int) + +class A(val t: T) { + inner class B(val u: U) { + // NEXT_SIBLING: + fun i(v: V): Int { + return t.x + u.x + v.x + } + + fun foo(v: V): Int { + return i(v) + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt new file mode 100644 index 00000000000..c4ac1e73665 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt @@ -0,0 +1,9 @@ +open class Data(val x: Int) +trait DataEx + +// NEXT_SIBLING: +class A(val t: T) where T: DataEx { + fun foo(v: V): Int { + return t.x + v.x + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt.after new file mode 100644 index 00000000000..b9dda052e69 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt.after @@ -0,0 +1,13 @@ +open class Data(val x: Int) +trait DataEx + +// NEXT_SIBLING: +fun A.i(v: V): Int where T : DataEx { + return t.x + v.x +} + +class A(val t: T) where T: DataEx { + fun foo(v: V): Int { + return i(v) + } +} \ 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 27195742b07..a5ec2c5395c 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 @@ -186,7 +186,7 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { } @TestMetadata("idea/testData/refactoring/extractFunction") - @InnerTestClasses({ExtractFunction.Basic.class, ExtractFunction.ControlFlow.class, ExtractFunction.Parameters.class}) + @InnerTestClasses({ExtractFunction.Basic.class, ExtractFunction.ControlFlow.class, ExtractFunction.Parameters.class, ExtractFunction.TypeParameters.class}) public static class ExtractFunction extends AbstractJetExtractionTest { public void testAllFilesPresentInExtractFunction() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/refactoring/extractFunction"), Pattern.compile("^(.+)\\.kt$"), true); @@ -618,12 +618,81 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { } } + @TestMetadata("idea/testData/refactoring/extractFunction/typeParameters") + public static class TypeParameters extends AbstractJetExtractionTest { + public void testAllFilesPresentInTypeParameters() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/refactoring/extractFunction/typeParameters"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("localClassInBound.kt") + public void testLocalClassInBound() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/localClassInBound.kt"); + } + + @TestMetadata("localClassInTypeConstraint.kt") + public void testLocalClassInTypeConstraint() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/localClassInTypeConstraint.kt"); + } + + @TestMetadata("simpleTypeParameter.kt") + public void testSimpleTypeParameter() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt"); + } + + @TestMetadata("simpleTypeParameterWithConstraint.kt") + public void testSimpleTypeParameterWithConstraint() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt"); + } + + @TestMetadata("typeParamInArgument.kt") + public void testTypeParamInArgument() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt"); + } + + @TestMetadata("typeParametersAndConstraintsCombined1.kt") + public void testTypeParametersAndConstraintsCombined1() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt"); + } + + @TestMetadata("typeParametersAndConstraintsCombined2.kt") + public void testTypeParametersAndConstraintsCombined2() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt"); + } + + @TestMetadata("typeParametersAndConstraintsCombined3.kt") + public void testTypeParametersAndConstraintsCombined3() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt"); + } + + @TestMetadata("typeParametersCombined1.kt") + public void testTypeParametersCombined1() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt"); + } + + @TestMetadata("typeParametersCombined2.kt") + public void testTypeParametersCombined2() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt"); + } + + @TestMetadata("typeParametersCombined3.kt") + public void testTypeParametersCombined3() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt"); + } + + @TestMetadata("typeParametersCombinedAndThis.kt") + public void testTypeParametersCombinedAndThis() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt"); + } + + } + public static Test innerSuite() { TestSuite suite = new TestSuite("ExtractFunction"); suite.addTestSuite(ExtractFunction.class); suite.addTestSuite(Basic.class); suite.addTest(ControlFlow.innerSuite()); suite.addTest(Parameters.innerSuite()); + suite.addTestSuite(TypeParameters.class); return suite; } }