Create From Usage: Use supplied type arguments to infer function type parameters

This commit is contained in:
Alexey Sedunov
2014-10-22 20:32:21 +04:00
parent a13f334df2
commit abbbd198fd
27 changed files with 393 additions and 38 deletions
@@ -51,7 +51,6 @@ import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
import org.jetbrains.jet.plugin.refactoring.EmptyValidator
import org.jetbrains.jet.plugin.refactoring.CollectingValidator
import org.jetbrains.jet.plugin.util.isUnit
import com.intellij.util.ArrayUtil
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.PsiElement
import org.jetbrains.jet.lexer.JetTokens
@@ -59,6 +58,13 @@ import org.jetbrains.jet.plugin.util.application.runWriteAction
import org.jetbrains.jet.plugin.refactoring.isMultiLine
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
import com.intellij.psi.SmartPointerManager
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl
import java.util.LinkedHashMap
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList"
private val TEMPLATE_FROM_USAGE_FUNCTION_BODY = "New Kotlin Function Body.kt"
@@ -71,12 +77,14 @@ class TypeCandidate(val theType: JetType, scope: JetScope? = null) {
public val typeParameters: Array<TypeParameterDescriptor>
var renderedType: String? = null
private set
var typeParameterNames: Array<String>? = null
var renderedTypeParameters: List<RenderedTypeParameter>? = null
private set
fun render(typeParameterNameMap: Map<TypeParameterDescriptor, String>) {
fun render(typeParameterNameMap: Map<TypeParameterDescriptor, String>, fakeFunction: FunctionDescriptor) {
renderedType = theType.renderShort(typeParameterNameMap);
typeParameterNames = typeParameters.map { typeParameterNameMap[it]!! }.copyToArray()
renderedTypeParameters = typeParameters.map {
RenderedTypeParameter(it, it.getContainingDeclaration() == fakeFunction, typeParameterNameMap[it]!!)
}
}
{
@@ -93,6 +101,12 @@ class TypeCandidate(val theType: JetType, scope: JetScope? = null) {
override fun toString() = theType.toString()
}
class RenderedTypeParameter(
val typeParameter: TypeParameterDescriptor,
val fake: Boolean,
val text: String
)
fun List<TypeCandidate>.getTypeByRenderedType(renderedType: String): JetType? =
firstOrNull { it.renderedType == renderedType }?.theType
@@ -140,7 +154,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
fun computeTypeCandidates(
typeInfo: TypeInfo,
substitutions: Array<JetTypeSubstitution>,
substitutions: List<JetTypeSubstitution>,
scope: JetScope): List<TypeCandidate> {
if (typeInfo is TypeInfo.ByType && typeInfo.keepUnsubstituted) return computeTypeCandidates(typeInfo)
return typeCandidates.getOrPut(typeInfo) {
@@ -201,6 +215,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val receiverClassDescriptor: ClassDescriptor?
val typeParameterNameMap: Map<TypeParameterDescriptor, String>
val receiverTypeCandidate: TypeCandidate?
val substitutions: List<JetTypeSubstitution>
{
// gather relevant information
@@ -213,7 +228,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
containingElement = placement.containingElement
}
placement is CallablePlacement.WithReceiver -> {
receiverClassDescriptor = DescriptorUtils.getClassDescriptorForType(placement.receiverTypeCandidate.theType)
receiverClassDescriptor =
placement.receiverTypeCandidate.theType.getConstructor().getDeclarationDescriptor() as? ClassDescriptor
val classDeclaration = receiverClassDescriptor?.let { DescriptorToSourceUtils.classDescriptorToDeclaration(it) }
isExtension = !(classDeclaration is JetClassOrObject && classDeclaration.isWritable())
containingElement = if (isExtension) config.currentFile else classDeclaration as JetElement
@@ -239,13 +255,18 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
// figure out type substitutions for type parameters
val classTypeParameters = receiverType?.getArguments() ?: Collections.emptyList()
val ownerTypeArguments = (placement as? CallablePlacement.WithReceiver)?.receiverTypeCandidate?.theType?.getArguments()
?: Collections.emptyList()
assert(ownerTypeArguments.size == classTypeParameters.size)
val substitutions = ownerTypeArguments.zip(classTypeParameters).map {
JetTypeSubstitution(it.first.getType(), it.second.getType())
}.copyToArray()
val substitutionMap = LinkedHashMap<JetType, JetType>()
collectSubstitutionsForReceiverTypeParameters(receiverType, substitutionMap)
val typeArgumentsForFakeFunction = callableInfo.typeParameterInfos
.map {
val typeCandidates = computeTypeCandidates(it)
assert (typeCandidates.size == 1, "Ambiguous type candidates for type parameter $it: $typeCandidates")
typeCandidates.first().theType
}
.subtract(substitutionMap.keySet())
val fakeFunction = createFakeFunctionDescriptor(scope, typeArgumentsForFakeFunction.size)
collectSubstitutionsForCallableTypeParameters(fakeFunction, typeArgumentsForFakeFunction, substitutionMap)
substitutions = substitutionMap.map { JetTypeSubstitution(it.key, it.value) }
callableInfo.parameterInfos.forEach {
computeTypeCandidates(it.typeInfo, substitutions, scope)
@@ -261,18 +282,61 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
// figure out type parameter renames to avoid conflicts
typeParameterNameMap = getTypeParameterRenames(scope)
callableInfo.parameterInfos.forEach { renderTypeCandidates(it.typeInfo, typeParameterNameMap) }
callableInfo.parameterInfos.forEach { renderTypeCandidates(it.typeInfo, typeParameterNameMap, fakeFunction) }
if (!skipReturnType) {
renderTypeCandidates(callableInfo.returnTypeInfo, typeParameterNameMap)
renderTypeCandidates(callableInfo.returnTypeInfo, typeParameterNameMap, fakeFunction)
}
receiverTypeCandidate?.render(typeParameterNameMap)
receiverTypeCandidate?.render(typeParameterNameMap, fakeFunction)
}
private fun collectSubstitutionsForReceiverTypeParameters(
receiverType: JetType?,
result: MutableMap<JetType, JetType>
) {
val classTypeParameters = receiverType?.getArguments() ?: Collections.emptyList()
val ownerTypeArguments = (placement as? CallablePlacement.WithReceiver)?.receiverTypeCandidate?.theType?.getArguments()
?: Collections.emptyList()
assert(ownerTypeArguments.size == classTypeParameters.size)
ownerTypeArguments.zip(classTypeParameters).forEach { result[it.first.getType()] = it.second.getType() }
}
private fun collectSubstitutionsForCallableTypeParameters(
fakeFunction: FunctionDescriptor,
typeArguments: Set<JetType>,
result: MutableMap<JetType, JetType>) {
for ((typeArgument, typeParameter) in typeArguments zip fakeFunction.getTypeParameters()) {
result[typeArgument] = typeParameter.getDefaultType()
}
}
private fun createFakeFunctionDescriptor(scope: JetScope, typeParameterCount: Int): FunctionDescriptor {
val fakeFunction = SimpleFunctionDescriptorImpl.create(
MutablePackageFragmentDescriptor(currentFileModule, FqName("fake")),
Annotations.EMPTY,
Name.identifier("fake"),
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
)
val validator = CollectingValidator { scope.getClassifier(Name.identifier(it)) == null }
val typeParameters = typeParameterCount.indices.map {
TypeParameterDescriptorImpl.createWithDefaultBound(
fakeFunction,
Annotations.EMPTY,
false,
Variance.INVARIANT,
Name.identifier(validator.validateName("T")),
it
)
}
return fakeFunction.initialize(null, null, typeParameters, Collections.emptyList(), null, null, Visibilities.INTERNAL)
}
private fun renderTypeCandidates(
typeInfo: TypeInfo,
typeParameterNameMap: Map<TypeParameterDescriptor, String>
typeParameterNameMap: Map<TypeParameterDescriptor, String>,
fakeFunction: FunctionDescriptor
) {
typeCandidates[typeInfo]?.forEach { it.render(typeParameterNameMap) }
typeCandidates[typeInfo]?.forEach { it.render(typeParameterNameMap, fakeFunction) }
}
private fun createDeclarationSkeleton(): JetCallableDeclaration {
@@ -474,6 +538,16 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
func.getBodyExpression()!!.replace(newBodyExpression)
}
private fun setupCallTypeArguments(callExpr: JetCallExpression, typeParameters: List<TypeParameterDescriptor>) {
val oldTypeArgumentList = callExpr.getTypeArgumentList() ?: return
val renderedTypeArgs = typeParameters.map { typeParameter ->
val type = substitutions.first { it.byType.getConstructor().getDeclarationDescriptor() == typeParameter }.forType
IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
}
oldTypeArgumentList.replace(JetPsiFactory(callExpr).createTypeArguments(renderedTypeArgs.joinToString(", ", "<", ">")))
elementsToShorten.add(callExpr.getTypeArgumentList())
}
private fun setupReturnTypeTemplate(builder: TemplateBuilder, declaration: JetCallableDeclaration): TypeExpression? {
val returnTypeRef = declaration.getTypeReference() ?: return null
val candidates = typeCandidates[callableInfo.returnTypeInfo]!!
@@ -500,16 +574,16 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
private fun setupTypeParameterListTemplate(builder: TemplateBuilderImpl, declaration: JetCallableDeclaration): TypeParameterListExpression {
val typeParameterMap = HashMap<String, Array<String>>()
val receiverTypeParameterNames = receiverTypeCandidate?.let { it.typeParameterNames!! } ?: ArrayUtil.EMPTY_STRING_ARRAY
val typeParameterMap = HashMap<String, List<RenderedTypeParameter>>()
val receiverTypeParameterNames = receiverTypeCandidate?.let { it.renderedTypeParameters!! } ?: Collections.emptyList()
callableInfo.parameterInfos.stream().flatMap { typeCandidates[it.typeInfo]!!.stream() }.forEach {
typeParameterMap[it.renderedType!!] = it.typeParameterNames!!
typeParameterMap[it.renderedType!!] = it.renderedTypeParameters!!
}
if (declaration.getTypeReference() != null) {
typeCandidates[callableInfo.returnTypeInfo]!!.forEach {
typeParameterMap[it.renderedType!!] = it.typeParameterNames!!
typeParameterMap[it.renderedType!!] = it.renderedTypeParameters!!
}
}
// ((3, 3) is after "fun")
@@ -618,6 +692,9 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
// file templates
if (newDeclaration is JetNamedFunction) {
setupFunctionBody(newDeclaration)
(config.originalExpression as? JetCallExpression)?.let {
setupCallTypeArguments(it, expression.currentTypeParameters)
}
}
// change short type names to fully qualified ones (to be shortened below)
@@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.types.ErrorUtils
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.psi.JetTypeReference
/**
* Represents a concrete type or a set of types yet to be inferred from an expression.
@@ -32,6 +33,11 @@ abstract class TypeInfo(val variance: Variance) {
expression.guessTypes(builder.currentFileContext, builder.currentFileModule).flatMap { it.getPossibleSupertypes(variance) }
}
class ByTypeReference(val typeReference: JetTypeReference, variance: Variance): TypeInfo(variance) {
override fun getPossibleTypes(builder: CallableBuilder): List<JetType> =
builder.currentFileContext[BindingContext.TYPE, typeReference].getPossibleSupertypes(variance)
}
class ByType(val theType: JetType, variance: Variance, val keepUnsubstituted: Boolean = false): TypeInfo(variance) {
override fun getPossibleTypes(builder: CallableBuilder): List<JetType> =
theType.getPossibleSupertypes(variance)
@@ -45,8 +51,8 @@ abstract class TypeInfo(val variance: Variance) {
open val possibleNamesFromExpression: Array<String> get() = ArrayUtil.EMPTY_STRING_ARRAY
abstract fun getPossibleTypes(builder: CallableBuilder): List<JetType>
protected fun JetType.getPossibleSupertypes(variance: Variance): List<JetType> {
if (ErrorUtils.containsErrorType(this)) return Collections.singletonList(KotlinBuiltIns.getInstance().getAnyType())
protected fun JetType?.getPossibleSupertypes(variance: Variance): List<JetType> {
if (this == null || ErrorUtils.containsErrorType(this)) return Collections.singletonList(KotlinBuiltIns.getInstance().getAnyType())
val single = Collections.singletonList(this)
return when (variance) {
Variance.IN_VARIANCE -> single + supertypes()
@@ -56,6 +62,7 @@ abstract class TypeInfo(val variance: Variance) {
}
fun TypeInfo(expressionOfType: JetExpression, variance: Variance): TypeInfo = TypeInfo.ByExpression(expressionOfType, variance)
fun TypeInfo(typeReference: JetTypeReference, variance: Variance): TypeInfo = TypeInfo.ByTypeReference(typeReference, variance)
fun TypeInfo(theType: JetType, variance: Variance): TypeInfo = TypeInfo.ByType(theType, variance)
/**
@@ -75,7 +82,8 @@ abstract class CallableInfo (
val name: String,
val receiverTypeInfo: TypeInfo,
val returnTypeInfo: TypeInfo,
val possibleContainers: List<JetElement>
val possibleContainers: List<JetElement>,
val typeParameterInfos: List<TypeInfo>
) {
abstract val kind: CallableKind
abstract val parameterInfos: List<ParameterInfo>
@@ -85,8 +93,9 @@ class FunctionInfo(name: String,
receiverTypeInfo: TypeInfo,
returnTypeInfo: TypeInfo,
possibleContainers: List<JetElement> = Collections.emptyList(),
override val parameterInfos: List<ParameterInfo> = Collections.emptyList()
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers) {
override val parameterInfos: List<ParameterInfo> = Collections.emptyList(),
typeParameterInfos: List<TypeInfo> = Collections.emptyList()
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos) {
override val kind: CallableKind get() = CallableKind.FUNCTION
}
@@ -94,8 +103,9 @@ class PropertyInfo(name: String,
receiverTypeInfo: TypeInfo,
returnTypeInfo: TypeInfo,
val writable: Boolean,
possibleContainers: List<JetElement> = Collections.emptyList()
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers) {
possibleContainers: List<JetElement> = Collections.emptyList(),
typeParameterInfos: List<TypeInfo> = Collections.emptyList()
) : CallableInfo(name, receiverTypeInfo, returnTypeInfo, possibleContainers, typeParameterInfos) {
override val kind: CallableKind get() = CallableKind.PROPERTY
override val parameterInfos: List<ParameterInfo> get() = Collections.emptyList()
}
@@ -17,6 +17,8 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder
import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
import java.util.Collections
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
/**
* Special <code>Expression</code> for parameter names based on its type.
@@ -97,8 +99,10 @@ private class TypeExpression(public val typeCandidates: List<TypeCandidate>) : E
/**
* A sort-of dummy <code>Expression</code> for parameter lists, to allow us to update the parameter list as the user makes selections.
*/
private class TypeParameterListExpression(private val typeParameterNamesFromReceiverType: Array<String>,
private val parameterTypeToTypeParameterNamesMap: Map<String, Array<String>>) : Expression() {
private class TypeParameterListExpression(private val typeParameterNamesFromReceiverType: List<RenderedTypeParameter>,
private val parameterTypeToTypeParameterNamesMap: Map<String, List<RenderedTypeParameter>>) : Expression() {
public var currentTypeParameters: List<TypeParameterDescriptor> = Collections.emptyList()
private set
override fun calculateResult(context: ExpressionContext?): Result {
context!!
@@ -112,14 +116,14 @@ private class TypeParameterListExpression(private val typeParameterNamesFromRece
val callable = PsiTreeUtil.getParentOfType(elementAt, javaClass<JetCallableDeclaration>()) ?: return TextResult("")
val parameters = callable.getValueParameterList()?.getParameters() ?: Collections.emptyList<JetParameter>()
val typeParameterNames = LinkedHashSet<String>()
typeParameterNames.addAll(typeParameterNamesFromReceiverType)
val renderedTypeParameters = LinkedHashSet<RenderedTypeParameter>()
renderedTypeParameters.addAll(typeParameterNamesFromReceiverType)
for (parameter in parameters) {
val parameterTypeRef = parameter.getTypeReference()
if (parameterTypeRef != null) {
val typeParameterNamesFromParameter = parameterTypeToTypeParameterNamesMap[parameterTypeRef.getText()]
if (typeParameterNamesFromParameter != null) {
typeParameterNames.addAll(typeParameterNamesFromParameter)
renderedTypeParameters.addAll(typeParameterNamesFromParameter)
}
}
}
@@ -127,11 +131,17 @@ private class TypeParameterListExpression(private val typeParameterNamesFromRece
if (returnTypeRef != null) {
val typeParameterNamesFromReturnType = parameterTypeToTypeParameterNamesMap[returnTypeRef.getText()]
if (typeParameterNamesFromReturnType != null) {
typeParameterNames.addAll(typeParameterNamesFromReturnType)
renderedTypeParameters.addAll(typeParameterNamesFromReturnType)
}
}
return TextResult(if (typeParameterNames.empty) "" else typeParameterNames.joinToString(", ", " <", ">"))
val sortedRenderedTypeParameters = renderedTypeParameters.sortBy { if (it.fake) it.typeParameter.getIndex() else -1}
currentTypeParameters = sortedRenderedTypeParameters.map { it.typeParameter }
return TextResult(
if (sortedRenderedTypeParameters.empty) "" else sortedRenderedTypeParameters.map { it.text }.joinToString(", ", " <", ">")
)
}
override fun calculateQuickResult(context: ExpressionContext?): Result = calculateResult(context)
@@ -59,7 +59,7 @@ public class CreateCallableFromUsageFix(
// TODO: Support generation of Java class members
val containers = receiverTypeCandidates
.map { candidate ->
val descriptor = DescriptorUtils.getClassDescriptorForType(candidate.theType)
val descriptor = candidate.theType.getConstructor().getDeclarationDescriptor()
(DescriptorToDeclarationUtil.getDeclaration(file, descriptor) as? JetClassOrObject)?.let { candidate to it }
}
.filterNotNull()
@@ -84,8 +84,9 @@ object CreateFunctionOrPropertyFromCallActionFactory : JetSingleIntentionActionF
it.getArgumentName()?.getReferenceExpression()?.getReferencedName()
)
}
val typeParameters = callExpr.getTypeArguments().map { TypeInfo(it.getTypeReference(), Variance.INVARIANT) }
val returnType = TypeInfo(fullCallExpr, Variance.OUT_VARIANCE)
FunctionInfo(calleeExpr.getReferencedName(), receiverType, returnType, possibleContainers, parameters)
FunctionInfo(calleeExpr.getReferencedName(), receiverType, returnType, possibleContainers, parameters, typeParameters)
}
is JetSimpleNameExpression -> {
@@ -0,0 +1,14 @@
// "Create function 'foo' from usage" "true"
class B<T>(val t: T) {
fun <T1, T2> foo(arg: T1, arg1: T2): T1 {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
class A<T>(val b: B<T>) {
fun test(): Int {
return b.foo<Int, String>(2, "2")
}
}
@@ -0,0 +1,14 @@
// "Create function 'foo' from usage" "true"
class B<T>(val t: T) {
fun <T1> foo(i: Int, arg: T1): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
class A<T>(val b: B<T>) {
fun test(): Int {
return b.foo<String>(2, "2")
}
}
@@ -0,0 +1,14 @@
// "Create function 'foo' from usage" "true"
class B<T>(val t: T) {
fun <T1, T2> foo(arg: T1, arg1: T2): T1 {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
class A<T>(val b: B<T>) {
fun test(): Int {
return b.foo<Int, String>(2, "2")
}
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val items: List<T>) {
fun test(): Int {
return items.foo<T, Int, String>(2, "2")
}
}
fun <E, T, T1> List<E>.foo(arg: T, arg1: T1): T {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val items: List<T>) {
fun test(): Int {
return items.foo<T, Int>(2, "2")
}
}
fun <E, T> List<E>.foo(arg: T, s: String): T {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class A<T>(val items: List<T>) {
fun test(): Int {
return items.foo<T, Int, String>(2, "2")
}
}
fun <E, T, T1> List<E>.foo(arg: T, arg1: T1): T {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return foo<String, Int>(2, "2")
}
fun <T, T1> foo(arg: T1, arg1: T): T1 {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return foo<String, Int>(2, "2")
}
fun <T, T1> foo(arg: T1, arg1: T): T1 {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return foo<String, Int>(2, "2")
}
fun <T, T1> foo(arg: T1, arg1: T): T1 {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,9 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return foo<Int>(2, "2")
}
fun <T> foo(arg: T, s: String): T {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class B<T>(val t: T) {
}
class A<T>(val b: B<T>) {
fun test(): Int {
return b.<caret>foo<Int, String>(2, "2")
}
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class B<T>(val t: T) {
}
class A<T>(val b: B<T>) {
fun test(): Int {
return b.<caret>foo<String>(2, "2")
}
}
@@ -0,0 +1,11 @@
// "Create function 'foo' from usage" "true"
class B<T>(val t: T) {
}
class A<T>(val b: B<T>) {
fun test(): Int {
return b.<caret>foo<T, Int, String>(2, "2")
}
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val items: List<T>) {
fun test(): Int {
return items.<caret>foo<Int, String>(2, "2")
}
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val items: List<T>) {
fun test(): Int {
return items.<caret>foo<Int>(2, "2")
}
}
@@ -0,0 +1,7 @@
// "Create function 'foo' from usage" "true"
class A<T>(val items: List<T>) {
fun test(): Int {
return items.<caret>foo<T, Int, String>(2, "2")
}
}
@@ -0,0 +1,5 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return <caret>foo<String, Int>(2, "2")
}
@@ -0,0 +1,5 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return <caret>foo<String, Int, Boolean>(2, "2")
}
@@ -0,0 +1,5 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return <caret>foo<kotlin.String, Int>(2, "2")
}
@@ -0,0 +1,5 @@
// "Create function 'foo' from usage" "true"
fun test(): Int {
return <caret>foo<Int>(2, "2")
}
@@ -239,6 +239,7 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
@TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/call")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({})
@RunWith(JUnit3RunnerWithInners.class)
public static class Call extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInCall() throws Exception {
@@ -250,6 +251,7 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.Main.kt");
doTestWithExtraFile(fileName);
}
}
}
@@ -730,6 +730,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
@TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/call")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({Call.TypeArguments.class})
@RunWith(JUnit3RunnerWithInners.class)
public static class Call extends AbstractQuickFixTest {
public void testAllFilesPresentInCall() throws Exception {
@@ -933,6 +934,75 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeUnresolvedSupertype.kt");
doTest(fileName);
}
@TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeArguments extends AbstractQuickFixTest {
public void testAllFilesPresentInTypeArguments() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeClassMember.kt")
public void testClassMember() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeClassMember.kt");
doTest(fileName);
}
@TestMetadata("beforeClassMemberPartialSubstitution.kt")
public void testClassMemberPartialSubstitution() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeClassMemberPartialSubstitution.kt");
doTest(fileName);
}
@TestMetadata("beforeClassMemberWithReceiverArg.kt")
public void testClassMemberWithReceiverArg() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeClassMemberWithReceiverArg.kt");
doTest(fileName);
}
@TestMetadata("beforeExtension.kt")
public void testExtension() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeExtension.kt");
doTest(fileName);
}
@TestMetadata("beforeExtensionPartialSubstitution.kt")
public void testExtensionPartialSubstitution() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeExtensionPartialSubstitution.kt");
doTest(fileName);
}
@TestMetadata("beforeExtensionWithReceiverArg.kt")
public void testExtensionWithReceiverArg() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeExtensionWithReceiverArg.kt");
doTest(fileName);
}
@TestMetadata("beforeNoReceiver.kt")
public void testNoReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeNoReceiver.kt");
doTest(fileName);
}
@TestMetadata("beforeNoReceiverExtraArgs.kt")
public void testNoReceiverExtraArgs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeNoReceiverExtraArgs.kt");
doTest(fileName);
}
@TestMetadata("beforeNoReceiverLongName.kt")
public void testNoReceiverLongName() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeNoReceiverLongName.kt");
doTest(fileName);
}
@TestMetadata("beforeNoReceiverPartialSubstitution.kt")
public void testNoReceiverPartialSubstitution() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/typeArguments/beforeNoReceiverPartialSubstitution.kt");
doTest(fileName);
}
}
}
@TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/component")