Move top-level declarations to separate file: Refactoring processor and tests

This commit is contained in:
Alexey Sedunov
2014-03-20 15:34:04 +04:00
parent 6ddcd51af2
commit 5aa75ba3e1
216 changed files with 1770 additions and 42 deletions
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2014 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.jet.plugin.refactoring.move.moveTopLevelDeclarations
import com.intellij.refactoring.PackageWrapper
import com.intellij.refactoring.MoveDestination
import org.jetbrains.jet.lang.psi.JetFile
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
public trait KotlinMoveTarget {
val packageWrapper: PackageWrapper?
fun getOrCreateTargetPsi(originalPsi: PsiElement): PsiElement?
fun getTargetPsiIfExists(originalPsi: PsiElement): PsiElement?
// Check possible errors and return corresponding message, or null if no errors are detected
fun verify(file: PsiFile): String?
}
public class MoveDestinationKotlinMoveTarget(val moveDestination: MoveDestination): KotlinMoveTarget {
override val packageWrapper: PackageWrapper? = moveDestination.getTargetPackage()
override fun getOrCreateTargetPsi(originalPsi: PsiElement): PsiElement? =
moveDestination.getTargetDirectory(originalPsi.getContainingFile())
override fun getTargetPsiIfExists(originalPsi: PsiElement): PsiElement? =
moveDestination.getTargetIfExists(originalPsi.getContainingFile())
override fun verify(file: PsiFile): String? = moveDestination.verify(file)
}
public class JetFileKotlinMoveTarget(val targetFile: JetFile): KotlinMoveTarget {
override val packageWrapper: PackageWrapper? = targetFile.getPackageName()?.let { packageName ->
PackageWrapper(PsiManager.getInstance(targetFile.getProject()), packageName)
}
override fun getOrCreateTargetPsi(originalPsi: PsiElement): PsiElement? = targetFile
override fun getTargetPsiIfExists(originalPsi: PsiElement): PsiElement? = targetFile
// No additional verification is needed
override fun verify(file: PsiFile): String? = null
}
@@ -20,7 +20,6 @@ import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.openapi.project.Project
import com.intellij.usageView.UsageInfo
import com.intellij.usageView.UsageViewDescriptor
import com.intellij.refactoring.MoveDestination
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.MoveMultipleElementsViewDescriptor
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil
@@ -33,7 +32,6 @@ import com.intellij.util.IncorrectOperationException
import com.intellij.refactoring.util.RefactoringUIUtil
import org.jetbrains.jet.utils.keysToMap
import com.intellij.refactoring.rename.RenameUtil
import com.intellij.refactoring.move.MoveClassesOrPackagesCallback
import org.jetbrains.jet.plugin.refactoring.JetRefactoringBundle
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiDirectory
@@ -56,14 +54,12 @@ import com.intellij.psi.PsiReference
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.refactoring.util.MoveRenameUsageInfo
import com.intellij.psi.PsiClass
import com.intellij.refactoring.util.TextOccurrencesUtil
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassHandler
import com.intellij.util.containers.MultiMap
import org.jetbrains.jet.asJava.namedUnwrappedElement
import org.jetbrains.jet.lang.psi.psiUtil.isPrivate
import org.jetbrains.jet.plugin.refactoring.getUsageContext
import com.intellij.refactoring.util.CommonRefactoringUtil
import org.jetbrains.jet.lang.psi.psiUtil.isInsideOf
import org.jetbrains.jet.plugin.codeInsight.JetFileReferencesResolver
import org.jetbrains.jet.lang.resolve.BindingContext
@@ -78,7 +74,7 @@ import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode
public class MoveKotlinTopLevelDeclarationsOptions(
val elementsToMove: Collection<JetNamedDeclaration>,
val moveDestination: MoveDestination,
val moveTarget: KotlinMoveTarget,
val searchInCommentsAndStrings: Boolean = true,
val searchInNonCode: Boolean = true,
val moveCallback: MoveCallback? = null
@@ -92,18 +88,19 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
}
private var nonCodeUsages: Array<NonCodeUsageInfo>? = null
private val kotlinToLightElements = options.elementsToMove.keysToMap { it.toLightElements() }
private val elementsToMove = options.elementsToMove.filter { e -> e.getContainingFile() != options.moveTarget.getTargetPsiIfExists(e) }
private val kotlinToLightElements = elementsToMove.keysToMap { it.toLightElements() }
private val conflicts = MultiMap<PsiElement, String>()
override fun createUsageViewDescriptor(usages: Array<out UsageInfo>?): UsageViewDescriptor {
return MoveMultipleElementsViewDescriptor(
options.elementsToMove.copyToArray(),
MoveClassesOrPackagesUtil.getPackageName(options.moveDestination.getTargetPackage())
elementsToMove.copyToArray(),
MoveClassesOrPackagesUtil.getPackageName(options.moveTarget.packageWrapper)
)
}
override fun findUsages(): Array<UsageInfo> {
val newPackageName = options.moveDestination.getTargetPackage()?.getQualifiedName() ?: ""
val newPackageName = options.moveTarget.packageWrapper?.getQualifiedName() ?: ""
fun collectUsages(): List<UsageInfo> {
return kotlinToLightElements.values().flatten().flatMap { lightElement ->
@@ -156,7 +153,7 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
val declaration = usage.getReferencedElement()?.namedUnwrappedElement as? JetNamedDeclaration
if (declaration == null || !declaration.isPrivate()) continue
if (element.isInsideOf(options.elementsToMove)) continue
if (element.isInsideOf(elementsToMove)) continue
val container = element.getUsageContext()
if (!declarationToContainers.getOrPut(declaration) { HashSet<PsiElement>() }.add(container)) continue
@@ -177,13 +174,13 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
fun collectConflictsInDeclarations() {
val declarationToReferenceTargets = HashMap<JetNamedDeclaration, MutableSet<PsiElement>>()
for (declaration in options.elementsToMove) {
for (declaration in elementsToMove) {
val referenceToContext = JetFileReferencesResolver.resolve(element = declaration, visitReceivers = false)
for ((refExpr, bindingContext) in referenceToContext) {
val refTarget = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.let { descriptor ->
DescriptorToDeclarationUtil.getDeclaration(declaration.getProject(), descriptor, bindingContext)
}
if (refTarget == null || refTarget.isInsideOf(options.elementsToMove)) continue
if (refTarget == null || refTarget.isInsideOf(elementsToMove)) continue
val packagePrivate = when(refTarget) {
is JetModifierListOwner ->
@@ -223,23 +220,32 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
}
override fun performRefactoring(usages: Array<out UsageInfo>?) {
fun moveDeclaration(declaration: JetNamedDeclaration, moveDestination: PsiDirectory): JetNamedDeclaration? {
val newPackage = moveDestination.getPackage()
if (newPackage == null) return null
fun moveDeclaration(declaration: JetNamedDeclaration, moveTarget: KotlinMoveTarget): JetNamedDeclaration? {
val file = declaration.getContainingFile() as? JetFile
if (file == null) return null
assert (file != null, "${declaration.getClass()}: ${declaration.getText()}")
val packageNameInfo = PackageNameInfo(JetPsiUtil.getFQName(file), FqName(newPackage.getQualifiedName()))
val targetPsi = moveTarget.getOrCreateTargetPsi(declaration)
val targetFile =
if (targetPsi is PsiDirectory) {
val existingFile = if (targetPsi != file!!.getContainingDirectory()) targetPsi.findFile(file.getName()) else null
val newFile = existingFile ?: declaration.getFileNameAfterMove()?.let {
fileName ->
createKotlinFile(fileName, targetPsi)
}
val existingFile = if (moveDestination != file.getContainingDirectory()) moveDestination.findFile(file.getName()) else null
val newFile = existingFile ?: declaration.getFileNameAfterMove()?.let {
fileName -> createKotlinFile(fileName, moveDestination)
}
assert(newFile != null, "Couldn't create Koltin file for: ${declaration.getClass()}: ${declaration.getText()}")
newFile
}
else targetPsi
assert(targetFile is JetFile, "Couldn't create Koltin file for: ${declaration.getClass()}: ${declaration.getText()}")
val newPackage = (targetFile as JetFile).getPackageName()
assert (newPackage != null, "${targetFile.getClass()}: ${targetFile.getText()}")
val packageNameInfo = PackageNameInfo(JetPsiUtil.getFQName(file!!), FqName(newPackage!!))
declaration.updateInternalReferencesOnPackageNameChange(packageNameInfo, ShorteningMode.NO_SHORTENING)
val newElement = newFile!!.add(declaration) as JetNamedDeclaration
val newElement = targetFile.add(declaration) as JetNamedDeclaration
declaration.delete()
newElement.addToShorteningWaitSet()
@@ -250,11 +256,13 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
try {
val oldToNewElementsMapping = HashMap<PsiElement, PsiElement>()
for ((oldDeclaration, oldLightElements) in kotlinToLightElements) {
val targetDirectory = options.moveDestination.getTargetDirectory(oldDeclaration.getContainingFile())
if (targetDirectory == null) continue
val newDeclaration = moveDeclaration(oldDeclaration, targetDirectory)
if (newDeclaration == null) continue
val newDeclaration = moveDeclaration(oldDeclaration, options.moveTarget)
if (newDeclaration == null) {
for (oldElement in oldLightElements) {
oldToNewElementsMapping[oldElement] = oldElement
}
continue
}
getTransaction()!!.getElementListener(oldDeclaration).elementMoved(newDeclaration)
for ((oldElement, newElement) in oldLightElements.iterator() zip newDeclaration.toLightElements().iterator()) {
@@ -272,13 +280,7 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
override fun performPsiSpoilingRefactoring() {
nonCodeUsages?.let { nonCodeUsages -> RenameUtil.renameNonCodeUsages(myProject, nonCodeUsages) }
options.moveCallback?.let { moveCallback ->
if (moveCallback is MoveClassesOrPackagesCallback) {
moveCallback.classesOrPackagesMoved(options.moveDestination)
}
moveCallback.refactoringCompleted()
}
options.moveCallback?.refactoringCompleted()
}
override fun getCommandName(): String = REFACTORING_NAME
@@ -0,0 +1,7 @@
package a
import b.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package a
import b.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,7 @@
package a
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,7 @@
package a
import b.Test
fun test(): Test {
return Test()
}
@@ -0,0 +1,9 @@
package a;
import b.Test;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package a
import b.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package a
import b.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,16 @@
package b
open class Foo {
open class Bar {
}
}
class Test {
val aFoo: a.Foo = a.Foo()
val bFoo: Foo = Foo()
val cFoo: c.Foo = c.Foo()
val aBar: a.Foo.Bar = a.Foo.Bar()
val bBar: Foo.Bar = Foo.Bar()
val cBar: c.Foo.Bar = c.Foo.Bar()
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,5 @@
package b
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package b
import a.*
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package b
import b.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package b
import b.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,7 @@
package c
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,9 @@
package c;
import b.Test;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package c
import b.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,9 @@
package c;
import b.Test;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,8 @@
package c
import a.*
import b.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,9 @@
package c;
import b.Test;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package c
import b.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package c
import b.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,5 @@
package a
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package a
import a.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,7 @@
package a
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,14 @@
package a
class <caret>Test {
val aFoo: Foo = Foo()
val bFoo: b.Foo = b.Foo()
val cFoo: c.Foo = c.Foo()
val aBar: Foo.Bar = Foo.Bar()
val bBar: b.Foo.Bar = b.Foo.Bar()
val cBar: c.Foo.Bar = c.Foo.Bar()
}
fun test(): Test {
return Test()
}
@@ -0,0 +1,7 @@
package a;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,5 @@
package a
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package a
import a.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,8 @@
package b
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
a.Test t = new a.Test();
}
}
@@ -0,0 +1,5 @@
package b
fun bar() {
val t: a.Test = a.Test()
}
@@ -0,0 +1,9 @@
package b;
import a.*;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package b
import a.*
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,9 @@
package b;
import a.Test;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package b
import a.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package b
import a.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,7 @@
package c
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,7 @@
package c;
class J {
void bar() {
a.Test t = new a.Test();
}
}
@@ -0,0 +1,5 @@
package c
fun bar() {
val t: a.Test = a.Test()
}
@@ -0,0 +1,9 @@
package c;
import a.*;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package c
import a.*
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,9 @@
package c;
import a.Test;
class J {
void bar() {
Test t = new Test();
}
}
@@ -0,0 +1,7 @@
package c
import a.Test
fun bar() {
val t: Test = Test()
}
@@ -0,0 +1,7 @@
package c
import a.Test as _Test
fun bar() {
val t: _Test = _Test()
}
@@ -0,0 +1,5 @@
{
"mainFile": "a/main.kt",
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
"targetFile": "b/dependency.kt"
}
@@ -0,0 +1,5 @@
package a
fun bar() {
b.test()
}
@@ -0,0 +1,7 @@
package a
import b.test as _test
fun bar() {
_test()
}
@@ -0,0 +1,7 @@
package a
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,7 @@
package a
class Test {
fun foo() {
b.test()
}
}
@@ -0,0 +1,7 @@
package a;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,5 @@
package a
fun bar() {
b.test()
}
@@ -0,0 +1,7 @@
package a;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,7 @@
package a
import b.test as _test
fun bar() {
_test()
}
@@ -0,0 +1,9 @@
package a;
import static b.BPackage.test;
class J {
void bar() {
test();
}
}
@@ -0,0 +1,16 @@
package b
open class Foo {
open class Bar {
}
}
fun test {
val aFoo: a.Foo = a.Foo()
val bFoo: Foo = Foo()
val cFoo: c.Foo = c.Foo()
val aBar: a.Foo.Bar = a.Foo.Bar()
val bBar: Foo.Bar = Foo.Bar()
val cBar: c.Foo.Bar = c.Foo.Bar()
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,5 @@
package b
fun bar() {
test()
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,7 @@
package b
import a.*
fun bar() {
test()
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,7 @@
package b
import b.test
fun bar() {
test()
}
@@ -0,0 +1,7 @@
package b
import b.test as _test
fun bar() {
_test()
}
@@ -0,0 +1,9 @@
package b;
import static b.BPackage.test;
class J {
void bar() {
test();
}
}
@@ -0,0 +1,7 @@
package c
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,7 @@
package c;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,5 @@
package c
fun bar() {
b.test()
}
@@ -0,0 +1,7 @@
package c;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,7 @@
package c
import a.*
fun bar() {
b.test()
}
@@ -0,0 +1,7 @@
package c;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,7 @@
package c;
class J {
void bar() {
b.BPackage.test();
}
}
@@ -0,0 +1,7 @@
package c
import b.test
fun bar() {
test()
}
@@ -0,0 +1,7 @@
package c
import b.test as _test
fun bar() {
_test()
}
@@ -0,0 +1,9 @@
package c;
import static b.BPackage.test;
class J {
void bar() {
test();
}
}
@@ -0,0 +1,5 @@
package a
fun bar() {
test()
}
@@ -0,0 +1,7 @@
package a
import a.test as _test
fun bar() {
_test()
}
@@ -0,0 +1,7 @@
package a
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,16 @@
package a
fun <caret>test {
val aFoo: Foo = Foo()
val bFoo: b.Foo = b.Foo()
val cFoo: c.Foo = c.Foo()
val aBar: Foo.Bar = Foo.Bar()
val bBar: b.Foo.Bar = b.Foo.Bar()
val cBar: c.Foo.Bar = c.Foo.Bar()
}
class Test {
fun foo() {
test()
}
}
@@ -0,0 +1,7 @@
package a;
class J {
void bar() {
APackage.test();
}
}
@@ -0,0 +1,5 @@
package a
fun bar() {
test()
}
@@ -0,0 +1,9 @@
package a;
import static a.APackage.*;
class J {
void bar() {
test();
}
}
@@ -0,0 +1,7 @@
package a
import a.test as _test
fun bar() {
_test()
}
@@ -0,0 +1,9 @@
package a;
import static a.APackage.test;
class J {
void bar() {
test();
}
}
@@ -0,0 +1,8 @@
package b
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,7 @@
package b;
class J {
void bar() {
a.APackage.test();
}
}
@@ -0,0 +1,5 @@
package b
fun bar() {
a.test()
}
@@ -0,0 +1,9 @@
package b;
import a.*;
class J {
void bar() {
APackage.test();
}
}
@@ -0,0 +1,7 @@
package b
import a.*
fun bar() {
test()
}
@@ -0,0 +1,9 @@
package b;
import static a.APackage.*;
class J {
void bar() {
test();
}
}
@@ -0,0 +1,9 @@
package b;
import a.APackage;
class J {
void bar() {
APackage.test();
}
}
@@ -0,0 +1,7 @@
package b
import a.test
fun bar() {
test()
}
@@ -0,0 +1,7 @@
package b
import a.test as _test
fun bar() {
_test()
}
@@ -0,0 +1,9 @@
package b;
import static a.APackage.test;
class J {
void bar() {
test();
}
}
@@ -0,0 +1,7 @@
package c
open class Foo {
open class Bar {
}
}
@@ -0,0 +1,7 @@
package c;
class J {
void bar() {
a.APackage.test();
}
}
@@ -0,0 +1,5 @@
package c
fun bar() {
a.test()
}

Some files were not shown because too many files have changed in this diff Show More