From 4e36edb5d6963689fa6514c0da3602723dd3dd6e Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 14 Dec 2015 12:24:28 +0300 Subject: [PATCH] Inline Variable: Remove invalid imports and perform reference lengthening/shortening when inlining non-local declaration #KT-8884 Fixed --- .../kotlin/generators/tests/GenerateTests.kt | 2 +- .../inline/KotlinInlineValHandler.kt | 75 +++++++++++++++---- .../kotlin/idea/refactoring/move/moveUtils.kt | 70 +++++++++-------- .../inline/property/keepImport.1.kt | 7 ++ .../inline/property/keepImport.1.kt.after | 8 ++ .../refactoring/inline/property/keepImport.kt | 5 ++ .../inline/property/keepImport.kt.after | 4 + .../inline/property/multiplePackages.1.kt | 3 + .../property/multiplePackages.1.kt.after | 3 + .../inline/property/multiplePackages.2.kt | 3 + .../property/multiplePackages.2.kt.after | 3 + .../inline/property/multiplePackages.3.kt | 5 ++ .../property/multiplePackages.3.kt.after | 5 ++ .../inline/property/multiplePackages.4.kt | 5 ++ .../property/multiplePackages.4.kt.after | 5 ++ .../inline/property/multiplePackages.5.kt | 5 ++ .../property/multiplePackages.5.kt.after | 6 ++ .../inline/property/multiplePackages.kt | 8 ++ .../inline/property/multiplePackages.kt.after | 6 ++ .../inline/property/removeImport.1.kt | 7 ++ .../inline/property/removeImport.1.kt.after | 7 ++ .../inline/property/removeImport.kt | 4 + .../inline/property/removeImport.kt.after | 3 + .../refactoring/inline/AbstractInlineTest.kt | 19 ++++- .../inline/InlineTestGenerated.java | 30 ++++++-- 25 files changed, 245 insertions(+), 53 deletions(-) create mode 100644 idea/testData/refactoring/inline/property/keepImport.1.kt create mode 100644 idea/testData/refactoring/inline/property/keepImport.1.kt.after create mode 100644 idea/testData/refactoring/inline/property/keepImport.kt create mode 100644 idea/testData/refactoring/inline/property/keepImport.kt.after create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.1.kt create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.1.kt.after create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.2.kt create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.2.kt.after create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.3.kt create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.3.kt.after create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.4.kt create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.4.kt.after create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.5.kt create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.5.kt.after create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.kt create mode 100644 idea/testData/refactoring/inline/property/multiplePackages.kt.after create mode 100644 idea/testData/refactoring/inline/property/removeImport.1.kt create mode 100644 idea/testData/refactoring/inline/property/removeImport.1.kt.after create mode 100644 idea/testData/refactoring/inline/property/removeImport.kt create mode 100644 idea/testData/refactoring/inline/property/removeImport.kt.after diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 517bc3f54fa..880cc310fe9 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -499,7 +499,7 @@ fun main(args: Array) { } testClass() { - model("refactoring/inline") + model("refactoring/inline", pattern = "^(\\w+)\\.kt$") } testClass() { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt index e6ce10e9e22..26aec750252 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt @@ -25,6 +25,7 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.colors.EditorColors import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key import com.intellij.openapi.wm.WindowManager import com.intellij.psi.PsiElement import com.intellij.psi.PsiWhiteSpace @@ -33,17 +34,24 @@ import com.intellij.refactoring.HelpID import com.intellij.refactoring.RefactoringBundle import com.intellij.refactoring.util.CommonRefactoringUtil import com.intellij.refactoring.util.RefactoringMessageDialog +import com.intellij.usageView.UsageInfo import com.intellij.util.containers.MultiMap import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedShortening import org.jetbrains.kotlin.idea.core.refactoring.checkConflictsInteractively import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.idea.refactoring.move.PackageNameInfo +import org.jetbrains.kotlin.idea.refactoring.move.lazilyProcessInternalReferencesToUpdateOnPackageNameChange +import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages +import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.ShortenReferences import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext @@ -58,6 +66,11 @@ import org.jetbrains.kotlin.utils.sure import java.util.* class KotlinInlineValHandler : InlineActionHandler() { + companion object { + private var KtSimpleNameExpression.internalUsageInfos: MutableMap UsageInfo?>? + by CopyableUserDataProperty(Key.create("INTERNAL_USAGE_INFOS")) + } + override fun isEnabledForLanguage(l: Language) = l == KotlinLanguage.INSTANCE override fun canInlineElement(element: PsiElement): Boolean { @@ -146,14 +159,28 @@ class KotlinInlineValHandler : InlineActionHandler() { val typeArgumentsForCall = getTypeArgumentsStringForCall(initializer) val parametersForFunctionLiteral = getParametersForFunctionLiteral(initializer) - val canHighlight = referenceExpressions.all { it.containingFile === file } - if (canHighlight) { + val isSingleFile = referenceExpressions.all { it.containingFile === file } + if (isSingleFile) { highlightExpressions(project, editor, referenceExpressions) } + if (!isSingleFile) { + val targetPackages = referenceExpressions.mapNotNullTo(LinkedHashSet()) { (it.containingFile as? KtFile)?.packageFqName } + for (targetPackage in targetPackages) { + if (targetPackage == file.packageFqName) continue + val packageNameInfo = PackageNameInfo(file.packageFqName, targetPackage.toUnsafe()) + initializer.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) { expr, factory -> + val infos = expr.internalUsageInfos + ?: LinkedHashMap UsageInfo?>() + .apply { expr.internalUsageInfos = this } + infos[targetPackage] = factory + } + } + } + fun performRefactoring() { if (!showDialog(project, name, declaration, referenceExpressions)) { - if (canHighlight) { + if (isSingleFile) { val statusBar = WindowManager.getInstance().getStatusBar(project) statusBar?.info = RefactoringBundle.message("press.escape.to.remove.the.highlighting") } @@ -161,23 +188,45 @@ class KotlinInlineValHandler : InlineActionHandler() { } project.executeWriteCommand(RefactoringBundle.message("inline.command", name)) { - val inlinedExpressions = referenceExpressions.flatMap { referenceExpression -> - if (assignments.contains(referenceExpression.parent)) return@flatMap emptyList() - doReplace(referenceExpression, initializer) - } + val inlinedExpressions = referenceExpressions + .flatMap { referenceExpression -> + if (assignments.contains(referenceExpression.parent)) return@flatMap emptyList() + + val importDirective = referenceExpression.getStrictParentOfType() + if (importDirective != null) { + val reference = referenceExpression.getQualifiedElementSelector()?.mainReference + if (reference != null && reference.multiResolve(false).size <= 1) { + importDirective.delete() + } + + return@flatMap emptyList() + } + + doReplace(referenceExpression, initializer) + } + .mapNotNull { inlinedExpression -> + val pointer = inlinedExpression.createSmartPointer() + val targetPackage = inlinedExpression.getContainingKtFile().packageFqName + val expressionsToProcess = inlinedExpression.collectDescendantsOfType { it.internalUsageInfos != null } + val internalUsages = expressionsToProcess.mapNotNull { it.internalUsageInfos!![targetPackage]?.invoke(it) } + expressionsToProcess.forEach { it.internalUsageInfos = null } + postProcessMoveUsages(internalUsages) + pointer.element + } assignments.forEach { it.delete() } declaration.delete() - if (inlinedExpressions.isEmpty()) return@executeWriteCommand + if (inlinedExpressions.isNotEmpty()) { + typeArgumentsForCall?.let { addTypeArguments(it, inlinedExpressions) } - typeArgumentsForCall?.let { addTypeArguments(it, inlinedExpressions) } + parametersForFunctionLiteral?.let { addFunctionLiteralParameterTypes(it, inlinedExpressions) } - parametersForFunctionLiteral?.let { addFunctionLiteralParameterTypes(it, inlinedExpressions) } - - if (canHighlight) { - highlightExpressions(project, editor, inlinedExpressions) + if (isSingleFile) { + highlightExpressions(project, editor, inlinedExpressions) + } } + performDelayedShortening(project) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt index 16aff373ad5..70dd6e71090 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt @@ -37,7 +37,6 @@ import com.intellij.refactoring.util.MoveRenameUsageInfo import com.intellij.refactoring.util.NonCodeUsageInfo import com.intellij.usageView.UsageInfo import com.intellij.util.IncorrectOperationException -import com.intellij.util.containers.ContainerUtil import org.jetbrains.kotlin.asJava.namedUnwrappedElement import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.descriptors.* @@ -63,14 +62,24 @@ import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor +import org.jetbrains.kotlin.utils.addIfNotNull import java.util.* val UNKNOWN_PACKAGE_FQ_NAME = FqNameUnsafe("org.jetbrains.kotlin.idea.refactoring.move.") public class PackageNameInfo(val oldPackageName: FqName, val newPackageName: FqNameUnsafe) -public fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo: PackageNameInfo): List { - val file = getContainingFile() as? KtFile ?: return listOf() +fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo: PackageNameInfo): List { + val usages = ArrayList() + lazilyProcessInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) { expr, factory -> usages.addIfNotNull(factory(expr)) } + return usages +} + +fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange( + packageNameInfo: PackageNameInfo, + body: (originalRefExpr: KtSimpleNameExpression, usageFactory: (KtSimpleNameExpression) -> UsageInfo?) -> Unit +) { + val file = getContainingFile() as? KtFile ?: return val importPaths = file.getImportDirectives().mapNotNull { it.getImportPath() } @@ -85,7 +94,7 @@ public fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(packageNam } } - fun processReference(refExpr: KtSimpleNameExpression, bindingContext: BindingContext): UsageInfo? { + fun processReference(refExpr: KtSimpleNameExpression, bindingContext: BindingContext): ((KtSimpleNameExpression) -> UsageInfo?)? { val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.getImportableDescriptor() ?: return null val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(getProject(), descriptor) ?: return null @@ -95,11 +104,13 @@ public fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(packageNam if (isCallable && !isExtension) { val containingDescriptor = descriptor.getContainingDeclaration() - val receiver = refExpr.getReceiverExpression() - if (receiver != null) { - val receiverRef = receiver.getQualifiedElementSelector() as? KtSimpleNameExpression ?: return null - if (bindingContext[BindingContext.QUALIFIER, receiverRef] == null) return null - return processReference(receiverRef, bindingContext) + if (refExpr.getReceiverExpression() != null) { + return fun(refExpr: KtSimpleNameExpression): UsageInfo? { + val receiver = refExpr.getReceiverExpression() ?: return null + val receiverRef = receiver.getQualifiedElementSelector() as? KtSimpleNameExpression ?: return null + if (bindingContext[BindingContext.QUALIFIER, receiverRef] == null) return null + return processReference(receiverRef, bindingContext)?.invoke(receiverRef) + } } if (containingDescriptor !is PackageFragmentDescriptor) return null } @@ -113,41 +124,38 @@ public fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(packageNam val oldPackageName = packageNameInfo.oldPackageName val newPackageName = packageNameInfo.newPackageName - return when { - isExtension || - packageName == oldPackageName || - packageName?.asString() == newPackageName.asString() || - isImported(descriptor) -> { - if (isAncestor(declaration, false)) { - if (descriptor.importableFqName == null) return null - if (isUnqualifiedExtensionReference(refExpr.mainReference, declaration)) return null - if (packageName == null || !newPackageName.isSafe) return null - fqName.asString().let { - val prefix = packageName.asString() - val prefixOffset = it.indexOf(prefix) - val newFqName = FqName(it.replaceRange(prefixOffset..prefixOffset + prefix.length() - 1, newPackageName.asString())) - return MoveRenameSelfUsageInfo(refExpr.mainReference, declaration, newFqName) - } - } - createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false) + fun doCreateUsageInfo(refExpr: KtSimpleNameExpression): UsageInfo? { + if (isAncestor(declaration, false)) { + if (descriptor.importableFqName == null) return null + if (isUnqualifiedExtensionReference(refExpr.mainReference, declaration)) return null + if (packageName == null || !newPackageName.isSafe) return null + return fqName.asString().let { + val prefix = packageName.asString() + val prefixOffset = it.indexOf(prefix) + val newFqName = FqName(it.replaceRange(prefixOffset..prefixOffset + prefix.length() - 1, newPackageName.asString())) + MoveRenameSelfUsageInfo(refExpr.mainReference, declaration, newFqName) + } } - else -> null + return createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false) } + + if (!isExtension && + packageName != oldPackageName && + packageName?.asString() != newPackageName.asString() && + !isImported(descriptor)) return null + return ::doCreateUsageInfo } val referenceToContext = KotlinFileReferencesResolver.resolve(file = file, elements = listOf(this)) - val usages = ArrayList() for ((refExpr, bindingContext) in referenceToContext) { if (refExpr !is KtSimpleNameExpression || refExpr.getParent() is KtThisExpression) continue if (bindingContext[BindingContext.QUALIFIER, refExpr] != null) continue - processReference(refExpr, bindingContext)?.let { usages.add(it) } + processReference(refExpr, bindingContext)?.let { body(refExpr, it) } } - - return usages } class MoveRenameUsageInfoForExtension( diff --git a/idea/testData/refactoring/inline/property/keepImport.1.kt b/idea/testData/refactoring/inline/property/keepImport.1.kt new file mode 100644 index 00000000000..b8a6b9d6502 --- /dev/null +++ b/idea/testData/refactoring/inline/property/keepImport.1.kt @@ -0,0 +1,7 @@ +package boo + +import foo.bar.a + +fun main(args: Array) { + println(a + a()) +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/keepImport.1.kt.after b/idea/testData/refactoring/inline/property/keepImport.1.kt.after new file mode 100644 index 00000000000..94db8c3337b --- /dev/null +++ b/idea/testData/refactoring/inline/property/keepImport.1.kt.after @@ -0,0 +1,8 @@ +package boo + +import foo.bar.a +import foo.bar.b + +fun main(args: Array) { + println(b + a()) +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/keepImport.kt b/idea/testData/refactoring/inline/property/keepImport.kt new file mode 100644 index 00000000000..9f0edfa8671 --- /dev/null +++ b/idea/testData/refactoring/inline/property/keepImport.kt @@ -0,0 +1,5 @@ +package foo.bar + +val b = 1 +val a = b +fun a() = b \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/keepImport.kt.after b/idea/testData/refactoring/inline/property/keepImport.kt.after new file mode 100644 index 00000000000..fc71cf6749f --- /dev/null +++ b/idea/testData/refactoring/inline/property/keepImport.kt.after @@ -0,0 +1,4 @@ +package foo.bar + +val b = 1 +fun a() = b \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.1.kt b/idea/testData/refactoring/inline/property/multiplePackages.1.kt new file mode 100644 index 00000000000..516fef35600 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.1.kt @@ -0,0 +1,3 @@ +package bar + +val x = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.1.kt.after b/idea/testData/refactoring/inline/property/multiplePackages.1.kt.after new file mode 100644 index 00000000000..516fef35600 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.1.kt.after @@ -0,0 +1,3 @@ +package bar + +val x = 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.2.kt b/idea/testData/refactoring/inline/property/multiplePackages.2.kt new file mode 100644 index 00000000000..fb1ae4facee --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.2.kt @@ -0,0 +1,3 @@ +package baz + +val y = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.2.kt.after b/idea/testData/refactoring/inline/property/multiplePackages.2.kt.after new file mode 100644 index 00000000000..fb1ae4facee --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.2.kt.after @@ -0,0 +1,3 @@ +package baz + +val y = 2 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.3.kt b/idea/testData/refactoring/inline/property/multiplePackages.3.kt new file mode 100644 index 00000000000..e2e40385810 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.3.kt @@ -0,0 +1,5 @@ +package bar + +import foo.z + +fun test() = z + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.3.kt.after b/idea/testData/refactoring/inline/property/multiplePackages.3.kt.after new file mode 100644 index 00000000000..2e21a9faf52 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.3.kt.after @@ -0,0 +1,5 @@ +package bar + +import baz.y + +fun test() = x + y + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.4.kt b/idea/testData/refactoring/inline/property/multiplePackages.4.kt new file mode 100644 index 00000000000..f03aa886397 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.4.kt @@ -0,0 +1,5 @@ +package baz + +import foo.z + +fun test() = z + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.4.kt.after b/idea/testData/refactoring/inline/property/multiplePackages.4.kt.after new file mode 100644 index 00000000000..c215754c65b --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.4.kt.after @@ -0,0 +1,5 @@ +package baz + +import bar.x + +fun test() = x + y + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.5.kt b/idea/testData/refactoring/inline/property/multiplePackages.5.kt new file mode 100644 index 00000000000..1f39a08a198 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.5.kt @@ -0,0 +1,5 @@ +package other + +import foo.z + +fun test() = z + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.5.kt.after b/idea/testData/refactoring/inline/property/multiplePackages.5.kt.after new file mode 100644 index 00000000000..781b0a18925 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.5.kt.after @@ -0,0 +1,6 @@ +package other + +import bar.x +import baz.y + +fun test() = x + y + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.kt b/idea/testData/refactoring/inline/property/multiplePackages.kt new file mode 100644 index 00000000000..f405e6d83c8 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.kt @@ -0,0 +1,8 @@ +package foo + +import bar.x +import baz.y + +val z = x + y + +fun test() = z + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/multiplePackages.kt.after b/idea/testData/refactoring/inline/property/multiplePackages.kt.after new file mode 100644 index 00000000000..3db4f5c9e26 --- /dev/null +++ b/idea/testData/refactoring/inline/property/multiplePackages.kt.after @@ -0,0 +1,6 @@ +package foo + +import bar.x +import baz.y + +fun test() = x + y + 1 \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/removeImport.1.kt b/idea/testData/refactoring/inline/property/removeImport.1.kt new file mode 100644 index 00000000000..8b1db781ef4 --- /dev/null +++ b/idea/testData/refactoring/inline/property/removeImport.1.kt @@ -0,0 +1,7 @@ +package boo + +import foo.bar.a + +fun main(args: Array) { + println(a) +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/removeImport.1.kt.after b/idea/testData/refactoring/inline/property/removeImport.1.kt.after new file mode 100644 index 00000000000..f634978e72d --- /dev/null +++ b/idea/testData/refactoring/inline/property/removeImport.1.kt.after @@ -0,0 +1,7 @@ +package boo + +import foo.bar.b + +fun main(args: Array) { + println(b) +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/removeImport.kt b/idea/testData/refactoring/inline/property/removeImport.kt new file mode 100644 index 00000000000..43492ce3bb2 --- /dev/null +++ b/idea/testData/refactoring/inline/property/removeImport.kt @@ -0,0 +1,4 @@ +package foo.bar + +val b = 1 +val a = b \ No newline at end of file diff --git a/idea/testData/refactoring/inline/property/removeImport.kt.after b/idea/testData/refactoring/inline/property/removeImport.kt.after new file mode 100644 index 00000000000..53252726dcf --- /dev/null +++ b/idea/testData/refactoring/inline/property/removeImport.kt.after @@ -0,0 +1,3 @@ +package foo.bar + +val b = 1 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/AbstractInlineTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/AbstractInlineTest.kt index e08eaf876c6..301a0afa371 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/AbstractInlineTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/AbstractInlineTest.kt @@ -22,18 +22,30 @@ import com.intellij.codeInsight.TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED import com.intellij.openapi.util.io.FileUtil import com.intellij.refactoring.util.CommonRefactoringUtil import com.intellij.testFramework.UsefulTestCase +import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture import junit.framework.TestCase import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.test.InTextDirectivesUtils +import org.jetbrains.kotlin.test.KotlinTestUtils import java.io.File abstract class AbstractInlineTest : KotlinLightCodeInsightFixtureTestCase() { + val fixture: JavaCodeInsightTestFixture + get() = myFixture + protected fun doTest(path: String) { + val mainFile = File(path) val afterFile = File(path + ".after") - myFixture.configureByFile(path) + val mainFileName = mainFile.name + val mainFileBaseName = FileUtil.getNameWithoutExtension(mainFileName) + val extraFiles = mainFile.parentFile.listFiles { file, name -> + name != mainFileName && name.startsWith("$mainFileBaseName.") && (name.endsWith(".kt") || name.endsWith(".java")) + } + val extraFilesToPsi = extraFiles.toMapBy { fixture.configureByFile(path.replace(mainFileName, it.name)) } + val file = myFixture.configureByFile(path) val afterFileExists = afterFile.exists() @@ -47,7 +59,10 @@ abstract class AbstractInlineTest : KotlinLightCodeInsightFixtureTestCase() { TestCase.assertTrue(afterFileExists) UsefulTestCase.assertEmpty(expectedErrors) - myFixture.checkResult(FileUtil.loadFile(afterFile, true)) + KotlinTestUtils.assertEqualsToFile(afterFile, file.text) + for ((extraPsiFile, extraFile) in extraFilesToPsi) { + KotlinTestUtils.assertEqualsToFile(File("${extraFile.path}.after"), extraPsiFile.text) + } } catch (e: CommonRefactoringUtil.RefactoringErrorHintException) { TestCase.assertFalse(afterFileExists) diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java index ffbf3d6c8c7..5012af55728 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java @@ -32,7 +32,7 @@ import java.util.regex.Pattern; @RunWith(JUnit3RunnerWithInners.class) public class InlineTestGenerated extends AbstractInlineTest { public void testAllFilesPresentInInline() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline"), Pattern.compile("^(\\w+)\\.kt$"), true); } @TestMetadata("Basic.kt") @@ -154,7 +154,7 @@ public class InlineTestGenerated extends AbstractInlineTest { @RunWith(JUnit3RunnerWithInners.class) public static class AddParenthesis extends AbstractInlineTest { public void testAllFilesPresentInAddParenthesis() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/addParenthesis"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/addParenthesis"), Pattern.compile("^(\\w+)\\.kt$"), true); } @TestMetadata("ArrayAccess.kt") @@ -343,7 +343,7 @@ public class InlineTestGenerated extends AbstractInlineTest { @RunWith(JUnit3RunnerWithInners.class) public static class ExplicateParameterTypes extends AbstractInlineTest { public void testAllFilesPresentInExplicateParameterTypes() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/explicateParameterTypes"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/explicateParameterTypes"), Pattern.compile("^(\\w+)\\.kt$"), true); } @TestMetadata("EnoughDontExplicate.kt") @@ -394,7 +394,7 @@ public class InlineTestGenerated extends AbstractInlineTest { @RunWith(JUnit3RunnerWithInners.class) public static class ExplicateTypeArgument extends AbstractInlineTest { public void testAllFilesPresentInExplicateTypeArgument() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/explicateTypeArgument"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/explicateTypeArgument"), Pattern.compile("^(\\w+)\\.kt$"), true); } @TestMetadata("DeeperNestedCall.kt") @@ -457,7 +457,7 @@ public class InlineTestGenerated extends AbstractInlineTest { @RunWith(JUnit3RunnerWithInners.class) public static class Property extends AbstractInlineTest { public void testAllFilesPresentInProperty() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/property"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/property"), Pattern.compile("^(\\w+)\\.kt$"), true); } @TestMetadata("Basic.kt") @@ -484,6 +484,18 @@ public class InlineTestGenerated extends AbstractInlineTest { doTest(fileName); } + @TestMetadata("keepImport.kt") + public void testKeepImport() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/property/keepImport.kt"); + doTest(fileName); + } + + @TestMetadata("multiplePackages.kt") + public void testMultiplePackages() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/property/multiplePackages.kt"); + doTest(fileName); + } + @TestMetadata("ObjectProperty.kt") public void testObjectProperty() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/property/ObjectProperty.kt"); @@ -496,6 +508,12 @@ public class InlineTestGenerated extends AbstractInlineTest { doTest(fileName); } + @TestMetadata("removeImport.kt") + public void testRemoveImport() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/property/removeImport.kt"); + doTest(fileName); + } + @TestMetadata("WithGetter.kt") public void testWithGetter() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/property/WithGetter.kt"); @@ -520,7 +538,7 @@ public class InlineTestGenerated extends AbstractInlineTest { } public void testAllFilesPresentInStringTemplates() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/stringTemplates"), Pattern.compile("^(.+)\\.kt$"), true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/inline/stringTemplates"), Pattern.compile("^(\\w+)\\.kt$"), true); } @TestMetadata("blockEntry.kt")