diff --git a/ChangeLog.md b/ChangeLog.md index 9e809f8e21e..9e90f9d37c0 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -101,6 +101,12 @@ These artifacts include extensions for the types available in the latter JDKs, s - [`KT-8672`](https://youtrack.jetbrains.com/issue/KT-8672) Rename: Optimize search of parameter references in calls with named arguments - [`KT-9285`](https://youtrack.jetbrains.com/issue/KT-9285) Rename: Optimize search of private class members +#### Intention actions, inspections and quickfixes + +##### New features + +- [`KT-11525`](https://youtrack.jetbrains.com/issue/KT-11525) Implement "Create type parameter" quickfix + #### Refactorings - [`KT-13535`](https://youtrack.jetbrains.com/issue/KT-13535) Pull Up: Remove visibility modifiers on adding 'override' diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/EditCommaSeparatedListHelper.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/EditCommaSeparatedListHelper.kt index 801f1480dad..ffedf6e3813 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/EditCommaSeparatedListHelper.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/EditCommaSeparatedListHelper.kt @@ -18,18 +18,21 @@ package org.jetbrains.kotlin.psi import com.intellij.psi.PsiComment import com.intellij.psi.PsiWhiteSpace +import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.psiUtil.siblings object EditCommaSeparatedListHelper { - fun addItem(list: KtElement, allItems: List, item: TItem): TItem { - return addItemBefore(list, allItems, item, null) + @JvmOverloads + fun addItem(list: KtElement, allItems: List, item: TItem, prefix: KtToken = KtTokens.LPAR): TItem { + return addItemBefore(list, allItems, item, null, prefix) } - fun addItemAfter(list: KtElement, allItems: List, item: TItem, anchor: TItem?): TItem { + @JvmOverloads + fun addItemAfter(list: KtElement, allItems: List, item: TItem, anchor: TItem?, prefix: KtToken = KtTokens.LPAR): TItem { assert(anchor == null || anchor.parent == list) if (allItems.isEmpty()) { - if (list.firstChild.node.elementType == KtTokens.LPAR) { + if (list.firstChild.node.elementType == prefix) { return list.addAfter(item, list.firstChild) as TItem } else { @@ -49,7 +52,8 @@ object EditCommaSeparatedListHelper { } } - fun addItemBefore(list: KtElement, allItems: List, item: TItem, anchor: TItem?): TItem { + @JvmOverloads + fun addItemBefore(list: KtElement, allItems: List, item: TItem, anchor: TItem?, prefix: KtToken = KtTokens.LPAR): TItem { val anchorAfter: TItem? if (allItems.isEmpty()) { assert(anchor == null) @@ -65,7 +69,7 @@ object EditCommaSeparatedListHelper { anchorAfter = allItems.get(allItems.size - 1) } } - return addItemAfter(list, allItems, item, anchorAfter) + return addItemAfter(list, allItems, item, anchorAfter, prefix) } fun removeItem(item: TItem) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt index 0a0ef9bd558..72e823c38ef 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt @@ -90,6 +90,8 @@ class KtPsiFactory(private val project: Project) { return (property.getInitializer() as KtCallExpression).typeArgumentList!! } + fun createTypeArgument(text: String) = createTypeArguments("<$text>").arguments.first() + fun createType(type: String): KtTypeReference { val typeReference = createTypeIfPossible(type) if (typeReference == null || typeReference.text != type) { @@ -316,6 +318,10 @@ class KtPsiFactory(private val project: Project) { return createFunction("fun foo$text{}").getValueParameterList()!! } + fun createTypeParameterList(text: String) = createClass("class Foo$text").typeParameterList!! + + fun createTypeParameter(text: String) = createTypeParameterList("<$text>").parameters.first()!! + fun createFunctionLiteralParameterList(text: String): KtParameterList { return (createExpression("{ $text -> 0}") as KtLambdaExpression).functionLiteral.valueParameterList!! } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtTypeArgumentList.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtTypeArgumentList.java index 5bc710f17db..aea76eaa423 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtTypeArgumentList.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtTypeArgumentList.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub; import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes; @@ -43,7 +44,7 @@ public class KtTypeArgumentList extends KtElementImplStub R accept(@NotNull KtVisitor visitor, D data) { return visitor.visitTypeParameterList(this, data); diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt index 158fc3b5dc0..eab8fbd69a5 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt @@ -271,4 +271,18 @@ fun dropEnclosingParenthesesIfPossible(expression: KtExpression): KtExpression { val parent = expression.parent as? KtParenthesizedExpression ?: return expression if (!KtPsiUtil.areParenthesesUseless(parent)) return expression return parent.replaced(expression) +} + +fun KtTypeParameterListOwner.addTypeParameter(typeParameter: KtTypeParameter): KtTypeParameter? { + typeParameterList?.let { return it.addParameter(typeParameter) } + + val list = KtPsiFactory(this).createTypeParameterList("") + list.parameters[0].replace(typeParameter) + val leftAnchor = when (this) { + is KtClass -> nameIdentifier ?: getClassOrInterfaceKeyword() + is KtNamedFunction -> funKeyword + is KtProperty -> valOrVarKeyword + else -> null + } ?: return null + return (addAfter(list, leftAnchor) as KtTypeParameterList).parameters.first() } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArgumentsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArgumentsIntention.kt index 62ff941e8e3..cbb893906da 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArgumentsIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArgumentsIntention.kt @@ -22,11 +22,13 @@ import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.core.ShortenReferences +import org.jetbrains.kotlin.psi.KtCallElement import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtTypeArgumentList import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.ErrorUtils class InsertExplicitTypeArgumentsIntention : SelfTargetingRangeIntention(KtCallExpression::class.java, "Add explicit type arguments"), LowPriorityAction { @@ -34,17 +36,10 @@ class InsertExplicitTypeArgumentsIntention : SelfTargetingRangeIntention, + val upperBound: KotlinType +) { + fun performSubstitution(vararg substitution: Pair): TypeConstraintInfo? { + val currentSubstitution = LinkedHashMap().apply { + this.putAll(originalSubstitution) + this.putAll(substitution) + } + val substitutedUpperBound = TypeSubstitutor.create(currentSubstitution).substitute(upperBound, Variance.INVARIANT) ?: return null + return TypeConstraintInfo(typeParameter, substitutedUpperBound) + } +} + +data class TypeConstraintInfo( + val typeParameter: TypeParameterDescriptor, + val upperBound: KotlinType +) + +fun getUnsubstitutedTypeConstraintInfo(element: KtTypeElement): UnsubstitutedTypeConstraintInfo? { + val context = element.analyze(BodyResolveMode.PARTIAL) + val containingTypeArg = (element.parent as? KtTypeReference)?.parent as? KtTypeProjection ?: return null + val argumentList = containingTypeArg.parent as? KtTypeArgumentList ?: return null + val containingTypeRef = (argumentList.parent as? KtTypeElement)?.parent as? KtTypeReference ?: return null + val containingType = containingTypeRef.getAbbreviatedTypeOrType(context) ?: return null + val baseType = containingType.constructor.declarationDescriptor?.defaultType ?: return null + val typeParameter = containingType.constructor.parameters.getOrNull(argumentList.arguments.indexOf(containingTypeArg)) + val upperBound = typeParameter?.upperBounds?.singleOrNull() ?: return null + val substitution = getTypeSubstitution(baseType, containingType) ?: return null + return UnsubstitutedTypeConstraintInfo(typeParameter, substitution, upperBound) +} + +fun getTypeConstraintInfo(element: KtTypeElement) = getUnsubstitutedTypeConstraintInfo(element)?.performSubstitution() diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeAlias/CreateTypeAliasFromTypeReferenceActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeAlias/CreateTypeAliasFromTypeReferenceActionFactory.kt index 77a469f2034..8c5e4dd8d5a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeAlias/CreateTypeAliasFromTypeReferenceActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeAlias/CreateTypeAliasFromTypeReferenceActionFactory.kt @@ -16,45 +16,21 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeAlias -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.CollectingNameValidator import org.jetbrains.kotlin.idea.core.KotlinNameSuggester import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator import org.jetbrains.kotlin.idea.quickfix.IntentionActionPriority import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactoryWithDelegate import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClassFromTypeReferenceActionFactory -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.getTypeConstraintInfo +import org.jetbrains.kotlin.psi.KtUserType import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.resolve.bindingContextUtil.getAbbreviatedTypeOrType -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeSubstitutor -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.substitutions.getTypeSubstitution import org.jetbrains.kotlin.types.typeUtil.containsError object CreateTypeAliasFromTypeReferenceActionFactory : KotlinSingleIntentionActionFactoryWithDelegate(IntentionActionPriority.LOW) { override fun getElementOfInterest(diagnostic: Diagnostic) = CreateClassFromTypeReferenceActionFactory.getElementOfInterest(diagnostic) - data class TypeConstraintInfo(val typeParameter: TypeParameterDescriptor, val upperBound: KotlinType) - - private fun getTypeConstraintInfo(element: KtUserType): TypeConstraintInfo? { - val context = element.analyze(BodyResolveMode.PARTIAL) - val containingTypeArg = (element.parent as? KtTypeReference)?.parent as? KtTypeProjection ?: return null - val argumentList = containingTypeArg.parent as? KtTypeArgumentList ?: return null - val containingTypeRef = (argumentList.parent as? KtTypeElement)?.parent as? KtTypeReference ?: return null - val containingType = containingTypeRef.getAbbreviatedTypeOrType(context) ?: return null - val baseType = containingType.constructor.declarationDescriptor?.defaultType ?: return null - val typeParameter = containingType.constructor.parameters.getOrNull(argumentList.arguments.indexOf(containingTypeArg)) - val upperBound = typeParameter?.upperBounds?.singleOrNull() ?: return null - val substitution = getTypeSubstitution(baseType, containingType) ?: return null - val substitutedUpperBound = TypeSubstitutor.create(substitution).substitute(upperBound, Variance.INVARIANT) ?: return null - if (substitutedUpperBound.containsError()) return null - return TypeConstraintInfo(typeParameter, substitutedUpperBound) - } - override fun extractFixData(element: KtUserType, diagnostic: Diagnostic): TypeAliasInfo? { if (element.getParentOfTypeAndBranch(true) { qualifier } != null) return null diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByRefActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByRefActionFactory.kt new file mode 100644 index 00000000000..1b586662338 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByRefActionFactory.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter + +import com.intellij.psi.PsiElement +import com.intellij.psi.SmartPsiElementPointer +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionFactoryWithDelegate +import org.jetbrains.kotlin.idea.quickfix.QuickFixWithDelegateFactory +import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.getUnsubstitutedTypeConstraintInfo +import org.jetbrains.kotlin.idea.refactoring.introduce.isObjectOrNonInnerClass +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch +import org.jetbrains.kotlin.psi.psiUtil.parents +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjectionImpl +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.containsError + +data class CreateTypeParameterData( + val name: String, + val declaration: KtTypeParameterListOwner, + val upperBoundType: KotlinType?, + val fakeTypeParameter: TypeParameterDescriptor +) + +object CreateTypeParameterByRefActionFactory : KotlinIntentionActionFactoryWithDelegate() { + override fun getElementOfInterest(diagnostic: Diagnostic): KtUserType? { + val ktUserType = diagnostic.psiElement.getParentOfTypeAndBranch { referenceExpression } ?: return null + if (ktUserType.qualifier != null) return null + if (ktUserType.getParentOfTypeAndBranch(true) { qualifier } != null) return null + if (ktUserType.typeArgumentList != null) return null + return ktUserType + } + + override fun extractFixData(element: KtUserType, diagnostic: Diagnostic): CreateTypeParameterData? { + val name = element.referencedName ?: return null + val declaration = element.parents.firstOrNull { + it is KtProperty || it is KtNamedFunction || it is KtClass + } as? KtTypeParameterListOwner ?: return null + val containingDescriptor = declaration.resolveToDescriptor() + val fakeTypeParameter = createFakeTypeParameterDescriptor(containingDescriptor, name) + val upperBoundType = getUnsubstitutedTypeConstraintInfo(element)?.let { + it.performSubstitution(it.typeParameter.typeConstructor to TypeProjectionImpl(fakeTypeParameter.defaultType))?.upperBound + } + if (upperBoundType != null && upperBoundType.containsError()) return null + return CreateTypeParameterData(name, declaration, upperBoundType, fakeTypeParameter) + } + + override fun createFixes( + originalElementPointer: SmartPsiElementPointer, + diagnostic: Diagnostic, + quickFixDataFactory: () -> CreateTypeParameterData? + ): List { + val ktUserType = originalElementPointer.element ?: return emptyList() + val name = ktUserType.referencedName ?: return emptyList() + return getPossibleTypeParameterContainers(ktUserType) + .filter { it.typeParameters.all { it.name != name } } + .map { + QuickFixWithDelegateFactory factory@ { + val originalElement = originalElementPointer.element ?: return@factory null + val data = quickFixDataFactory()?.copy(declaration = it) ?: return@factory null + CreateTypeParameterFromUsageFix(originalElement, data) + } + } + } +} + +fun createFakeTypeParameterDescriptor(containingDescriptor: DeclarationDescriptor, name: String): TypeParameterDescriptor { + return TypeParameterDescriptorImpl + .createWithDefaultBound(containingDescriptor, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier(name), -1) +} + +fun getPossibleTypeParameterContainers(startFrom: PsiElement): List { + val stopAt = startFrom.parents.firstOrNull(::isObjectOrNonInnerClass)?.parent + return (if (stopAt != null) startFrom.parents.takeWhile { it != stopAt } else startFrom.parents) + .filterIsInstance() + .filter { + ((it is KtClass && !it.isInterface() && it !is KtEnumEntry) || + it is KtNamedFunction || + (it is KtProperty && !it.isLocal) || + it is KtTypeAlias) && it.nameIdentifier != null + } + .toList() +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterFromUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterFromUsageFix.kt new file mode 100644 index 00000000000..cd6fc5e70b2 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterFromUsageFix.kt @@ -0,0 +1,137 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter + +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.ElementDescriptionUtil +import com.intellij.psi.search.searches.ReferencesSearch +import com.intellij.usageView.UsageViewTypeLocation +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.core.ShortenReferences +import org.jetbrains.kotlin.idea.core.addTypeParameter +import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArgumentsIntention +import org.jetbrains.kotlin.idea.quickfix.createFromUsage.CreateFromUsageFixBase +import org.jetbrains.kotlin.idea.refactoring.runSynchronouslyWithProgress +import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.idea.util.application.runWriteAction +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.types.TypeProjectionImpl +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.isNullableAny +import org.jetbrains.kotlin.utils.SmartList + +class CreateTypeParameterFromUsageFix( + originalElement: KtUserType, + private val data: CreateTypeParameterData +) : CreateFromUsageFixBase(originalElement) { + override fun getText() = "Create type parameter '${data.name}' in " + + ElementDescriptionUtil.getElementDescription(data.declaration, UsageViewTypeLocation.INSTANCE) + " '${data.declaration.name}'" + + override fun startInWriteAction() = false + + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + val declaration = data.declaration + val usages = project.runSynchronouslyWithProgress("Searching ${declaration.name}...", true) { + runReadAction { + ReferencesSearch + .search(declaration) + .mapNotNull { + it.element.getParentOfTypeAndBranch { referenceExpression } ?: + it.element.getParentOfTypeAndBranch { calleeExpression } + } + .toSet() + } + } ?: return + + runWriteAction { + val psiFactory = KtPsiFactory(project) + + val elementsToShorten = SmartList() + + val upperBoundType = data.upperBoundType + val upperBoundText = if (upperBoundType != null && !upperBoundType.isNullableAny()) { + IdeDescriptorRenderers.SOURCE_CODE.renderType(upperBoundType) + } + else null + val upperBound = upperBoundText?.let { psiFactory.createType(it) } + val newTypeParameterText = if (upperBound != null) "${data.name} : ${upperBound.text}" else data.name + elementsToShorten += declaration.addTypeParameter(psiFactory.createTypeParameter(newTypeParameterText))!! + + val anonymizedTypeParameter = createFakeTypeParameterDescriptor(data.fakeTypeParameter.containingDeclaration, "_") + val anonymizedUpperBoundText = upperBoundType?.let { + TypeSubstitutor + .create(mapOf(data.fakeTypeParameter.typeConstructor to TypeProjectionImpl(anonymizedTypeParameter.defaultType))) + .substitute(upperBoundType, Variance.INVARIANT) + }?.let { + IdeDescriptorRenderers.SOURCE_CODE.renderType(it) + } + + val anonymizedUpperBoundAsTypeArg = psiFactory.createTypeArgument(anonymizedUpperBoundText ?: "kotlin.Any?") + + val callsToExplicateArguments = SmartList() + usages.forEach { + when (it) { + is KtUserType -> { + val typeArgumentList = it.typeArgumentList + elementsToShorten += if (typeArgumentList != null) { + typeArgumentList.addArgument(anonymizedUpperBoundAsTypeArg) + } + else { + it.addAfter( + psiFactory.createTypeArguments("<${anonymizedUpperBoundAsTypeArg.text}>"), + it.referenceExpression!! + ) as KtTypeArgumentList + } + } + is KtCallElement -> { + if (it.analyze(BodyResolveMode.PARTIAL).diagnostics.forElement(it.calleeExpression!!).any { + it.factory in Errors.TYPE_INFERENCE_ERRORS + }) { + callsToExplicateArguments += it + } + } + } + } + + callsToExplicateArguments.forEach { + val typeArgumentList = it.typeArgumentList + if (typeArgumentList == null) { + InsertExplicitTypeArgumentsIntention.applyTo(it, shortenReferences = false) + + val newTypeArgument = it.typeArguments.lastOrNull() + if (anonymizedUpperBoundText != null && newTypeArgument != null && newTypeArgument.text == "kotlin.Any") { + newTypeArgument.replaced(anonymizedUpperBoundAsTypeArg) + } + + elementsToShorten += it.typeArgumentList + } + else { + elementsToShorten += typeArgumentList.addArgument(anonymizedUpperBoundAsTypeArg) + } + } + + ShortenReferences.DEFAULT.process(elementsToShorten) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt index 5103f6cbd64..572a7651d9d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt @@ -216,3 +216,5 @@ fun KtExpression.mustBeParenthesizedInInitializerPosition(): Boolean { if (left?.mustBeParenthesizedInInitializerPosition() ?: false) return true return PsiChildRange(left, operationReference).any { (it is PsiWhiteSpace) && it.textContains('\n') } } + +fun isObjectOrNonInnerClass(e: PsiElement): Boolean = e is KtObjectDeclaration || (e is KtClass && !e.isInner()) \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/delegationSpecifier/classDelegatorToSuperclass.kt b/idea/testData/quickfix/createFromUsage/createClass/delegationSpecifier/classDelegatorToSuperclass.kt index 8bc4a817b21..9d76c6bd421 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/delegationSpecifier/classDelegatorToSuperclass.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/delegationSpecifier/classDelegatorToSuperclass.kt @@ -1,6 +1,7 @@ // "Create class 'A'" "false" // ACTION: Create interface 'A' // ACTION: Create type alias 'A' +// ACTION: Create type parameter 'A' in class 'Foo' // ACTION: Create test // ERROR: Unresolved reference: A package p diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/enumEntryNotQualifierNoTypeArgs.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/enumEntryNotQualifierNoTypeArgs.kt index 3c3fb702438..bc3e75fbac5 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/enumEntryNotQualifierNoTypeArgs.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/enumEntryNotQualifierNoTypeArgs.kt @@ -6,6 +6,7 @@ // ACTION: Create type alias 'A' // ACTION: Convert to block body // ACTION: Remove explicit type specification +// ACTION: Create type parameter 'A' in function 'foo' // ERROR: Unresolved reference: A package p diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeBound.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeBound.kt index 6c767b03d98..1477d268b2f 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeBound.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeBound.kt @@ -2,6 +2,7 @@ // ACTION: Create class 'NotExistent' // ACTION: Create interface 'NotExistent' // ACTION: Create type alias 'NotExistent' +// ACTION: Create type parameter 'NotExistent' in class 'TPB' // ACTION: Create test // ERROR: Unresolved reference: NotExistent class TPBNotExistent> \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeConstraint.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeConstraint.kt index d95564d8977..80d95154862 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeConstraint.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noAnnotationForTypeConstraint.kt @@ -2,6 +2,7 @@ // ACTION: Create class 'NotExistent' // ACTION: Create interface 'NotExistent' // ACTION: Create type alias 'NotExistent' +// ACTION: Create type parameter 'NotExistent' in class 'TPB' // ACTION: Create test // ERROR: Unresolved reference: NotExistent class TPB where X : NotExistent \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeBound.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeBound.kt index c2f3d573609..30eea9137d7 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeBound.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeBound.kt @@ -2,6 +2,7 @@ // ACTION: Create class 'NotExistent' // ACTION: Create interface 'NotExistent' // ACTION: Create type alias 'NotExistent' +// ACTION: Create type parameter 'NotExistent' in class 'TPB' // ACTION: Create test // ERROR: Unresolved reference: NotExistent class TPBNotExistent> \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeConstraint.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeConstraint.kt index d3c432aa129..e074568c2d1 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeConstraint.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noEnumForTypeConstraint.kt @@ -2,6 +2,7 @@ // ACTION: Create class 'NotExistent' // ACTION: Create interface 'NotExistent' // ACTION: Create type alias 'NotExistent' +// ACTION: Create type parameter 'NotExistent' in class 'TPB' // ACTION: Create test // ERROR: Unresolved reference: NotExistent class TPB where X : NotExistent \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeBound.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeBound.kt index 2a062a593a0..4d60bcddd64 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeBound.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeBound.kt @@ -2,6 +2,7 @@ // ACTION: Create class 'NotExistent' // ACTION: Create interface 'NotExistent' // ACTION: Create type alias 'NotExistent' +// ACTION: Create type parameter 'NotExistent' in class 'TPB' // ACTION: Create test // ERROR: Unresolved reference: NotExistent class TPBNotExistent> \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeConstraint.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeConstraint.kt index 879c503781e..ae4d4983281 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeConstraint.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/noObjectForTypeConstraint.kt @@ -2,6 +2,7 @@ // ACTION: Create class 'NotExistent' // ACTION: Create interface 'NotExistent' // ACTION: Create type alias 'NotExistent' +// ACTION: Create type parameter 'NotExistent' in class 'TPB' // ACTION: Create test // ERROR: Unresolved reference: NotExistent class TPB where X : NotExistent \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/typeReference/objectNotQualifierNoTypeArgs.kt b/idea/testData/quickfix/createFromUsage/createClass/typeReference/objectNotQualifierNoTypeArgs.kt index 86739118091..3a6aac643e0 100644 --- a/idea/testData/quickfix/createFromUsage/createClass/typeReference/objectNotQualifierNoTypeArgs.kt +++ b/idea/testData/quickfix/createFromUsage/createClass/typeReference/objectNotQualifierNoTypeArgs.kt @@ -6,6 +6,7 @@ // ACTION: Create type alias 'A' // ACTION: Convert to block body // ACTION: Remove explicit type specification +// ACTION: Create type parameter 'A' in function 'foo' // ERROR: Unresolved reference: A package p diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt new file mode 100644 index 00000000000..2b16d2b6a08 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt @@ -0,0 +1,13 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +open class Foo(x: X) + +class Bar : Foo(1) + +fun test() { + Foo(1) + Foo("2") + + object : Foo("2") { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt.after new file mode 100644 index 00000000000..af7d8745f23 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt.after @@ -0,0 +1,13 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +open class Foo(x: X) + +class Bar : Foo(1) + +fun test() { + Foo(1) + Foo("2") + + object : Foo("2") { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt new file mode 100644 index 00000000000..a6939e35e25 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt @@ -0,0 +1,16 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +// ERROR: Type mismatch: inferred type is A but A was expected +class A + +open class Foo(x: A<X>) + +class Bar : Foo(A()) + +fun test() { + Foo(A()) + Foo(A()) + + object : Foo(A()) { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt.after new file mode 100644 index 00000000000..281cd09c94f --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt.after @@ -0,0 +1,16 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +// ERROR: Type mismatch: inferred type is A but A was expected +class A + +open class Foo(x: A) + +class Bar : Foo(A()) + +fun test() { + Foo(A()) + Foo(A()) + + object : Foo(A()) { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt new file mode 100644 index 00000000000..0d983c5e266 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt @@ -0,0 +1,21 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +// ERROR: Unresolved reference: _ +// ERROR: Unresolved reference: _ +// ERROR: Unresolved reference: _ +// ERROR: Type mismatch: inferred type is A but A> was expected +class A> + +interface I : List + +open class Foo(x: A<X>) + +class Bar : Foo(A()) + +fun test() { + Foo(A()) + Foo(A()) + + object : Foo(A()) { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt.after new file mode 100644 index 00000000000..c9e121e4b07 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt.after @@ -0,0 +1,21 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +// ERROR: Unresolved reference: _ +// ERROR: Unresolved reference: _ +// ERROR: Unresolved reference: _ +// ERROR: Type mismatch: inferred type is A but A> was expected +class A> + +interface I : List + +open class Foo>(x: A) + +class Bar : Foo>(A()) + +fun test() { + Foo>(A()) + Foo(A()) + + object : Foo>(A()) { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt new file mode 100644 index 00000000000..8df10a49e43 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt @@ -0,0 +1,15 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +class A> + +open class Foo(x: A<X>) + +class Bar : Foo(A()) + +fun test() { + Foo(A()) + Foo(A>()) + + object : Foo(A>()) { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt.after new file mode 100644 index 00000000000..96d8a952c84 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt.after @@ -0,0 +1,15 @@ +// "Create type parameter 'X' in class 'Foo'" "true" +class A> + +open class Foo>(x: A) + +class Bar : Foo>(A()) + +fun test() { + Foo>(A()) + Foo(A>()) + + object : Foo>(A>()) { + + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt new file mode 100644 index 00000000000..d9361d793eb --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt @@ -0,0 +1,9 @@ +// "Create type parameter 'X' in function 'foo'" "true" +fun foo(x: X) { + +} + +fun test() { + foo(1) + foo("2") +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt.after new file mode 100644 index 00000000000..c3ade76e4ec --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt.after @@ -0,0 +1,9 @@ +// "Create type parameter 'X' in function 'foo'" "true" +fun foo(x: X) { + +} + +fun test() { + foo(1) + foo("2") +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt new file mode 100644 index 00000000000..1eced0fe34f --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt @@ -0,0 +1,11 @@ +// "Create type parameter 'X' in function 'foo'" "true" +class A + +fun foo(x: A<X>) { + +} + +fun test() { + foo(A()) + foo(A()) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt.after new file mode 100644 index 00000000000..d749a141c47 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt.after @@ -0,0 +1,11 @@ +// "Create type parameter 'X' in function 'foo'" "true" +class A + +fun foo(x: A) { + +} + +fun test() { + foo(A()) + foo(A()) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt new file mode 100644 index 00000000000..2406bb720cf --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt @@ -0,0 +1,14 @@ +// "Create type parameter 'X' in function 'foo'" "true" +// ERROR: Unresolved reference: _ +class A> + +interface I : List + +fun foo(x: A<X>) { + +} + +fun test() { + foo(A()) + foo(A()) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt.after new file mode 100644 index 00000000000..46e9ec7522d --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt.after @@ -0,0 +1,14 @@ +// "Create type parameter 'X' in function 'foo'" "true" +// ERROR: Unresolved reference: _ +class A> + +interface I : List + +fun > foo(x: A) { + +} + +fun test() { + foo>(A()) + foo(A()) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt new file mode 100644 index 00000000000..fc744eb0c38 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt @@ -0,0 +1,11 @@ +// "Create type parameter 'X' in function 'foo'" "true" +class A> + +fun foo(x: A<X>) { + +} + +fun test() { + foo(A()) + foo(A>()) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt.after new file mode 100644 index 00000000000..e08bf18ffd6 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt.after @@ -0,0 +1,11 @@ +// "Create type parameter 'X' in function 'foo'" "true" +class A> + +fun > foo(x: A) { + +} + +fun test() { + foo>(A()) + foo(A>()) +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/qualifiedType.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/qualifiedType.kt new file mode 100644 index 00000000000..1467f47bd95 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/qualifiedType.kt @@ -0,0 +1,13 @@ +// "Create type parameter 'X'" "false" +// ACTION: Create annotation 'X' +// ACTION: Create class 'X' +// ACTION: Create enum 'X' +// ACTION: Create interface 'X' +// ACTION: Create type alias 'X' +// ERROR: Unresolved reference: X + +class A + +fun foo(x: A.X) { + +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/typeQualifier.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/typeQualifier.kt new file mode 100644 index 00000000000..344487f1265 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/typeQualifier.kt @@ -0,0 +1,12 @@ +// "Create type parameter 'X'" "false" +// ACTION: Create class 'X' +// ACTION: Create enum 'X' +// ACTION: Create interface 'X' +// ACTION: Create object 'X' +// ERROR: Unresolved reference: X + +class A + +fun foo(x: X.Y) { + +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/withTypeArguments.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/withTypeArguments.kt new file mode 100644 index 00000000000..431949e3002 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/withTypeArguments.kt @@ -0,0 +1,11 @@ +// "Create type parameter 'X'" "false" +// ACTION: Create class 'X' +// ACTION: Create interface 'X' +// ACTION: Create type alias 'X' +// ERROR: Unresolved reference: X + +class A + +fun foo(x: X) { + +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/dontChangeFunctionReturnTypeToErrorType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/dontChangeFunctionReturnTypeToErrorType.kt index 19feef72ee8..7b7de07d7e7 100644 --- a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/dontChangeFunctionReturnTypeToErrorType.kt +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/dontChangeFunctionReturnTypeToErrorType.kt @@ -5,6 +5,7 @@ // ACTION: Create interface 'NoSuchType' // ACTION: Create type alias 'NoSuchType' // ACTION: Remove explicit lambda parameter types (may break code) +// ACTION: Create type parameter 'NoSuchType' in function 'foo' // ERROR: Type mismatch: inferred type is ([ERROR : NoSuchType]) -> Int but Int was expected // ERROR: Unresolved reference: NoSuchType diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 2cf2418877a..0548ac3bc64 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -3050,6 +3050,81 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CreateTypeParameter extends AbstractQuickFixTest { + public void testAllFilesPresentInCreateTypeParameter() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createTypeParameter"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true); + } + + @TestMetadata("classNoExplication.kt") + public void testClassNoExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt"); + doTest(fileName); + } + + @TestMetadata("classWithExplication.kt") + public void testClassWithExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt"); + doTest(fileName); + } + + @TestMetadata("classWithExplicationAndRecursiveUpperBound.kt") + public void testClassWithExplicationAndRecursiveUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("classWithExplicationAndUpperBound.kt") + public void testClassWithExplicationAndUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("functionNoExplication.kt") + public void testFunctionNoExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt"); + doTest(fileName); + } + + @TestMetadata("functionWithExplication.kt") + public void testFunctionWithExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt"); + doTest(fileName); + } + + @TestMetadata("functionWithExplicationAndRecursiveUpperBound.kt") + public void testFunctionWithExplicationAndRecursiveUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("functionWithExplicationAndUpperBound.kt") + public void testFunctionWithExplicationAndUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("qualifiedType.kt") + public void testQualifiedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/qualifiedType.kt"); + doTest(fileName); + } + + @TestMetadata("typeQualifier.kt") + public void testTypeQualifier() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/typeQualifier.kt"); + doTest(fileName); + } + + @TestMetadata("withTypeArguments.kt") + public void testWithTypeArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/withTypeArguments.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/createFromUsage/createVariable") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)