diff --git a/ChangeLog.md b/ChangeLog.md index dd6fc16b63e..fb8adaa4eef 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -341,6 +341,7 @@ These artifacts include extensions for the types available in the latter JDKs, s ##### New features - [`KT-14729`](https://youtrack.jetbrains.com/issue/KT-14729) Implement "Add names to call arguments" intention +- [`KT-11760`](https://youtrack.jetbrains.com/issue/KT-11760) Create from Usage: Support adding type parameters to the referenced type #### Refactorings diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 85d7daa5c40..f782a800a09 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -29,7 +29,8 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClas import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClassFromReferenceExpressionActionFactory import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.CreateClassFromTypeReferenceActionFactory import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeAlias.CreateTypeAliasFromTypeReferenceActionFactory -import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter.CreateTypeParameterByRefActionFactory +import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter.CreateTypeParameterByUnresolvedRefActionFactory +import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter.CreateTypeParameterUnmatchedTypeArgumentActionFactory import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateLocalVariableActionFactory import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateParameterByNamedArgumentActionFactory import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createVariable.CreateParameterByRefActionFactory @@ -429,7 +430,8 @@ class QuickFixRegistrar : QuickFixContributor { VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.registerFactory(AddTypeAnnotationToValueParameterFix) - UNRESOLVED_REFERENCE.registerFactory(CreateTypeParameterByRefActionFactory) + UNRESOLVED_REFERENCE.registerFactory(CreateTypeParameterByUnresolvedRefActionFactory) + WRONG_NUMBER_OF_TYPE_ARGUMENTS.registerFactory(CreateTypeParameterUnmatchedTypeArgumentActionFactory) FINAL_UPPER_BOUND.registerFactory(InlineTypeParameterFix) FINAL_UPPER_BOUND.registerFactory(RemoveFinalUpperBoundFix) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByRefActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByUnresolvedRefActionFactory.kt similarity index 93% rename from idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByRefActionFactory.kt rename to idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByUnresolvedRefActionFactory.kt index b2e9f2d61b1..aea8f325867 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByRefActionFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterByUnresolvedRefActionFactory.kt @@ -37,14 +37,18 @@ import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.typeUtil.containsError -data class CreateTypeParameterData( +data class TypeParameterInfo( val name: String, - val declaration: KtTypeParameterListOwner, val upperBoundType: KotlinType?, val fakeTypeParameter: TypeParameterDescriptor ) -object CreateTypeParameterByRefActionFactory : KotlinIntentionActionFactoryWithDelegate() { +data class CreateTypeParameterData( + val declaration: KtTypeParameterListOwner, + val typeParameters: List +) + +object CreateTypeParameterByUnresolvedRefActionFactory : KotlinIntentionActionFactoryWithDelegate() { override fun getElementOfInterest(diagnostic: Diagnostic): KtUserType? { val ktUserType = diagnostic.psiElement.getParentOfTypeAndBranch { referenceExpression } ?: return null if (ktUserType.qualifier != null) return null @@ -63,7 +67,7 @@ object CreateTypeParameterByRefActionFactory : KotlinIntentionActionFactoryWithD it.performSubstitution(it.typeParameter.typeConstructor to TypeProjectionImpl(fakeTypeParameter.defaultType))?.upperBound } if (upperBoundType != null && upperBoundType.containsError()) return null - return CreateTypeParameterData(newName, declaration, upperBoundType, fakeTypeParameter) + return CreateTypeParameterData(declaration, listOf(TypeParameterInfo(newName, upperBoundType, fakeTypeParameter))) } override fun extractFixData(element: KtUserType, diagnostic: Diagnostic): CreateTypeParameterData? { @@ -84,7 +88,7 @@ object CreateTypeParameterByRefActionFactory : KotlinIntentionActionFactoryWithD QuickFixWithDelegateFactory factory@ { val originalElement = originalElementPointer.element ?: return@factory null val data = quickFixDataFactory()?.copy(declaration = it) ?: return@factory null - CreateTypeParameterFromUsageFix(originalElement, data) + CreateTypeParameterFromUsageFix(originalElement, data, presentTypeParameterNames = true) } } } 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 index 0f3223417bf..39db3885792 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterFromUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterFromUsageFix.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project +import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.ElementDescriptionUtil import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.usageView.UsageViewTypeLocation @@ -42,11 +43,17 @@ import org.jetbrains.kotlin.types.typeUtil.isNullableAny import org.jetbrains.kotlin.utils.SmartList class CreateTypeParameterFromUsageFix( - originalElement: KtTypeElement, - private val data: CreateTypeParameterData -) : CreateFromUsageFixBase(originalElement) { - override fun getText() = "Create type parameter '${data.name}' in " + - ElementDescriptionUtil.getElementDescription(data.declaration, UsageViewTypeLocation.INSTANCE) + " '${data.declaration.name}'" + originalElement: KtElement, + private val data: CreateTypeParameterData, + private val presentTypeParameterNames: Boolean +) : CreateFromUsageFixBase(originalElement) { + override fun getText(): String { + val prefix = "type parameter".let { if (data.typeParameters.size > 1) StringUtil.pluralize(it) else it } + val typeParametersText = if (presentTypeParameterNames) data.typeParameters.joinToString(prefix = " ") { "'${it.name}'" } else "" + val containerText = ElementDescriptionUtil.getElementDescription(data.declaration, UsageViewTypeLocation.INSTANCE) + + " '${data.declaration.name}'" + return "Create $prefix$typeParametersText in $containerText" + } override fun startInWriteAction() = false @@ -54,92 +61,105 @@ class CreateTypeParameterFromUsageFix( doInvoke() } - fun doInvoke(): KtTypeParameter? { + fun doInvoke(): List { val declaration = data.declaration val project = declaration.project val usages = project.runSynchronouslyWithProgress("Searching ${declaration.name}...", true) { runReadAction { + val expectedTypeArgumentCount = declaration.typeParameters.size + data.typeParameters.size ReferencesSearch .search(declaration) .mapNotNull { it.element.getParentOfTypeAndBranch { referenceExpression } ?: it.element.getParentOfTypeAndBranch { calleeExpression } } + .filter { + val arguments = when (it) { + is KtUserType -> it.typeArguments + is KtCallElement -> it.typeArguments + else -> return@filter false + } + arguments.size != expectedTypeArgumentCount + } .toSet() } - } ?: return null + } ?: return emptyList() 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 - val newTypeParameter = declaration.addTypeParameter(psiFactory.createTypeParameter(newTypeParameterText))!! - elementsToShorten += newTypeParameter + val newTypeParameters = data.typeParameters.map { typeParameter -> + val upperBoundType = typeParameter.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) "${typeParameter.name} : ${upperBound.text}" else typeParameter.name + val newTypeParameter = declaration.addTypeParameter(psiFactory.createTypeParameter(newTypeParameterText))!! + elementsToShorten += newTypeParameter - 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 anonymizedTypeParameter = createFakeTypeParameterDescriptor(typeParameter.fakeTypeParameter.containingDeclaration, "_") + val anonymizedUpperBoundText = upperBoundType?.let { + TypeSubstitutor + .create(mapOf(typeParameter.fakeTypeParameter.typeConstructor to TypeProjectionImpl(anonymizedTypeParameter.defaultType))) + .substitute(upperBoundType, Variance.INVARIANT) + }?.let { + IdeDescriptorRenderers.SOURCE_CODE.renderType(it) + } - val anonymizedUpperBoundAsTypeArg = psiFactory.createTypeArgument(anonymizedUpperBoundText ?: "kotlin.Any?") + 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) + 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 + } } - else { - it.addAfter( - psiFactory.createTypeArguments("<${anonymizedUpperBoundAsTypeArg.text}>"), - it.referenceExpression!! - ) as KtTypeArgumentList - } - } - is KtCallElement -> { - if (it.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS).diagnostics.forElement(it.calleeExpression!!).any { - it.factory in Errors.TYPE_INFERENCE_ERRORS - }) { - callsToExplicateArguments += it + is KtCallElement -> { + if (it.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS).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) + 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) + 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) + } + } - elementsToShorten += it.typeArgumentList - } - else { - elementsToShorten += typeArgumentList.addArgument(anonymizedUpperBoundAsTypeArg) - } + newTypeParameter } ShortenReferences.DEFAULT.process(elementsToShorten) - newTypeParameter + newTypeParameters } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterUnmatchedTypeArgumentActionFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterUnmatchedTypeArgumentActionFactory.kt new file mode 100644 index 00000000000..a6ed39b22da --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createTypeParameter/CreateTypeParameterUnmatchedTypeArgumentActionFactory.kt @@ -0,0 +1,86 @@ +/* + * 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.SmartPsiElementPointer +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde +import org.jetbrains.kotlin.idea.core.CollectingNameValidator +import org.jetbrains.kotlin.idea.core.KotlinNameSuggester +import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionFactoryWithDelegate +import org.jetbrains.kotlin.idea.quickfix.QuickFixWithDelegateFactory +import org.jetbrains.kotlin.idea.util.getResolutionScope +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtCallElement +import org.jetbrains.kotlin.psi.KtTypeArgumentList +import org.jetbrains.kotlin.psi.KtTypeParameterListOwner +import org.jetbrains.kotlin.psi.KtUserType +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier +import org.jetbrains.kotlin.utils.addToStdlib.singletonList + +object CreateTypeParameterUnmatchedTypeArgumentActionFactory : KotlinIntentionActionFactoryWithDelegate() { + override fun getElementOfInterest(diagnostic: Diagnostic) = diagnostic.psiElement as? KtTypeArgumentList + + override fun extractFixData(element: KtTypeArgumentList, diagnostic: Diagnostic): CreateTypeParameterData? { + val project = element.project + val typeArguments = element.arguments + val context = element.analyze() + val parent = element.parent + val referencedDescriptor = when (parent) { + is KtUserType -> context[BindingContext.REFERENCE_TARGET, parent.referenceExpression] + is KtCallElement -> parent.getResolvedCall(context)?.resultingDescriptor + else -> null + } ?: return null + val referencedDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, referencedDescriptor) as? KtTypeParameterListOwner + ?: return null + + val missingParameterCount = typeArguments.size - referencedDeclaration.typeParameters.size + if (missingParameterCount <= 0) return null + + val scope = referencedDeclaration.getResolutionScope() + val suggestedNames = KotlinNameSuggester.suggestNamesForTypeParameters( + missingParameterCount, + CollectingNameValidator(referencedDeclaration.typeParameters.mapNotNull { it.name }) { + scope.findClassifier(Name.identifier(it), NoLookupLocation.FROM_IDE) == null + } + ) + val typeParameterInfos = suggestedNames.map { name -> + TypeParameterInfo( + name, + null, + createFakeTypeParameterDescriptor(referencedDescriptor, name) + ) + } + return CreateTypeParameterData(referencedDeclaration, typeParameterInfos) + } + + override fun createFixes( + originalElementPointer: SmartPsiElementPointer, + diagnostic: Diagnostic, + quickFixDataFactory: () -> CreateTypeParameterData? + ): List { + return QuickFixWithDelegateFactory factory@ { + val originalElement = originalElementPointer.element ?: return@factory null + val data = quickFixDataFactory() ?: return@factory null + CreateTypeParameterFromUsageFix(originalElement, data, false) + }.singletonList() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeParameter/KotlinIntroduceTypeParameterHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeParameter/KotlinIntroduceTypeParameterHandler.kt index 3bab72d025b..f2750b105ea 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeParameter/KotlinIntroduceTypeParameterHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceTypeParameter/KotlinIntroduceTypeParameterHandler.kt @@ -33,7 +33,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils import org.jetbrains.kotlin.idea.core.CollectingNameValidator import org.jetbrains.kotlin.idea.core.KotlinNameSuggester -import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter.CreateTypeParameterByRefActionFactory +import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter.CreateTypeParameterByUnresolvedRefActionFactory import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter.CreateTypeParameterFromUsageFix import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createTypeParameter.getPossibleTypeParameterContainers import org.jetbrains.kotlin.idea.refactoring.introduce.AbstractIntroduceAction @@ -99,12 +99,12 @@ object KotlinIntroduceTypeParameterHandler : RefactoringActionHandler { val originalType = typeElementToExtract.getAbbreviatedTypeOrType(context) val createTypeParameterData = - CreateTypeParameterByRefActionFactory.extractFixData(typeElementToExtract, defaultName) - ?.copy(upperBoundType = originalType, declaration = targetOwner) - ?: return showErrorHint(project, editor, "Refactoring is not applicable in the current context", REFACTORING_NAME) + CreateTypeParameterByUnresolvedRefActionFactory.extractFixData(typeElementToExtract, defaultName)?.let { + it.copy(typeParameters = listOf(it.typeParameters.single().copy(upperBoundType = originalType)), declaration = targetOwner) + } ?: return showErrorHint(project, editor, "Refactoring is not applicable in the current context", REFACTORING_NAME) project.executeCommand(REFACTORING_NAME) { - val newTypeParameter = CreateTypeParameterFromUsageFix(typeElementToExtract, createTypeParameterData).doInvoke() + val newTypeParameter = CreateTypeParameterFromUsageFix(typeElementToExtract, createTypeParameterData, false).doInvoke().singleOrNull() ?: return@executeCommand val newTypeParameterPointer = newTypeParameter.createSmartPointer() diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classNoExplication.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classNoExplication.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classNoExplication.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classNoExplication.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplication.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplication.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplication.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplication.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplication.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndRecursiveUpperBound.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndRecursiveUpperBound.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndRecursiveUpperBound.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndRecursiveUpperBound.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndRecursiveUpperBound.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndUpperBound.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndUpperBound.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndUpperBound.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/classWithExplicationAndUpperBound.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndUpperBound.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionNoExplication.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionNoExplication.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionNoExplication.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionNoExplication.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplication.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplication.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplication.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplication.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndRecursiveUpperBound.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndRecursiveUpperBound.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndRecursiveUpperBound.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndRecursiveUpperBound.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndRecursiveUpperBound.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndUpperBound.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndUpperBound.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndUpperBound.kt.after similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplicationAndUpperBound.kt.after rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndUpperBound.kt.after diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/qualifiedType.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/qualifiedType.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/qualifiedType.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/qualifiedType.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/typeQualifier.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/typeQualifier.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/typeQualifier.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/typeQualifier.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/withTypeArguments.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/withTypeArguments.kt similarity index 100% rename from idea/testData/quickfix/createFromUsage/createTypeParameter/withTypeArguments.kt rename to idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/withTypeArguments.kt diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addMultiple.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addMultiple.kt new file mode 100644 index 00000000000..a7e1fc0870a --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addMultiple.kt @@ -0,0 +1,5 @@ +// "Create type parameters in class 'X'" "true" + +class X + +fun foo(x: X<String, Int, Boolean>) {} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addMultiple.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addMultiple.kt.after new file mode 100644 index 00000000000..cbf4c4536a5 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addMultiple.kt.after @@ -0,0 +1,5 @@ +// "Create type parameters in class 'X'" "true" + +class X + +fun foo(x: X<String, Int, Boolean>) {} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addSingle.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addSingle.kt new file mode 100644 index 00000000000..55e3c570621 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addSingle.kt @@ -0,0 +1,5 @@ +// "Create type parameter in class 'X'" "true" + +class X + +fun foo(x: X<String>) {} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addSingle.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addSingle.kt.after new file mode 100644 index 00000000000..1b9fc831ee6 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addSingle.kt.after @@ -0,0 +1,5 @@ +// "Create type parameter in class 'X'" "true" + +class X + +fun foo(x: X<String>) {} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addToFunction.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addToFunction.kt new file mode 100644 index 00000000000..85fbde9684c --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addToFunction.kt @@ -0,0 +1,9 @@ +// "Create type parameter in function 'bar'" "true" + +fun bar() { + +} + +fun foo() { + bar<String>() +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addToFunction.kt.after b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addToFunction.kt.after new file mode 100644 index 00000000000..de5d82c72f0 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addToFunction.kt.after @@ -0,0 +1,9 @@ +// "Create type parameter in function 'bar'" "true" + +fun bar() { + +} + +fun foo() { + bar<String>() +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/missingArguments.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/missingArguments.kt new file mode 100644 index 00000000000..52a281f88b4 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/missingArguments.kt @@ -0,0 +1,4 @@ +// "Create type parameter in class 'X'" "false" +// ERROR: 2 type arguments expected for class X defined in root package +class X +fun Y(x: X<String>) {} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/notOnTypeArgumentList.kt b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/notOnTypeArgumentList.kt new file mode 100644 index 00000000000..8347e0f0d3f --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/notOnTypeArgumentList.kt @@ -0,0 +1,6 @@ +// "Create type parameter in class 'X'" "false" +// ERROR: No type arguments expected for class X defined in root package + +class X + +fun foo(x: X) {} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index d395435ff44..4e86d3df4e2 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -1308,6 +1308,16 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } + @TestMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CreateTypeParameter extends AbstractQuickFixMultiFileTest { + public void testAllFilesPresentInCreateTypeParameter() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createTypeParameter"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true); + } + + } + @TestMetadata("idea/testData/quickfix/createFromUsage/createVariable") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 19bb7f71097..3b9e48e4fb9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -3174,70 +3174,118 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createTypeParameter"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("classNoExplication.kt") - public void testClassNoExplication() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/classNoExplication.kt"); - doTest(fileName); + @TestMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InContainingDeclaration extends AbstractQuickFixTest { + public void testAllFilesPresentInInContainingDeclaration() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("classNoExplication.kt") + public void testClassNoExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classNoExplication.kt"); + doTest(fileName); + } + + @TestMetadata("classWithExplication.kt") + public void testClassWithExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplication.kt"); + doTest(fileName); + } + + @TestMetadata("classWithExplicationAndRecursiveUpperBound.kt") + public void testClassWithExplicationAndRecursiveUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndRecursiveUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("classWithExplicationAndUpperBound.kt") + public void testClassWithExplicationAndUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/classWithExplicationAndUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("functionNoExplication.kt") + public void testFunctionNoExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionNoExplication.kt"); + doTest(fileName); + } + + @TestMetadata("functionWithExplication.kt") + public void testFunctionWithExplication() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplication.kt"); + doTest(fileName); + } + + @TestMetadata("functionWithExplicationAndRecursiveUpperBound.kt") + public void testFunctionWithExplicationAndRecursiveUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndRecursiveUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("functionWithExplicationAndUpperBound.kt") + public void testFunctionWithExplicationAndUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/functionWithExplicationAndUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("qualifiedType.kt") + public void testQualifiedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/qualifiedType.kt"); + doTest(fileName); + } + + @TestMetadata("typeQualifier.kt") + public void testTypeQualifier() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/typeQualifier.kt"); + doTest(fileName); + } + + @TestMetadata("withTypeArguments.kt") + public void testWithTypeArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inContainingDeclaration/withTypeArguments.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("idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class InReferencedDeclaration extends AbstractQuickFixTest { + @TestMetadata("addMultiple.kt") + public void testAddMultiple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addMultiple.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("addSingle.kt") + public void testAddSingle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addSingle.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("addToFunction.kt") + public void testAddToFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/addToFunction.kt"); + doTest(fileName); + } - @TestMetadata("functionNoExplication.kt") - public void testFunctionNoExplication() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/functionNoExplication.kt"); - doTest(fileName); - } + public void testAllFilesPresentInInReferencedDeclaration() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } - @TestMetadata("functionWithExplication.kt") - public void testFunctionWithExplication() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/functionWithExplication.kt"); - doTest(fileName); - } + @TestMetadata("missingArguments.kt") + public void testMissingArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/missingArguments.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("notOnTypeArgumentList.kt") + public void testNotOnTypeArgumentList() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createTypeParameter/inReferencedDeclaration/notOnTypeArgumentList.kt"); + doTest(fileName); + } } }