Cleanup 191 patchset logic (KTI-267)
This commit is contained in:
+1
-1
@@ -200,7 +200,7 @@ extra["intellijSeparateSdks"] = intellijSeparateSdks
|
||||
|
||||
extra["IntellijCoreDependencies"] =
|
||||
listOf(
|
||||
if (Platform[191].orHigher()) "asm-all-7.0.1" else "asm-all",
|
||||
"asm-all-7.0.1",
|
||||
"guava",
|
||||
"jdom",
|
||||
"jna",
|
||||
|
||||
@@ -30,9 +30,6 @@ dependencies {
|
||||
}
|
||||
|
||||
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", "groovy-all", rootProject = rootProject) }
|
||||
Platform[191].orLower {
|
||||
testCompile(intellijDep()) { includeJars("jps-builders") }
|
||||
}
|
||||
Platform[192].orHigher {
|
||||
testCompile(intellijPluginDep("java")) { includeJars("jps-builders") }
|
||||
}
|
||||
|
||||
@@ -17,10 +17,6 @@ dependencies {
|
||||
includeJars("extensions", "idea_rt", "util", "asm-all", rootProject = rootProject)
|
||||
}
|
||||
|
||||
Platform[191].orLower {
|
||||
testCompileOnly(intellijDep()) { includeJars("java-api") }
|
||||
}
|
||||
|
||||
Platform[192].orHigher {
|
||||
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api") }
|
||||
testRuntimeOnly(intellijPluginDep("java"))
|
||||
|
||||
+11
-41
@@ -9,7 +9,6 @@ package org.jetbrains.kotlin.idea.caches.trackers
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.SimpleModificationTracker
|
||||
import com.intellij.pom.tree.TreeAspect
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
|
||||
/**
|
||||
@@ -21,61 +20,32 @@ class KotlinCodeBlockModificationListener(
|
||||
treeAspect: TreeAspect
|
||||
) : KotlinCodeBlockModificationListenerCompat(project) {
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
private val isLanguageTrackerEnabled = modificationTrackerImpl.isEnableLanguageTrackerCompat
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
// When there're we no per-language trackers we had to increment global tracker first and process result afterward
|
||||
private val customIncrement = if (isLanguageTrackerEnabled) 0 else 1
|
||||
|
||||
init {
|
||||
init(
|
||||
treeAspect,
|
||||
incOCBCounter = { ktFile ->
|
||||
if (isLanguageTrackerEnabled) {
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
||||
} else {
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, false)
|
||||
// Increment counter and process changes in PsiModificationTracker.Listener
|
||||
modificationTrackerImpl.incCounter()
|
||||
}
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
||||
},
|
||||
kotlinOutOfCodeBlockTrackerProducer = {
|
||||
if (isLanguageTrackerEnabled) {
|
||||
SimpleModificationTracker()
|
||||
} else {
|
||||
object : SimpleModificationTracker() {
|
||||
override fun getModificationCount(): Long {
|
||||
@Suppress("DEPRECATION")
|
||||
return modificationTrackerImpl.outOfCodeBlockModificationCount
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleModificationTracker()
|
||||
},
|
||||
psiModificationTrackerListener = {
|
||||
@Suppress("UnstableApiUsage")
|
||||
if (isLanguageTrackerEnabled) {
|
||||
val kotlinTrackerInternalIDECount =
|
||||
modificationTrackerImpl.forLanguage(KotlinLanguage.INSTANCE).modificationCount
|
||||
if (kotlinModificationTracker == kotlinTrackerInternalIDECount) {
|
||||
// Some update that we are not sure is from Kotlin language, as Kotlin language tracker wasn't changed
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
} else {
|
||||
kotlinModificationTracker = kotlinTrackerInternalIDECount
|
||||
}
|
||||
val kotlinTrackerInternalIDECount =
|
||||
modificationTrackerImpl.forLanguage(KotlinLanguage.INSTANCE).modificationCount
|
||||
if (kotlinModificationTracker == kotlinTrackerInternalIDECount) {
|
||||
// Some update that we are not sure is from Kotlin language, as Kotlin language tracker wasn't changed
|
||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||
} else {
|
||||
kotlinModificationTracker = kotlinTrackerInternalIDECount
|
||||
}
|
||||
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onPsiModificationTrackerUpdate(customIncrement)
|
||||
perModuleOutOfCodeBlockTrackerUpdater.onPsiModificationTrackerUpdate()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun treeChanged(event: PsiTreeChangeEventImpl) {
|
||||
assert(isLanguageTrackerEnabled)
|
||||
super.treeChanged(event)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): KotlinCodeBlockModificationListener =
|
||||
project.getComponent(KotlinCodeBlockModificationListener::class.java)
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.caches.trackers
|
||||
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
@Suppress("unused")
|
||||
val PsiModificationTrackerImpl.isEnableLanguageTrackerCompat
|
||||
get() = true
|
||||
-16
@@ -38,22 +38,6 @@ abstract class AbstractKotlinInspection : LocalInspectionTool() {
|
||||
val problemDescriptor = manager.createProblemDescriptor(element, range, description, highlightType, isOnTheFly, *fixes)
|
||||
registerProblem(problemDescriptor)
|
||||
}
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
// a workaround for IDEA-211491
|
||||
override fun getProblemElement(psiElement: PsiElement): PsiNamedElement? {
|
||||
val parent = psiElement.parents().firstOrNull { parent ->
|
||||
when (parent) {
|
||||
is KtPropertyAccessor -> true
|
||||
is KtNamedDeclaration -> parent !is KtValVarKeywordOwner || parent.valOrVarKeyword != null
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
if (parent is KtPropertyAccessor) {
|
||||
return parent.property
|
||||
}
|
||||
return super.getProblemElement(psiElement)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -18,9 +18,6 @@ dependencies {
|
||||
testCompileOnly(intellijDep())
|
||||
testRuntime(intellijDep())
|
||||
|
||||
if (Platform[191].orLower()) {
|
||||
testRuntimeOnly(intellijPluginDep("Groovy"))
|
||||
}
|
||||
Platform[192].orHigher {
|
||||
testCompileOnly(intellijPluginDep("java"))
|
||||
testRuntime(intellijPluginDep("java"))
|
||||
|
||||
-4
@@ -935,8 +935,6 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp
|
||||
}
|
||||
}
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED Can't use property because there's no getter in 192 and thus it isn't property anymore
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
sourceSet.setSources(sourcesWithTypes.toMap())
|
||||
}
|
||||
}
|
||||
@@ -952,8 +950,6 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp
|
||||
sourceSet.targetCompatibility = ktSourceSetData.targetCompatibility
|
||||
sourceSet.dependencies += ktSourceSet.dependencies.mapNotNull { mppModel.dependencyMap[it] }
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED Can't use property because there's no getter in 192 and thus it isn't property anymore
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
sourceSet.setSources(linkedMapOf(
|
||||
ktSourceSet.sourceType to DefaultExternalSourceDirectorySet().also { dirSet ->
|
||||
dirSet.srcDirs = ktSourceSet.sourceDirs
|
||||
|
||||
+2
-2
@@ -47,6 +47,7 @@ import org.jetbrains.plugins.gradle.execution.build.GradleProjectTaskRunner;
|
||||
import org.jetbrains.plugins.gradle.service.project.GradleBuildSrcProjectsResolver;
|
||||
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil;
|
||||
import org.jetbrains.plugins.gradle.service.task.GradleTaskManager;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
|
||||
@@ -58,7 +59,6 @@ import java.util.stream.Collectors;
|
||||
import static com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration.PROGRESS_LISTENER_KEY;
|
||||
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
|
||||
import static com.intellij.openapi.util.text.StringUtil.*;
|
||||
import static org.jetbrains.kotlin.idea.gradle.execution.KotlinMPPGradleProjectTaskRunnerUtilKt.isDelegatedBuild;
|
||||
import static org.jetbrains.plugins.gradle.execution.GradleRunnerUtil.resolveProjectPath;
|
||||
|
||||
/**
|
||||
@@ -180,7 +180,7 @@ class KotlinMPPGradleProjectTaskRunner extends ProjectTaskRunner
|
||||
final ModuleBuildTask moduleBuildTask = (ModuleBuildTask) projectTask;
|
||||
final Module module = moduleBuildTask.getModule();
|
||||
|
||||
if (! isDelegatedBuild(module)) {
|
||||
if (module.getProject().getPresentableUrl() != null && GradleProjectSettings.isDelegatedBuildEnabled(module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -45,6 +45,7 @@ import org.jetbrains.plugins.gradle.execution.build.GradleProjectTaskRunner;
|
||||
import org.jetbrains.plugins.gradle.service.project.GradleBuildSrcProjectsResolver;
|
||||
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil;
|
||||
import org.jetbrains.plugins.gradle.service.task.GradleTaskManager;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
|
||||
@@ -56,7 +57,6 @@ import java.util.stream.Collectors;
|
||||
import static com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration.PROGRESS_LISTENER_KEY;
|
||||
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
|
||||
import static com.intellij.openapi.util.text.StringUtil.*;
|
||||
import static org.jetbrains.kotlin.idea.gradle.execution.KotlinMPPGradleProjectTaskRunnerUtilKt.isDelegatedBuild;
|
||||
import static org.jetbrains.plugins.gradle.execution.GradleRunnerUtil.resolveProjectPath;
|
||||
|
||||
/**
|
||||
@@ -177,7 +177,7 @@ class KotlinMPPGradleProjectTaskRunner extends ProjectTaskRunner
|
||||
final ModuleBuildTask moduleBuildTask = (ModuleBuildTask) projectTask;
|
||||
final Module module = moduleBuildTask.getModule();
|
||||
|
||||
if (! isDelegatedBuild(module)) {
|
||||
if (module.getProject().getPresentableUrl() != null && GradleProjectSettings.isDelegatedBuildEnabled(module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.gradle.execution
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
fun isDelegatedBuild(module: Module): Boolean {
|
||||
val projectUrl = module.project.presentableUrl
|
||||
if (projectUrl == null || !GradleProjectSettings.isDelegatedBuildEnabled(module)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -43,10 +43,6 @@ dependencies {
|
||||
compileOnly(intellijPluginDep("maven"))
|
||||
}
|
||||
|
||||
Platform[191].orLower {
|
||||
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
||||
}
|
||||
|
||||
Platform[192].orHigher {
|
||||
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||
|
||||
+2
-7
@@ -5,23 +5,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.test
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.testFramework.LightPlatformCodeInsightTestCase
|
||||
import com.intellij.util.ThrowableRunnable
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class KotlinLightPlatformCodeInsightTestCase : LightPlatformCodeInsightTestCase() {
|
||||
protected inline val project_: Project get() = project
|
||||
protected inline val editor_: Editor get() = editor
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
enableKotlinOfficialCodeStyle(project_)
|
||||
enableKotlinOfficialCodeStyle(project)
|
||||
}
|
||||
|
||||
override fun tearDown() = runAll(
|
||||
ThrowableRunnable { disableKotlinOfficialCodeStyle(project_) },
|
||||
ThrowableRunnable { disableKotlinOfficialCodeStyle(project) },
|
||||
ThrowableRunnable { super.tearDown() },
|
||||
)
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.testFramework.LightIdeaTestCase
|
||||
|
||||
// FIX ME WHEN BUNCH as36 REMOVED
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use KotlinLightCodeInsightFixtureTestCase instead")
|
||||
abstract class KotlinLightCodeInsightTestCase : com.intellij.testFramework.LightCodeInsightTestCase() {
|
||||
@@ -32,7 +31,6 @@ abstract class KotlinLightCodeInsightTestCase : com.intellij.testFramework.Light
|
||||
}
|
||||
|
||||
// FIX ME WHEN BUNCH as36 REMOVED
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class KotlinLightIdeaTestCase : LightIdeaTestCase() {
|
||||
protected inline val project_: Project get() = project
|
||||
protected inline val module_: Module get() = module
|
||||
|
||||
-2
@@ -16,7 +16,6 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.testFramework.LightIdeaTestCase
|
||||
|
||||
// FIX ME WHEN BUNCH as36 REMOVED
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use KotlinLightCodeInsightFixtureTestCase instead")
|
||||
abstract class KotlinLightCodeInsightTestCase : com.intellij.testFramework.LightCodeInsightTestCase() {
|
||||
@@ -32,7 +31,6 @@ abstract class KotlinLightCodeInsightTestCase : com.intellij.testFramework.Light
|
||||
}
|
||||
|
||||
// FIX ME WHEN BUNCH as36 REMOVED
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class KotlinLightIdeaTestCase : LightIdeaTestCase() {
|
||||
protected inline val project_: Project get() = project
|
||||
protected inline val module_: Module get() = module
|
||||
|
||||
@@ -19,10 +19,6 @@ dependencies {
|
||||
|
||||
testCompile(intellijPluginDep("stream-debugger"))
|
||||
|
||||
Platform[191].orLower {
|
||||
testCompileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
||||
}
|
||||
|
||||
Platform[192].orHigher {
|
||||
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl", "aether-dependency-resolver") }
|
||||
testRuntime(intellijPluginDep("java"))
|
||||
|
||||
+4
-4
@@ -33,7 +33,7 @@ abstract class AbstractPerformanceTypingIndentationTest : KotlinLightPlatformCod
|
||||
val originalFileText = FileUtil.loadFile(File(originFilePath), true)
|
||||
|
||||
try {
|
||||
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project_))
|
||||
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project))
|
||||
configurator.configureSettings()
|
||||
|
||||
performanceTest<Unit, Unit> {
|
||||
@@ -48,8 +48,8 @@ abstract class AbstractPerformanceTypingIndentationTest : KotlinLightPlatformCod
|
||||
executeAction(IdeActions.ACTION_EDITOR_ENTER)
|
||||
}
|
||||
tearDown {
|
||||
val actualTextWithCaret = StringBuilder(editor_.document.text).insert(
|
||||
editor_.caretModel.offset,
|
||||
val actualTextWithCaret = StringBuilder(editor.document.text).insert(
|
||||
editor.caretModel.offset,
|
||||
EditorTestUtil.CARET_TAG
|
||||
).toString()
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class AbstractPerformanceTypingIndentationTest : KotlinLightPlatformCod
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
CodeStyle.getSettings(project_).clearCodeStyleSettings()
|
||||
CodeStyle.getSettings(project).clearCodeStyleSettings()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler
|
||||
import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinPropertyProcessorCompat
|
||||
import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinPropertyProcessor
|
||||
import org.jetbrains.kotlin.idea.util.string.collapseSpaces
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -148,7 +148,7 @@ class KotlinElementDescriptionProvider : ElementDescriptionProvider {
|
||||
is KtImportAlias -> KotlinBundle.message("find.usages.import.alias")
|
||||
is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper -> KotlinBundle.message("find.usages.property")
|
||||
is KtLightClassForFacade -> KotlinBundle.message("find.usages.facade.class")
|
||||
is RenameKotlinPropertyProcessorCompat.PropertyMethodWrapper -> KotlinBundle.message("find.usages.property.accessor")
|
||||
is RenameKotlinPropertyProcessor.PropertyMethodWrapper -> KotlinBundle.message("find.usages.property.accessor")
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.move
|
||||
|
||||
import com.intellij.refactoring.move.MoveHandlerDelegate
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesHandler
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
typealias MoveHandlerDelegateCompat = MoveHandlerDelegate
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
typealias MoveFilesOrDirectoriesHandlerCompat = MoveFilesOrDirectoriesHandler
|
||||
+2
-2
@@ -25,6 +25,7 @@ import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.move.MoveCallback
|
||||
import com.intellij.refactoring.move.MoveHandlerDelegate
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesImpl
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.core.getPackage
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
|
||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.MoveHandlerDelegateCompat
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinSelectNestedClassRefactoringDialog
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinNestedClassesDialog
|
||||
@@ -91,7 +91,7 @@ private val defaultHandlerActions = object : MoveKotlinDeclarationsHandlerAction
|
||||
}
|
||||
|
||||
class MoveKotlinDeclarationsHandler internal constructor(private val handlerActions: MoveKotlinDeclarationsHandlerActions) :
|
||||
MoveHandlerDelegateCompat() {
|
||||
MoveHandlerDelegate() {
|
||||
|
||||
constructor() : this(defaultHandlerActions)
|
||||
|
||||
|
||||
+2
-2
@@ -13,9 +13,9 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.refactoring.move.MoveCallback
|
||||
import com.intellij.refactoring.move.MoveHandler
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesHandler
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.MoveFilesOrDirectoriesHandlerCompat
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.logFusForMoveRefactoring
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesModel
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandlerCompat() {
|
||||
class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler() {
|
||||
private fun adjustElements(elements: Array<out PsiElement>): Array<PsiFileSystemItem>? {
|
||||
return elements.map {
|
||||
when {
|
||||
|
||||
+120
-2
@@ -5,12 +5,130 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
|
||||
import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import java.util.ArrayList
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
class RenameKotlinClassifierProcessor : RenameKotlinClassifierProcessorCompat() {
|
||||
class RenameKotlinClassifierProcessor : RenameKotlinPsiProcessor() {
|
||||
|
||||
override fun canProcessElement(element: PsiElement): Boolean {
|
||||
return element is KtClassOrObject || element is KtLightClass || element is KtConstructor<*> || element is KtTypeAlias
|
||||
}
|
||||
|
||||
override fun isToSearchInComments(psiElement: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_CLASS
|
||||
|
||||
override fun setToSearchInComments(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_CLASS = enabled
|
||||
}
|
||||
|
||||
override fun isToSearchForTextOccurrences(element: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_CLASS
|
||||
|
||||
override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_CLASS = enabled
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor?) = getClassOrObject(element)
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>) {
|
||||
super.prepareRenaming(element, newName, allRenames)
|
||||
|
||||
val classOrObject = getClassOrObject(element) as? KtClassOrObject ?: return
|
||||
|
||||
classOrObject.withExpectedActuals().forEach {
|
||||
val file = it.containingKtFile
|
||||
val virtualFile = file.virtualFile
|
||||
if (virtualFile != null) {
|
||||
val nameWithoutExtensions = virtualFile.nameWithoutExtension
|
||||
if (nameWithoutExtensions == it.name) {
|
||||
val newFileName = newName + "." + virtualFile.extension
|
||||
allRenames.put(file, newFileName)
|
||||
forElement(file).prepareRenaming(file, newFileName, allRenames)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun processFoundReferences(
|
||||
element: PsiElement,
|
||||
references: Collection<PsiReference>
|
||||
): Collection<PsiReference> {
|
||||
if (element is KtObjectDeclaration && element.isCompanion()) {
|
||||
return references.filter { !it.isCompanionObjectClassReference() }
|
||||
}
|
||||
return references
|
||||
}
|
||||
|
||||
private fun PsiReference.isCompanionObjectClassReference(): Boolean {
|
||||
if (this !is KtSimpleNameReference) {
|
||||
return false
|
||||
}
|
||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
||||
return bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element] != null
|
||||
}
|
||||
|
||||
override fun findCollisions(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
allRenames: MutableMap<out PsiElement, String>,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return
|
||||
|
||||
val collisions = SmartList<UsageInfo>()
|
||||
checkRedeclarations(declaration, newName, collisions)
|
||||
checkOriginalUsagesRetargeting(declaration, newName, result, collisions)
|
||||
checkNewNameUsagesRetargeting(declaration, newName, collisions)
|
||||
result += collisions
|
||||
}
|
||||
|
||||
private fun getClassOrObject(element: PsiElement?): PsiElement? = when (element) {
|
||||
is KtLightClass ->
|
||||
when (element) {
|
||||
is KtLightClassForSourceDeclaration -> element.kotlinOrigin
|
||||
is KtLightClassForFacade -> element
|
||||
else -> throw AssertionError("Should not be suggested to rename element of type " + element::class.java + " " + element)
|
||||
}
|
||||
|
||||
is KtConstructor<*> ->
|
||||
element.getContainingClassOrObject()
|
||||
|
||||
is KtClassOrObject, is KtTypeAlias -> element
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun renameElement(element: PsiElement, newName: String, usages: Array<UsageInfo>, listener: RefactoringElementListener?) {
|
||||
val simpleUsages = ArrayList<UsageInfo>(usages.size)
|
||||
val ambiguousImportUsages = com.intellij.util.SmartList<UsageInfo>()
|
||||
for (usage in usages) {
|
||||
if (usage.isAmbiguousImportUsage()) {
|
||||
ambiguousImportUsages += usage
|
||||
} else {
|
||||
simpleUsages += usage
|
||||
}
|
||||
}
|
||||
element.ambiguousImportUsages = ambiguousImportUsages
|
||||
|
||||
super.renameElement(element, newName, simpleUsages.toTypedArray(), listener)
|
||||
|
||||
usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() }
|
||||
}
|
||||
|
||||
override fun findReferences(
|
||||
element: PsiElement,
|
||||
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
|
||||
import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import java.util.*
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class RenameKotlinClassifierProcessorCompat : RenameKotlinPsiProcessor() {
|
||||
override fun canProcessElement(element: PsiElement): Boolean {
|
||||
return element is KtClassOrObject || element is KtLightClass || element is KtConstructor<*> || element is KtTypeAlias
|
||||
}
|
||||
|
||||
override fun isToSearchInComments(psiElement: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_CLASS
|
||||
|
||||
override fun setToSearchInComments(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_CLASS = enabled
|
||||
}
|
||||
|
||||
override fun isToSearchForTextOccurrences(element: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_CLASS
|
||||
|
||||
override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_CLASS = enabled
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor?) = getClassOrObject(element)
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>) {
|
||||
super.prepareRenaming(element, newName, allRenames)
|
||||
|
||||
val classOrObject = getClassOrObject(element) as? KtClassOrObject ?: return
|
||||
|
||||
classOrObject.withExpectedActuals().forEach {
|
||||
val file = it.containingKtFile
|
||||
val virtualFile = file.virtualFile
|
||||
if (virtualFile != null) {
|
||||
val nameWithoutExtensions = virtualFile.nameWithoutExtension
|
||||
if (nameWithoutExtensions == it.name) {
|
||||
val newFileName = newName + "." + virtualFile.extension
|
||||
allRenames.put(file, newFileName)
|
||||
forElement(file).prepareRenaming(file, newFileName, allRenames)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun processFoundReferences(
|
||||
element: PsiElement,
|
||||
references: Collection<PsiReference>
|
||||
): Collection<PsiReference> {
|
||||
if (element is KtObjectDeclaration && element.isCompanion()) {
|
||||
return references.filter { !it.isCompanionObjectClassReference() }
|
||||
}
|
||||
return references
|
||||
}
|
||||
|
||||
private fun PsiReference.isCompanionObjectClassReference(): Boolean {
|
||||
if (this !is KtSimpleNameReference) {
|
||||
return false
|
||||
}
|
||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
||||
return bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element] != null
|
||||
}
|
||||
|
||||
override fun findCollisions(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
allRenames: MutableMap<out PsiElement, String>,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return
|
||||
|
||||
val collisions = SmartList<UsageInfo>()
|
||||
checkRedeclarations(declaration, newName, collisions)
|
||||
checkOriginalUsagesRetargeting(declaration, newName, result, collisions)
|
||||
checkNewNameUsagesRetargeting(declaration, newName, collisions)
|
||||
result += collisions
|
||||
}
|
||||
|
||||
private fun getClassOrObject(element: PsiElement?): PsiElement? = when (element) {
|
||||
is KtLightClass ->
|
||||
when (element) {
|
||||
is KtLightClassForSourceDeclaration -> element.kotlinOrigin
|
||||
is KtLightClassForFacade -> element
|
||||
else -> throw AssertionError("Should not be suggested to rename element of type " + element::class.java + " " + element)
|
||||
}
|
||||
|
||||
is KtConstructor<*> ->
|
||||
element.getContainingClassOrObject()
|
||||
|
||||
is KtClassOrObject, is KtTypeAlias -> element
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun renameElement(element: PsiElement, newName: String, usages: Array<UsageInfo>, listener: RefactoringElementListener?) {
|
||||
val simpleUsages = ArrayList<UsageInfo>(usages.size)
|
||||
val ambiguousImportUsages = com.intellij.util.SmartList<UsageInfo>()
|
||||
for (usage in usages) {
|
||||
if (usage.isAmbiguousImportUsage()) {
|
||||
ambiguousImportUsages += usage
|
||||
} else {
|
||||
simpleUsages += usage
|
||||
}
|
||||
}
|
||||
element.ambiguousImportUsages = ambiguousImportUsages
|
||||
|
||||
super.renameElement(element, newName, simpleUsages.toTypedArray(), listener)
|
||||
|
||||
usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() }
|
||||
}
|
||||
}
|
||||
+241
-4
@@ -5,12 +5,249 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Pass
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.refactoring.rename.*
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.refactoring.util.RefactoringUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.*
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsKotlinAware
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.liftToExpected
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import java.util.ArrayList
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
class RenameKotlinFunctionProcessor : RenameKotlinFunctionProcessorCompat() {
|
||||
class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() {
|
||||
|
||||
private val javaMethodProcessorInstance = RenameJavaMethodProcessor()
|
||||
|
||||
override fun canProcessElement(element: PsiElement): Boolean {
|
||||
return element is KtNamedFunction || (element is KtLightMethod && element.kotlinOrigin is KtNamedFunction) || element is FunctionWithSupersWrapper
|
||||
}
|
||||
|
||||
override fun isToSearchInComments(psiElement: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_METHOD
|
||||
|
||||
override fun setToSearchInComments(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_METHOD = enabled
|
||||
}
|
||||
|
||||
override fun isToSearchForTextOccurrences(element: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_METHOD
|
||||
|
||||
override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_METHOD = enabled
|
||||
}
|
||||
|
||||
private fun getJvmName(element: PsiElement): String? {
|
||||
val descriptor = (element.unwrapped as? KtFunction)?.unsafeResolveToDescriptor() as? FunctionDescriptor ?: return null
|
||||
return DescriptorUtils.getJvmName(descriptor)
|
||||
}
|
||||
|
||||
protected fun processFoundReferences(
|
||||
element: PsiElement,
|
||||
allReferences: Collection<PsiReference>
|
||||
): Collection<PsiReference> {
|
||||
return when {
|
||||
getJvmName(element) == null -> allReferences
|
||||
element is KtElement -> allReferences.filterIsInstance<KtReference>()
|
||||
element is KtLightElement<*, *> -> allReferences.filterNot { it is KtReference }
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun findCollisions(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
allRenames: Map<out PsiElement, String>,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
val declaration = element.unwrapped as? KtNamedFunction ?: return
|
||||
checkConflictsAndReplaceUsageInfos(element, allRenames, result)
|
||||
result += SmartList<UsageInfo>().also { collisions ->
|
||||
checkRedeclarations(declaration, newName, collisions)
|
||||
checkOriginalUsagesRetargeting(declaration, newName, result, collisions)
|
||||
checkNewNameUsagesRetargeting(declaration, newName, collisions)
|
||||
}
|
||||
}
|
||||
|
||||
class FunctionWithSupersWrapper(
|
||||
val originalDeclaration: KtNamedFunction,
|
||||
val supers: List<PsiElement>
|
||||
) : KtLightElement<KtNamedFunction, KtNamedFunction>, PsiNamedElement by originalDeclaration {
|
||||
override val kotlinOrigin: KtNamedFunction?
|
||||
get() = originalDeclaration
|
||||
override val clsDelegate: KtNamedFunction
|
||||
get() = originalDeclaration
|
||||
}
|
||||
|
||||
private fun substituteForExpectOrActual(element: PsiElement?) =
|
||||
(element?.namedUnwrappedElement as? KtNamedDeclaration)?.liftToExpected()
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor?): PsiElement? {
|
||||
substituteForExpectOrActual(element)?.let { return it }
|
||||
|
||||
val wrappedMethod = wrapPsiMethod(element) ?: return element
|
||||
|
||||
val deepestSuperMethods = findDeepestSuperMethodsKotlinAware(wrappedMethod)
|
||||
val substitutedJavaElement = when {
|
||||
deepestSuperMethods.isEmpty() -> return element
|
||||
wrappedMethod.isConstructor || deepestSuperMethods.size == 1 || element !is KtNamedFunction -> {
|
||||
javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor)
|
||||
}
|
||||
else -> {
|
||||
val chosenElements = checkSuperMethods(element, null, KotlinBundle.message("text.rename.as.part.of.phrase"))
|
||||
if (chosenElements.size > 1) FunctionWithSupersWrapper(element, chosenElements) else wrappedMethod
|
||||
}
|
||||
}
|
||||
|
||||
if (substitutedJavaElement is KtLightMethod && element is KtDeclaration) {
|
||||
return substitutedJavaElement.kotlinOrigin as? KtNamedFunction
|
||||
}
|
||||
|
||||
val canRename = try {
|
||||
PsiElementRenameHandler.canRename(element.project, editor, substitutedJavaElement)
|
||||
} catch (e: CommonRefactoringUtil.RefactoringErrorHintException) {
|
||||
false
|
||||
}
|
||||
|
||||
return if (canRename) substitutedJavaElement else element
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor, renameCallback: Pass<PsiElement>) {
|
||||
fun preprocessAndPass(substitutedJavaElement: PsiElement) {
|
||||
val elementToProcess = if (substitutedJavaElement is KtLightMethod && element is KtDeclaration) {
|
||||
substitutedJavaElement.kotlinOrigin as? KtNamedFunction
|
||||
} else {
|
||||
substitutedJavaElement
|
||||
}
|
||||
renameCallback.pass(elementToProcess)
|
||||
}
|
||||
|
||||
substituteForExpectOrActual(element)?.let { return preprocessAndPass(it) }
|
||||
|
||||
val wrappedMethod = wrapPsiMethod(element)
|
||||
val deepestSuperMethods = if (wrappedMethod != null) {
|
||||
findDeepestSuperMethodsKotlinAware(wrappedMethod)
|
||||
} else {
|
||||
findDeepestSuperMethodsNoWrapping(element)
|
||||
}
|
||||
when {
|
||||
deepestSuperMethods.isEmpty() -> preprocessAndPass(element)
|
||||
wrappedMethod != null && (wrappedMethod.isConstructor || element !is KtNamedFunction) -> {
|
||||
javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor, Pass(::preprocessAndPass))
|
||||
}
|
||||
else -> {
|
||||
val declaration = element.unwrapped as? KtNamedFunction ?: return
|
||||
checkSuperMethodsWithPopup(declaration, deepestSuperMethods.toList(), RefactoringBundle.message("rename.title"), editor) {
|
||||
preprocessAndPass(if (it.size > 1) FunctionWithSupersWrapper(declaration, it) else wrappedMethod ?: element)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createRenameDialog(
|
||||
project: Project,
|
||||
element: PsiElement,
|
||||
nameSuggestionContext: PsiElement?,
|
||||
editor: Editor?
|
||||
): RenameDialog {
|
||||
val elementForDialog = (element as? FunctionWithSupersWrapper)?.originalDeclaration ?: element
|
||||
return object : RenameDialog(project, elementForDialog, nameSuggestionContext, editor) {
|
||||
override fun createRenameProcessor(newName: String) =
|
||||
RenameProcessor(getProject(), element, newName, isSearchInComments, isSearchInNonJavaFiles)
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
super.prepareRenaming(element, newName, allRenames, scope)
|
||||
|
||||
if (element is KtLightMethod && getJvmName(element) == null) {
|
||||
(element.kotlinOrigin as? KtNamedFunction)?.let { allRenames[it] = newName }
|
||||
}
|
||||
if (element is FunctionWithSupersWrapper) {
|
||||
allRenames.remove(element)
|
||||
}
|
||||
val originalName = (element.unwrapped as? KtNamedFunction)?.name ?: return
|
||||
for (declaration in ((element as? FunctionWithSupersWrapper)?.supers ?: listOf(element))) {
|
||||
val psiMethod = wrapPsiMethod(declaration) ?: continue
|
||||
allRenames[declaration] = newName
|
||||
val baseName = psiMethod.name
|
||||
val newBaseName = if (KotlinTypeMapper.InternalNameMapper.demangleInternalName(baseName) == originalName) {
|
||||
KotlinTypeMapper.InternalNameMapper.mangleInternalName(
|
||||
newName,
|
||||
KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix(baseName)!!
|
||||
)
|
||||
} else newName
|
||||
if (psiMethod.containingClass != null) {
|
||||
psiMethod.forEachOverridingMethod(scope) {
|
||||
val overrider = (it as? PsiMirrorElement)?.prototype as? PsiMethod ?: it
|
||||
|
||||
if (overrider is SyntheticElement) return@forEachOverridingMethod true
|
||||
|
||||
val overriderName = overrider.name
|
||||
val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, baseName, newBaseName)
|
||||
if (newOverriderName != null) {
|
||||
RenameProcessor.assertNonCompileElement(overrider)
|
||||
allRenames[overrider] = newOverriderName
|
||||
}
|
||||
return@forEachOverridingMethod true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun renameElement(element: PsiElement, newName: String, usages: Array<UsageInfo>, listener: RefactoringElementListener?) {
|
||||
val simpleUsages = ArrayList<UsageInfo>(usages.size)
|
||||
val ambiguousImportUsages = SmartList<UsageInfo>()
|
||||
ForeignUsagesRenameProcessor.processAll(element, newName, usages, fallbackHandler = { usage ->
|
||||
if (usage is LostDefaultValuesInOverridingFunctionUsageInfo) {
|
||||
usage.apply()
|
||||
return@processAll
|
||||
}
|
||||
|
||||
if (usage.isAmbiguousImportUsage()) {
|
||||
ambiguousImportUsages += usage
|
||||
} else {
|
||||
if (!renameMangledUsageIfPossible(usage, element, newName)) {
|
||||
simpleUsages += usage
|
||||
}
|
||||
}
|
||||
})
|
||||
element.ambiguousImportUsages = ambiguousImportUsages
|
||||
|
||||
RenameUtil.doRenameGenericNamedElement(element, newName, simpleUsages.toTypedArray(), listener)
|
||||
|
||||
usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() }
|
||||
|
||||
(element.unwrapped as? KtNamedDeclaration)?.let(::dropOverrideKeywordIfNecessary)
|
||||
}
|
||||
|
||||
private fun wrapPsiMethod(element: PsiElement?): PsiMethod? = when (element) {
|
||||
is PsiMethod -> element
|
||||
is KtNamedFunction, is KtSecondaryConstructor -> runReadAction {
|
||||
LightClassUtil.getLightClassMethod(element as KtFunction)
|
||||
}
|
||||
else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
}
|
||||
|
||||
override fun findReferences(
|
||||
element: PsiElement,
|
||||
|
||||
-250
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Pass
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.refactoring.rename.*
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.refactoring.util.RefactoringUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.demangleInternalName
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.mangleInternalName
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.*
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsKotlinAware
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.liftToExpected
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import java.util.*
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class RenameKotlinFunctionProcessorCompat : RenameKotlinPsiProcessor() {
|
||||
private val javaMethodProcessorInstance = RenameJavaMethodProcessor()
|
||||
|
||||
override fun canProcessElement(element: PsiElement): Boolean {
|
||||
return element is KtNamedFunction || (element is KtLightMethod && element.kotlinOrigin is KtNamedFunction) || element is FunctionWithSupersWrapper
|
||||
}
|
||||
|
||||
override fun isToSearchInComments(psiElement: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_METHOD
|
||||
|
||||
override fun setToSearchInComments(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_METHOD = enabled
|
||||
}
|
||||
|
||||
override fun isToSearchForTextOccurrences(element: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_METHOD
|
||||
|
||||
override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_METHOD = enabled
|
||||
}
|
||||
|
||||
private fun getJvmName(element: PsiElement): String? {
|
||||
val descriptor = (element.unwrapped as? KtFunction)?.unsafeResolveToDescriptor() as? FunctionDescriptor ?: return null
|
||||
return DescriptorUtils.getJvmName(descriptor)
|
||||
}
|
||||
|
||||
protected fun processFoundReferences(
|
||||
element: PsiElement,
|
||||
allReferences: Collection<PsiReference>
|
||||
): Collection<PsiReference> {
|
||||
return when {
|
||||
getJvmName(element) == null -> allReferences
|
||||
element is KtElement -> allReferences.filterIsInstance<KtReference>()
|
||||
element is KtLightElement<*, *> -> allReferences.filterNot { it is KtReference }
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun findCollisions(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
allRenames: Map<out PsiElement, String>,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
val declaration = element.unwrapped as? KtNamedFunction ?: return
|
||||
checkConflictsAndReplaceUsageInfos(element, allRenames, result)
|
||||
result += SmartList<UsageInfo>().also { collisions ->
|
||||
checkRedeclarations(declaration, newName, collisions)
|
||||
checkOriginalUsagesRetargeting(declaration, newName, result, collisions)
|
||||
checkNewNameUsagesRetargeting(declaration, newName, collisions)
|
||||
}
|
||||
}
|
||||
|
||||
class FunctionWithSupersWrapper(
|
||||
val originalDeclaration: KtNamedFunction,
|
||||
val supers: List<PsiElement>
|
||||
) : KtLightElement<KtNamedFunction, KtNamedFunction>, PsiNamedElement by originalDeclaration {
|
||||
override val kotlinOrigin: KtNamedFunction?
|
||||
get() = originalDeclaration
|
||||
override val clsDelegate: KtNamedFunction
|
||||
get() = originalDeclaration
|
||||
}
|
||||
|
||||
private fun substituteForExpectOrActual(element: PsiElement?) =
|
||||
(element?.namedUnwrappedElement as? KtNamedDeclaration)?.liftToExpected()
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor?): PsiElement? {
|
||||
substituteForExpectOrActual(element)?.let { return it }
|
||||
|
||||
val wrappedMethod = wrapPsiMethod(element) ?: return element
|
||||
|
||||
val deepestSuperMethods = findDeepestSuperMethodsKotlinAware(wrappedMethod)
|
||||
val substitutedJavaElement = when {
|
||||
deepestSuperMethods.isEmpty() -> return element
|
||||
wrappedMethod.isConstructor || deepestSuperMethods.size == 1 || element !is KtNamedFunction -> {
|
||||
javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor)
|
||||
}
|
||||
else -> {
|
||||
val chosenElements = checkSuperMethods(element, null, KotlinBundle.message("text.rename.as.part.of.phrase"))
|
||||
if (chosenElements.size > 1) FunctionWithSupersWrapper(element, chosenElements) else wrappedMethod
|
||||
}
|
||||
}
|
||||
|
||||
if (substitutedJavaElement is KtLightMethod && element is KtDeclaration) {
|
||||
return substitutedJavaElement.kotlinOrigin as? KtNamedFunction
|
||||
}
|
||||
|
||||
val canRename = try {
|
||||
PsiElementRenameHandler.canRename(element.project, editor, substitutedJavaElement)
|
||||
} catch (e: CommonRefactoringUtil.RefactoringErrorHintException) {
|
||||
false
|
||||
}
|
||||
|
||||
return if (canRename) substitutedJavaElement else element
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor, renameCallback: Pass<PsiElement>) {
|
||||
fun preprocessAndPass(substitutedJavaElement: PsiElement) {
|
||||
val elementToProcess = if (substitutedJavaElement is KtLightMethod && element is KtDeclaration) {
|
||||
substitutedJavaElement.kotlinOrigin as? KtNamedFunction
|
||||
} else {
|
||||
substitutedJavaElement
|
||||
}
|
||||
renameCallback.pass(elementToProcess)
|
||||
}
|
||||
|
||||
substituteForExpectOrActual(element)?.let { return preprocessAndPass(it) }
|
||||
|
||||
val wrappedMethod = wrapPsiMethod(element)
|
||||
val deepestSuperMethods = if (wrappedMethod != null) {
|
||||
findDeepestSuperMethodsKotlinAware(wrappedMethod)
|
||||
} else {
|
||||
findDeepestSuperMethodsNoWrapping(element)
|
||||
}
|
||||
when {
|
||||
deepestSuperMethods.isEmpty() -> preprocessAndPass(element)
|
||||
wrappedMethod != null && (wrappedMethod.isConstructor || element !is KtNamedFunction) -> {
|
||||
javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor, Pass(::preprocessAndPass))
|
||||
}
|
||||
else -> {
|
||||
val declaration = element.unwrapped as? KtNamedFunction ?: return
|
||||
checkSuperMethodsWithPopup(declaration, deepestSuperMethods.toList(), RefactoringBundle.message("rename.title"), editor) {
|
||||
preprocessAndPass(if (it.size > 1) FunctionWithSupersWrapper(declaration, it) else wrappedMethod ?: element)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createRenameDialog(
|
||||
project: Project,
|
||||
element: PsiElement,
|
||||
nameSuggestionContext: PsiElement?,
|
||||
editor: Editor?
|
||||
): RenameDialog {
|
||||
val elementForDialog = (element as? FunctionWithSupersWrapper)?.originalDeclaration ?: element
|
||||
return object : RenameDialog(project, elementForDialog, nameSuggestionContext, editor) {
|
||||
override fun createRenameProcessor(newName: String) =
|
||||
RenameProcessor(getProject(), element, newName, isSearchInComments, isSearchInNonJavaFiles)
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
super.prepareRenaming(element, newName, allRenames, scope)
|
||||
|
||||
if (element is KtLightMethod && getJvmName(element) == null) {
|
||||
(element.kotlinOrigin as? KtNamedFunction)?.let { allRenames[it] = newName }
|
||||
}
|
||||
if (element is FunctionWithSupersWrapper) {
|
||||
allRenames.remove(element)
|
||||
}
|
||||
val originalName = (element.unwrapped as? KtNamedFunction)?.name ?: return
|
||||
for (declaration in ((element as? FunctionWithSupersWrapper)?.supers ?: listOf(element))) {
|
||||
val psiMethod = wrapPsiMethod(declaration) ?: continue
|
||||
allRenames[declaration] = newName
|
||||
val baseName = psiMethod.name
|
||||
val newBaseName = if (demangleInternalName(baseName) == originalName) {
|
||||
mangleInternalName(newName, getModuleNameSuffix(baseName)!!)
|
||||
} else newName
|
||||
if (psiMethod.containingClass != null) {
|
||||
psiMethod.forEachOverridingMethod(scope) {
|
||||
val overrider = (it as? PsiMirrorElement)?.prototype as? PsiMethod ?: it
|
||||
|
||||
if (overrider is SyntheticElement) return@forEachOverridingMethod true
|
||||
|
||||
val overriderName = overrider.name
|
||||
val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, baseName, newBaseName)
|
||||
if (newOverriderName != null) {
|
||||
RenameProcessor.assertNonCompileElement(overrider)
|
||||
allRenames[overrider] = newOverriderName
|
||||
}
|
||||
return@forEachOverridingMethod true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun renameElement(element: PsiElement, newName: String, usages: Array<UsageInfo>, listener: RefactoringElementListener?) {
|
||||
val simpleUsages = ArrayList<UsageInfo>(usages.size)
|
||||
val ambiguousImportUsages = SmartList<UsageInfo>()
|
||||
ForeignUsagesRenameProcessor.processAll(element, newName, usages, fallbackHandler = { usage ->
|
||||
if (usage is LostDefaultValuesInOverridingFunctionUsageInfo) {
|
||||
usage.apply()
|
||||
return@processAll
|
||||
}
|
||||
|
||||
if (usage.isAmbiguousImportUsage()) {
|
||||
ambiguousImportUsages += usage
|
||||
} else {
|
||||
if (!renameMangledUsageIfPossible(usage, element, newName)) {
|
||||
simpleUsages += usage
|
||||
}
|
||||
}
|
||||
})
|
||||
element.ambiguousImportUsages = ambiguousImportUsages
|
||||
|
||||
RenameUtil.doRenameGenericNamedElement(element, newName, simpleUsages.toTypedArray(), listener)
|
||||
|
||||
usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() }
|
||||
|
||||
(element.unwrapped as? KtNamedDeclaration)?.let(::dropOverrideKeywordIfNecessary)
|
||||
}
|
||||
|
||||
private fun wrapPsiMethod(element: PsiElement?): PsiMethod? = when (element) {
|
||||
is PsiMethod -> element
|
||||
is KtNamedFunction, is KtSecondaryConstructor -> runReadAction {
|
||||
LightClassUtil.getLightClassMethod(element as KtFunction)
|
||||
}
|
||||
else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
}
|
||||
}
|
||||
+393
-10
@@ -5,34 +5,417 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.navigation.NavigationItem
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.util.Pass
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.refactoring.rename.RenameProcessor
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||
import com.intellij.refactoring.util.RefactoringUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.usageView.UsageViewUtil
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.propertyNameByAccessor
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
|
||||
import org.jetbrains.kotlin.idea.core.isEnumCompanionPropertyWithEntryConflict
|
||||
import org.jetbrains.kotlin.idea.core.unquote
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
|
||||
import org.jetbrains.kotlin.idea.refactoring.checkSuperMethodsWithPopup
|
||||
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
|
||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findPropertyByName
|
||||
import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.util.findCallableMemberBySignature
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
class RenameKotlinPropertyProcessor : RenameKotlinPropertyProcessorCompat() {
|
||||
class RenameKotlinPropertyProcessor : RenameKotlinPsiProcessor() {
|
||||
|
||||
override fun canProcessElement(element: PsiElement): Boolean {
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement
|
||||
return namedUnwrappedElement is KtProperty || namedUnwrappedElement is PropertyMethodWrapper ||
|
||||
(namedUnwrappedElement is KtParameter && namedUnwrappedElement.hasValOrVar())
|
||||
}
|
||||
|
||||
override fun isToSearchInComments(psiElement: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_FIELD
|
||||
|
||||
override fun setToSearchInComments(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_FIELD = enabled
|
||||
}
|
||||
|
||||
override fun isToSearchForTextOccurrences(element: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_FIELD
|
||||
|
||||
override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_FIELD = enabled
|
||||
}
|
||||
|
||||
private fun getJvmNames(element: PsiElement): Pair<String?, String?> {
|
||||
val descriptor = (element.unwrapped as? KtDeclaration)?.unsafeResolveToDescriptor() as? PropertyDescriptor ?: return null to null
|
||||
val getterName = descriptor.getter?.let { DescriptorUtils.getJvmName(it) }
|
||||
val setterName = descriptor.setter?.let { DescriptorUtils.getJvmName(it) }
|
||||
return getterName to setterName
|
||||
}
|
||||
|
||||
protected fun processFoundReferences(
|
||||
element: PsiElement,
|
||||
allReferences: Collection<PsiReference>
|
||||
): Collection<PsiReference> {
|
||||
val references = allReferences.filterNot { it is KtDestructuringDeclarationReference }
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(element)
|
||||
return when {
|
||||
getterJvmName == null && setterJvmName == null -> references
|
||||
element is KtElement -> references.filter {
|
||||
it is KtReference || (getterJvmName == null && (it.resolve() as? PsiNamedElement)?.name != setterJvmName) || (setterJvmName == null && (it.resolve() as? PsiNamedElement)?.name != getterJvmName)
|
||||
}
|
||||
element is KtLightDeclaration<*, *> -> {
|
||||
val name = element.name
|
||||
if (name == getterJvmName || name == setterJvmName) references.filterNot { it is KtReference } else references
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAccidentalOverrides(
|
||||
declaration: KtNamedDeclaration,
|
||||
newName: String,
|
||||
descriptor: VariableDescriptor,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
fun reportAccidentalOverride(candidate: PsiNamedElement) {
|
||||
val what = UsageViewUtil.getType(declaration).capitalize()
|
||||
val withWhat = candidate.renderDescription()
|
||||
val where = candidate.representativeContainer()?.renderDescription() ?: return
|
||||
val message = KotlinBundle.message("text.0.will.clash.with.existing.1.in.2", what, withWhat, where)
|
||||
result += BasicUnresolvableCollisionUsageInfo(candidate, candidate, message)
|
||||
}
|
||||
|
||||
if (descriptor !is PropertyDescriptor) return
|
||||
val initialClass = declaration.containingClassOrObject ?: return
|
||||
val initialClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return
|
||||
|
||||
val prototype = object : PropertyDescriptor by descriptor {
|
||||
override fun getName() = Name.guessByFirstCharacter(newName)
|
||||
}
|
||||
|
||||
DFS.dfs(
|
||||
listOf(initialClassDescriptor),
|
||||
DFS.Neighbors<ClassDescriptor> { DescriptorUtils.getSuperclassDescriptors(it) },
|
||||
object : DFS.AbstractNodeHandler<ClassDescriptor, Unit>() {
|
||||
override fun beforeChildren(current: ClassDescriptor): Boolean {
|
||||
if (current == initialClassDescriptor) return true
|
||||
(current.findCallableMemberBySignature(prototype))?.let { candidateDescriptor ->
|
||||
val candidate = candidateDescriptor.source.getPsi() as? PsiNamedElement ?: return false
|
||||
reportAccidentalOverride(candidate)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun result() {
|
||||
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (!declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
|
||||
val initialPsiClass = initialClass.toLightClass() ?: return
|
||||
val prototypes = declaration.toLightMethods().mapNotNull {
|
||||
it as KtLightMethod
|
||||
val methodName = accessorNameByPropertyName(newName, it) ?: return@mapNotNull null
|
||||
object : KtLightMethod by it {
|
||||
override fun getName() = methodName
|
||||
}
|
||||
}
|
||||
DFS.dfs(
|
||||
listOf(initialPsiClass),
|
||||
DFS.Neighbors<PsiClass> { DirectClassInheritorsSearch.search(it) },
|
||||
object : DFS.AbstractNodeHandler<PsiClass, Unit>() {
|
||||
override fun beforeChildren(current: PsiClass): Boolean {
|
||||
if (current == initialPsiClass) return true
|
||||
|
||||
if (current is KtLightClass) {
|
||||
val property = current.kotlinOrigin?.findPropertyByName(newName) ?: return true
|
||||
reportAccidentalOverride(property)
|
||||
return false
|
||||
}
|
||||
|
||||
for (psiMethod in prototypes) {
|
||||
current.findMethodBySignature(psiMethod, false)?.let {
|
||||
val candidate = it.unwrapped as? PsiNamedElement ?: return true
|
||||
reportAccidentalOverride(candidate)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun result() {
|
||||
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun findCollisions(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
allRenames: MutableMap<out PsiElement, String>,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return
|
||||
val resolutionFacade = declaration.getResolutionFacade()
|
||||
val descriptor = declaration.unsafeResolveToDescriptor(resolutionFacade) as VariableDescriptor
|
||||
|
||||
val collisions = SmartList<UsageInfo>()
|
||||
checkRedeclarations(declaration, newName, collisions, resolutionFacade, descriptor)
|
||||
checkAccidentalOverrides(declaration, newName, descriptor, collisions)
|
||||
checkOriginalUsagesRetargeting(declaration, newName, result, collisions)
|
||||
checkNewNameUsagesRetargeting(declaration, newName, collisions)
|
||||
result += collisions
|
||||
}
|
||||
|
||||
private fun chooseCallableToRename(callableDeclaration: KtCallableDeclaration): KtCallableDeclaration? {
|
||||
val deepestSuperDeclaration = findDeepestOverriddenDeclaration(callableDeclaration)
|
||||
if (deepestSuperDeclaration == null || deepestSuperDeclaration == callableDeclaration) {
|
||||
return callableDeclaration
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication()!!.isUnitTestMode) return deepestSuperDeclaration
|
||||
|
||||
val containsText: String? =
|
||||
deepestSuperDeclaration.fqName?.parent()?.asString() ?: (deepestSuperDeclaration.parent as? KtClassOrObject)?.name
|
||||
|
||||
val message = if (containsText != null)
|
||||
KotlinBundle.message("text.do.you.want.to.rename.base.property.from.0", containsText)
|
||||
else
|
||||
KotlinBundle.message("text.do.you.want.to.rename.base.property")
|
||||
|
||||
val result = Messages.showYesNoCancelDialog(
|
||||
deepestSuperDeclaration.project,
|
||||
message,
|
||||
KotlinBundle.message("text.rename.warning"),
|
||||
Messages.getQuestionIcon()
|
||||
)
|
||||
|
||||
return when (result) {
|
||||
Messages.YES -> deepestSuperDeclaration
|
||||
Messages.NO -> callableDeclaration
|
||||
else -> /* Cancel rename */ null
|
||||
}
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor?): PsiElement? {
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement ?: return null
|
||||
|
||||
val callableDeclaration = namedUnwrappedElement as? KtCallableDeclaration
|
||||
?: throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
|
||||
val declarationToRename = chooseCallableToRename(callableDeclaration) ?: return null
|
||||
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement)
|
||||
if (element is KtLightMethod) {
|
||||
val name = element.name
|
||||
if (element.name != getterJvmName && element.name != setterJvmName) return declarationToRename
|
||||
return declarationToRename.toLightMethods().firstOrNull { it.name == name }
|
||||
}
|
||||
|
||||
return declarationToRename
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor, renameCallback: Pass<PsiElement>) {
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement ?: return
|
||||
|
||||
val callableDeclaration = namedUnwrappedElement as? KtCallableDeclaration
|
||||
?: throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
|
||||
fun preprocessAndPass(substitutedJavaElement: PsiElement) {
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement)
|
||||
val elementToProcess = if (element is KtLightMethod) {
|
||||
val name = element.name
|
||||
if (element.name != getterJvmName && element.name != setterJvmName) {
|
||||
substitutedJavaElement
|
||||
} else {
|
||||
substitutedJavaElement.toLightMethods().firstOrNull { it.name == name }
|
||||
}
|
||||
} else substitutedJavaElement
|
||||
renameCallback.pass(elementToProcess)
|
||||
}
|
||||
|
||||
val deepestSuperDeclaration = findDeepestOverriddenDeclaration(callableDeclaration)
|
||||
if (deepestSuperDeclaration == null || deepestSuperDeclaration == callableDeclaration) {
|
||||
return preprocessAndPass(callableDeclaration)
|
||||
}
|
||||
|
||||
val superPsiMethods = listOfNotNull(deepestSuperDeclaration.getRepresentativeLightMethod())
|
||||
checkSuperMethodsWithPopup(callableDeclaration, superPsiMethods, RefactoringBundle.message("rename.title"), editor) {
|
||||
preprocessAndPass(if (it.size > 1) deepestSuperDeclaration else callableDeclaration)
|
||||
}
|
||||
}
|
||||
|
||||
class PropertyMethodWrapper(private val propertyMethod: PsiMethod) : PsiNamedElement by propertyMethod,
|
||||
NavigationItem by propertyMethod {
|
||||
override fun getName() = propertyMethod.name
|
||||
override fun setName(name: String) = this
|
||||
override fun copy() = this
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
super.prepareRenaming(element, newName, allRenames, scope)
|
||||
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement
|
||||
val propertyMethods = when (namedUnwrappedElement) {
|
||||
is KtProperty -> runReadAction { LightClassUtil.getLightClassPropertyMethods(namedUnwrappedElement) }
|
||||
is KtParameter -> runReadAction { LightClassUtil.getLightClassPropertyMethods(namedUnwrappedElement) }
|
||||
else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
}
|
||||
|
||||
val newPropertyName = if (element is KtLightMethod) propertyNameByAccessor(newName, element) else newName
|
||||
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement)
|
||||
|
||||
val getter = propertyMethods.getter as? KtLightMethod
|
||||
val setter = propertyMethods.setter as? KtLightMethod
|
||||
if (newPropertyName != null
|
||||
&& getter != null && setter != null
|
||||
&& (element == getter || element == setter)
|
||||
&& propertyNameByAccessor(getter.name, getter) == propertyNameByAccessor(setter.name, setter)
|
||||
) {
|
||||
val accessorToRename = if (element == getter) setter else getter
|
||||
val newAccessorName = if (element == getter) JvmAbi.setterName(newPropertyName) else JvmAbi.getterName(newPropertyName)
|
||||
if (ApplicationManager.getApplication().isUnitTestMode || Messages.showYesNoDialog(
|
||||
KotlinBundle.message("text.do.you.want.to.rename.0.as.well", accessorToRename.name),
|
||||
RefactoringBundle.message("rename.title"),
|
||||
Messages.getQuestionIcon()
|
||||
) == Messages.YES
|
||||
) {
|
||||
allRenames[accessorToRename] = newAccessorName
|
||||
}
|
||||
}
|
||||
|
||||
for (propertyMethod in propertyMethods) {
|
||||
val mangledPropertyName = if (propertyMethod is KtLightMethod && propertyMethod.isMangled) {
|
||||
val suffix = KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix(propertyMethod.name)
|
||||
if (suffix != null && newPropertyName != null) KotlinTypeMapper.InternalNameMapper.mangleInternalName(
|
||||
newPropertyName,
|
||||
suffix
|
||||
) else null
|
||||
} else null
|
||||
val adjustedPropertyName = mangledPropertyName ?: newPropertyName
|
||||
if (element is KtDeclaration && adjustedPropertyName != null) {
|
||||
val wrapper = PropertyMethodWrapper(propertyMethod)
|
||||
when {
|
||||
JvmAbi.isGetterName(propertyMethod.name) && getterJvmName == null ->
|
||||
allRenames[wrapper] = JvmAbi.getterName(adjustedPropertyName)
|
||||
JvmAbi.isSetterName(propertyMethod.name) && setterJvmName == null ->
|
||||
allRenames[wrapper] = JvmAbi.setterName(adjustedPropertyName)
|
||||
}
|
||||
}
|
||||
addRenameElements(propertyMethod, (element as PsiNamedElement).name, adjustedPropertyName, allRenames, scope)
|
||||
}
|
||||
}
|
||||
|
||||
protected enum class UsageKind {
|
||||
SIMPLE_PROPERTY_USAGE,
|
||||
GETTER_USAGE,
|
||||
SETTER_USAGE
|
||||
}
|
||||
|
||||
private fun addRenameElements(
|
||||
psiMethod: PsiMethod?,
|
||||
oldName: String?,
|
||||
newName: String?,
|
||||
allRenames: MutableMap<PsiElement, String>,
|
||||
scope: SearchScope
|
||||
) {
|
||||
if (psiMethod == null) return
|
||||
|
||||
OverridingMethodsSearch.search(psiMethod, scope, true).forEach { overrider ->
|
||||
val overriderElement = overrider.namedUnwrappedElement
|
||||
|
||||
if (overriderElement != null && overriderElement !is SyntheticElement) {
|
||||
RenameProcessor.assertNonCompileElement(overriderElement)
|
||||
|
||||
val overriderName = overriderElement.name
|
||||
|
||||
if (overriderElement is PsiMethod) {
|
||||
if (newName != null && Name.isValidIdentifier(newName)) {
|
||||
val isGetter = overriderElement.parameterList.parametersCount == 0
|
||||
allRenames[overriderElement] = if (isGetter) JvmAbi.getterName(newName) else JvmAbi.setterName(newName)
|
||||
}
|
||||
} else {
|
||||
val demangledName =
|
||||
if (newName != null && overrider is KtLightMethod && overrider.isMangled) KotlinTypeMapper.InternalNameMapper.demangleInternalName(
|
||||
newName
|
||||
) else null
|
||||
val adjustedName = demangledName ?: newName
|
||||
val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, oldName, adjustedName)
|
||||
if (newOverriderName != null) {
|
||||
allRenames[overriderElement] = newOverriderName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findDeepestOverriddenDeclaration(declaration: KtCallableDeclaration): KtCallableDeclaration? {
|
||||
if (declaration.modifierList?.hasModifier(KtTokens.OVERRIDE_KEYWORD) == true) {
|
||||
val bindingContext = declaration.analyze()
|
||||
var descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
|
||||
if (descriptor is ValueParameterDescriptor) {
|
||||
descriptor = bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor]
|
||||
?: return declaration
|
||||
}
|
||||
|
||||
if (descriptor != null) {
|
||||
assert(descriptor is PropertyDescriptor) { "Property descriptor is expected" }
|
||||
|
||||
val supers = (descriptor as PropertyDescriptor).getDeepestSuperDeclarations()
|
||||
|
||||
// Take one of supers for now - API doesn't support substitute to several elements (IDEA-48796)
|
||||
val deepest = supers.first()
|
||||
if (deepest != descriptor) {
|
||||
val superPsiElement = DescriptorToSourceUtils.descriptorToDeclaration(deepest)
|
||||
return superPsiElement as? KtCallableDeclaration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun findReferences(
|
||||
element: PsiElement,
|
||||
|
||||
-407
@@ -1,407 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.navigation.NavigationItem
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.util.Pass
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import com.intellij.refactoring.RefactoringBundle
|
||||
import com.intellij.refactoring.rename.RenameProcessor
|
||||
import com.intellij.refactoring.util.RefactoringUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.usageView.UsageViewUtil
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.demangleInternalName
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.mangleInternalName
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
|
||||
import org.jetbrains.kotlin.idea.refactoring.checkSuperMethodsWithPopup
|
||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findPropertyByName
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.util.findCallableMemberBySignature
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class RenameKotlinPropertyProcessorCompat : RenameKotlinPsiProcessor() {
|
||||
override fun canProcessElement(element: PsiElement): Boolean {
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement
|
||||
return namedUnwrappedElement is KtProperty || namedUnwrappedElement is PropertyMethodWrapper ||
|
||||
(namedUnwrappedElement is KtParameter && namedUnwrappedElement.hasValOrVar())
|
||||
}
|
||||
|
||||
override fun isToSearchInComments(psiElement: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_FIELD
|
||||
|
||||
override fun setToSearchInComments(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_IN_COMMENTS_FOR_FIELD = enabled
|
||||
}
|
||||
|
||||
override fun isToSearchForTextOccurrences(element: PsiElement) = KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_FIELD
|
||||
|
||||
override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) {
|
||||
KotlinRefactoringSettings.instance.RENAME_SEARCH_FOR_TEXT_FOR_FIELD = enabled
|
||||
}
|
||||
|
||||
private fun getJvmNames(element: PsiElement): Pair<String?, String?> {
|
||||
val descriptor = (element.unwrapped as? KtDeclaration)?.unsafeResolveToDescriptor() as? PropertyDescriptor ?: return null to null
|
||||
val getterName = descriptor.getter?.let { DescriptorUtils.getJvmName(it) }
|
||||
val setterName = descriptor.setter?.let { DescriptorUtils.getJvmName(it) }
|
||||
return getterName to setterName
|
||||
}
|
||||
|
||||
protected fun processFoundReferences(
|
||||
element: PsiElement,
|
||||
allReferences: Collection<PsiReference>
|
||||
): Collection<PsiReference> {
|
||||
val references = allReferences.filterNot { it is KtDestructuringDeclarationReference }
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(element)
|
||||
return when {
|
||||
getterJvmName == null && setterJvmName == null -> references
|
||||
element is KtElement -> references.filter {
|
||||
it is KtReference || (getterJvmName == null && (it.resolve() as? PsiNamedElement)?.name != setterJvmName) || (setterJvmName == null && (it.resolve() as? PsiNamedElement)?.name != getterJvmName)
|
||||
}
|
||||
element is KtLightDeclaration<*, *> -> {
|
||||
val name = element.name
|
||||
if (name == getterJvmName || name == setterJvmName) references.filterNot { it is KtReference } else references
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAccidentalOverrides(
|
||||
declaration: KtNamedDeclaration,
|
||||
newName: String,
|
||||
descriptor: VariableDescriptor,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
fun reportAccidentalOverride(candidate: PsiNamedElement) {
|
||||
val what = UsageViewUtil.getType(declaration).capitalize()
|
||||
val withWhat = candidate.renderDescription()
|
||||
val where = candidate.representativeContainer()?.renderDescription() ?: return
|
||||
val message = KotlinBundle.message("text.0.will.clash.with.existing.1.in.2", what, withWhat, where)
|
||||
result += BasicUnresolvableCollisionUsageInfo(candidate, candidate, message)
|
||||
}
|
||||
|
||||
if (descriptor !is PropertyDescriptor) return
|
||||
val initialClass = declaration.containingClassOrObject ?: return
|
||||
val initialClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return
|
||||
|
||||
val prototype = object : PropertyDescriptor by descriptor {
|
||||
override fun getName() = Name.guessByFirstCharacter(newName)
|
||||
}
|
||||
|
||||
DFS.dfs(
|
||||
listOf(initialClassDescriptor),
|
||||
DFS.Neighbors<ClassDescriptor> { DescriptorUtils.getSuperclassDescriptors(it) },
|
||||
object : DFS.AbstractNodeHandler<ClassDescriptor, Unit>() {
|
||||
override fun beforeChildren(current: ClassDescriptor): Boolean {
|
||||
if (current == initialClassDescriptor) return true
|
||||
(current.findCallableMemberBySignature(prototype))?.let { candidateDescriptor ->
|
||||
val candidate = candidateDescriptor.source.getPsi() as? PsiNamedElement ?: return false
|
||||
reportAccidentalOverride(candidate)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun result() {
|
||||
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (!declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
|
||||
val initialPsiClass = initialClass.toLightClass() ?: return
|
||||
val prototypes = declaration.toLightMethods().mapNotNull {
|
||||
it as KtLightMethod
|
||||
val methodName = accessorNameByPropertyName(newName, it) ?: return@mapNotNull null
|
||||
object : KtLightMethod by it {
|
||||
override fun getName() = methodName
|
||||
}
|
||||
}
|
||||
DFS.dfs(
|
||||
listOf(initialPsiClass),
|
||||
DFS.Neighbors<PsiClass> { DirectClassInheritorsSearch.search(it) },
|
||||
object : DFS.AbstractNodeHandler<PsiClass, Unit>() {
|
||||
override fun beforeChildren(current: PsiClass): Boolean {
|
||||
if (current == initialPsiClass) return true
|
||||
|
||||
if (current is KtLightClass) {
|
||||
val property = current.kotlinOrigin?.findPropertyByName(newName) ?: return true
|
||||
reportAccidentalOverride(property)
|
||||
return false
|
||||
}
|
||||
|
||||
for (psiMethod in prototypes) {
|
||||
current.findMethodBySignature(psiMethod, false)?.let {
|
||||
val candidate = it.unwrapped as? PsiNamedElement ?: return true
|
||||
reportAccidentalOverride(candidate)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun result() {
|
||||
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun findCollisions(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
allRenames: MutableMap<out PsiElement, String>,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return
|
||||
val resolutionFacade = declaration.getResolutionFacade()
|
||||
val descriptor = declaration.unsafeResolveToDescriptor(resolutionFacade) as VariableDescriptor
|
||||
|
||||
val collisions = SmartList<UsageInfo>()
|
||||
checkRedeclarations(declaration, newName, collisions, resolutionFacade, descriptor)
|
||||
checkAccidentalOverrides(declaration, newName, descriptor, collisions)
|
||||
checkOriginalUsagesRetargeting(declaration, newName, result, collisions)
|
||||
checkNewNameUsagesRetargeting(declaration, newName, collisions)
|
||||
result += collisions
|
||||
}
|
||||
|
||||
private fun chooseCallableToRename(callableDeclaration: KtCallableDeclaration): KtCallableDeclaration? {
|
||||
val deepestSuperDeclaration = findDeepestOverriddenDeclaration(callableDeclaration)
|
||||
if (deepestSuperDeclaration == null || deepestSuperDeclaration == callableDeclaration) {
|
||||
return callableDeclaration
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication()!!.isUnitTestMode) return deepestSuperDeclaration
|
||||
|
||||
val containsText: String? =
|
||||
deepestSuperDeclaration.fqName?.parent()?.asString() ?: (deepestSuperDeclaration.parent as? KtClassOrObject)?.name
|
||||
|
||||
val message = if (containsText != null)
|
||||
KotlinBundle.message("text.do.you.want.to.rename.base.property.from.0", containsText)
|
||||
else
|
||||
KotlinBundle.message("text.do.you.want.to.rename.base.property")
|
||||
|
||||
val result = Messages.showYesNoCancelDialog(
|
||||
deepestSuperDeclaration.project,
|
||||
message,
|
||||
KotlinBundle.message("text.rename.warning"),
|
||||
Messages.getQuestionIcon()
|
||||
)
|
||||
|
||||
return when (result) {
|
||||
Messages.YES -> deepestSuperDeclaration
|
||||
Messages.NO -> callableDeclaration
|
||||
else -> /* Cancel rename */ null
|
||||
}
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor?): PsiElement? {
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement ?: return null
|
||||
|
||||
val callableDeclaration = namedUnwrappedElement as? KtCallableDeclaration
|
||||
?: throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
|
||||
val declarationToRename = chooseCallableToRename(callableDeclaration) ?: return null
|
||||
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement)
|
||||
if (element is KtLightMethod) {
|
||||
val name = element.name
|
||||
if (element.name != getterJvmName && element.name != setterJvmName) return declarationToRename
|
||||
return declarationToRename.toLightMethods().firstOrNull { it.name == name }
|
||||
}
|
||||
|
||||
return declarationToRename
|
||||
}
|
||||
|
||||
override fun substituteElementToRename(element: PsiElement, editor: Editor, renameCallback: Pass<PsiElement>) {
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement ?: return
|
||||
|
||||
val callableDeclaration = namedUnwrappedElement as? KtCallableDeclaration
|
||||
?: throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
|
||||
fun preprocessAndPass(substitutedJavaElement: PsiElement) {
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement)
|
||||
val elementToProcess = if (element is KtLightMethod) {
|
||||
val name = element.name
|
||||
if (element.name != getterJvmName && element.name != setterJvmName) {
|
||||
substitutedJavaElement
|
||||
} else {
|
||||
substitutedJavaElement.toLightMethods().firstOrNull { it.name == name }
|
||||
}
|
||||
} else substitutedJavaElement
|
||||
renameCallback.pass(elementToProcess)
|
||||
}
|
||||
|
||||
val deepestSuperDeclaration = findDeepestOverriddenDeclaration(callableDeclaration)
|
||||
if (deepestSuperDeclaration == null || deepestSuperDeclaration == callableDeclaration) {
|
||||
return preprocessAndPass(callableDeclaration)
|
||||
}
|
||||
|
||||
val superPsiMethods = listOfNotNull(deepestSuperDeclaration.getRepresentativeLightMethod())
|
||||
checkSuperMethodsWithPopup(callableDeclaration, superPsiMethods, RefactoringBundle.message("rename.title"), editor) {
|
||||
preprocessAndPass(if (it.size > 1) deepestSuperDeclaration else callableDeclaration)
|
||||
}
|
||||
}
|
||||
|
||||
class PropertyMethodWrapper(private val propertyMethod: PsiMethod) : PsiNamedElement by propertyMethod,
|
||||
NavigationItem by propertyMethod {
|
||||
override fun getName() = propertyMethod.name
|
||||
override fun setName(name: String) = this
|
||||
override fun copy() = this
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
super.prepareRenaming(element, newName, allRenames, scope)
|
||||
|
||||
val namedUnwrappedElement = element.namedUnwrappedElement
|
||||
val propertyMethods = when (namedUnwrappedElement) {
|
||||
is KtProperty -> runReadAction { LightClassUtil.getLightClassPropertyMethods(namedUnwrappedElement) }
|
||||
is KtParameter -> runReadAction { LightClassUtil.getLightClassPropertyMethods(namedUnwrappedElement) }
|
||||
else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
}
|
||||
|
||||
val newPropertyName = if (element is KtLightMethod) propertyNameByAccessor(newName, element) else newName
|
||||
|
||||
val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement)
|
||||
|
||||
val getter = propertyMethods.getter as? KtLightMethod
|
||||
val setter = propertyMethods.setter as? KtLightMethod
|
||||
if (newPropertyName != null
|
||||
&& getter != null && setter != null
|
||||
&& (element == getter || element == setter)
|
||||
&& propertyNameByAccessor(getter.name, getter) == propertyNameByAccessor(setter.name, setter)
|
||||
) {
|
||||
val accessorToRename = if (element == getter) setter else getter
|
||||
val newAccessorName = if (element == getter) JvmAbi.setterName(newPropertyName) else JvmAbi.getterName(newPropertyName)
|
||||
if (ApplicationManager.getApplication().isUnitTestMode || Messages.showYesNoDialog(
|
||||
KotlinBundle.message("text.do.you.want.to.rename.0.as.well", accessorToRename.name),
|
||||
RefactoringBundle.message("rename.title"),
|
||||
Messages.getQuestionIcon()
|
||||
) == Messages.YES
|
||||
) {
|
||||
allRenames[accessorToRename] = newAccessorName
|
||||
}
|
||||
}
|
||||
|
||||
for (propertyMethod in propertyMethods) {
|
||||
val mangledPropertyName = if (propertyMethod is KtLightMethod && propertyMethod.isMangled) {
|
||||
val suffix = getModuleNameSuffix(propertyMethod.name)
|
||||
if (suffix != null && newPropertyName != null) mangleInternalName(newPropertyName, suffix) else null
|
||||
} else null
|
||||
val adjustedPropertyName = mangledPropertyName ?: newPropertyName
|
||||
if (element is KtDeclaration && adjustedPropertyName != null) {
|
||||
val wrapper = PropertyMethodWrapper(propertyMethod)
|
||||
when {
|
||||
JvmAbi.isGetterName(propertyMethod.name) && getterJvmName == null ->
|
||||
allRenames[wrapper] = JvmAbi.getterName(adjustedPropertyName)
|
||||
JvmAbi.isSetterName(propertyMethod.name) && setterJvmName == null ->
|
||||
allRenames[wrapper] = JvmAbi.setterName(adjustedPropertyName)
|
||||
}
|
||||
}
|
||||
addRenameElements(propertyMethod, (element as PsiNamedElement).name, adjustedPropertyName, allRenames, scope)
|
||||
}
|
||||
}
|
||||
|
||||
protected enum class UsageKind {
|
||||
SIMPLE_PROPERTY_USAGE,
|
||||
GETTER_USAGE,
|
||||
SETTER_USAGE
|
||||
}
|
||||
|
||||
private fun addRenameElements(
|
||||
psiMethod: PsiMethod?,
|
||||
oldName: String?,
|
||||
newName: String?,
|
||||
allRenames: MutableMap<PsiElement, String>,
|
||||
scope: SearchScope
|
||||
) {
|
||||
if (psiMethod == null) return
|
||||
|
||||
OverridingMethodsSearch.search(psiMethod, scope, true).forEach { overrider ->
|
||||
val overriderElement = overrider.namedUnwrappedElement
|
||||
|
||||
if (overriderElement != null && overriderElement !is SyntheticElement) {
|
||||
RenameProcessor.assertNonCompileElement(overriderElement)
|
||||
|
||||
val overriderName = overriderElement.name
|
||||
|
||||
if (overriderElement is PsiMethod) {
|
||||
if (newName != null && Name.isValidIdentifier(newName)) {
|
||||
val isGetter = overriderElement.parameterList.parametersCount == 0
|
||||
allRenames[overriderElement] = if (isGetter) JvmAbi.getterName(newName) else JvmAbi.setterName(newName)
|
||||
}
|
||||
} else {
|
||||
val demangledName =
|
||||
if (newName != null && overrider is KtLightMethod && overrider.isMangled) demangleInternalName(newName) else null
|
||||
val adjustedName = demangledName ?: newName
|
||||
val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, oldName, adjustedName)
|
||||
if (newOverriderName != null) {
|
||||
allRenames[overriderElement] = newOverriderName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findDeepestOverriddenDeclaration(declaration: KtCallableDeclaration): KtCallableDeclaration? {
|
||||
if (declaration.modifierList?.hasModifier(KtTokens.OVERRIDE_KEYWORD) == true) {
|
||||
val bindingContext = declaration.analyze()
|
||||
var descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
|
||||
if (descriptor is ValueParameterDescriptor) {
|
||||
descriptor = bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor]
|
||||
?: return declaration
|
||||
}
|
||||
|
||||
if (descriptor != null) {
|
||||
assert(descriptor is PropertyDescriptor) { "Property descriptor is expected" }
|
||||
|
||||
val supers = (descriptor as PropertyDescriptor).getDeepestSuperDeclarations()
|
||||
|
||||
// Take one of supers for now - API doesn't support substitute to several elements (IDEA-48796)
|
||||
val deepest = supers.first()
|
||||
if (deepest != descriptor) {
|
||||
val superPsiElement = DescriptorToSourceUtils.descriptorToDeclaration(deepest)
|
||||
return superPsiElement as? KtCallableDeclaration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,192 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.psi.util.PsiUtilCore
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||
import com.intellij.refactoring.rename.RenameUtil
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.references.getImportAlias
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinMethodReferencesSearchParameters
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
|
||||
import org.jetbrains.kotlin.idea.util.actualsForExpected
|
||||
import org.jetbrains.kotlin.idea.util.liftToExpected
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import java.util.ArrayList
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class RenameKotlinPsiProcessor : RenameKotlinPsiProcessorCompat() {
|
||||
abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() {
|
||||
|
||||
class MangledJavaRefUsageInfo(
|
||||
val manglingSuffix: String,
|
||||
element: PsiElement,
|
||||
ref: PsiReference,
|
||||
referenceElement: PsiElement
|
||||
) : MoveRenameUsageInfo(
|
||||
referenceElement,
|
||||
ref,
|
||||
ref.getRangeInElement().getStartOffset(),
|
||||
ref.getRangeInElement().getEndOffset(),
|
||||
element,
|
||||
false
|
||||
)
|
||||
|
||||
override fun canProcessElement(element: PsiElement): Boolean = element is KtNamedDeclaration
|
||||
|
||||
protected fun findReferences(
|
||||
element: PsiElement,
|
||||
searchParameters: KotlinReferencesSearchParameters
|
||||
): Collection<PsiReference> {
|
||||
val references = ReferencesSearch.search(searchParameters).toMutableSet()
|
||||
if (element is KtNamedFunction || (element is KtProperty && !element.isLocal) || (element is KtParameter && element.hasValOrVar())) {
|
||||
element.toLightMethods().flatMapTo(references) { method ->
|
||||
MethodReferencesSearch.search(
|
||||
KotlinMethodReferencesSearchParameters(
|
||||
method,
|
||||
kotlinOptions = KotlinReferencesSearchOptions(
|
||||
acceptImportAlias = false
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return references.filter {
|
||||
// have to filter so far as
|
||||
// - text-matched reference could be named as imported alias and found in ReferencesSearch
|
||||
// - MethodUsagesSearcher could create its own MethodReferencesSearchParameters regardless provided one
|
||||
it.element.getNonStrictParentOfType<KtImportDirective>() != null || it.getImportAlias() == null
|
||||
}
|
||||
}
|
||||
|
||||
override fun createUsageInfo(element: PsiElement, ref: PsiReference, referenceElement: PsiElement): UsageInfo {
|
||||
if (ref !is KtReference) {
|
||||
val targetElement = ref.resolve()
|
||||
if (targetElement is KtLightMethod && targetElement.isMangled) {
|
||||
KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix(targetElement.name)?.let {
|
||||
return MangledJavaRefUsageInfo(
|
||||
it,
|
||||
element,
|
||||
ref,
|
||||
referenceElement
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.createUsageInfo(element, ref, referenceElement)
|
||||
}
|
||||
|
||||
override fun getElementToSearchInStringsAndComments(element: PsiElement): PsiElement? {
|
||||
val unwrapped = element.unwrapped ?: return null
|
||||
if ((unwrapped is KtDeclaration) && KtPsiUtil.isLocal(unwrapped)) return null
|
||||
return element
|
||||
}
|
||||
|
||||
override fun getQualifiedNameAfterRename(element: PsiElement, newName: String, nonJava: Boolean): String? {
|
||||
if (!nonJava) return newName
|
||||
|
||||
val qualifiedName = when (element) {
|
||||
is KtNamedDeclaration -> element.fqName?.asString() ?: element.name
|
||||
is PsiClass -> element.qualifiedName ?: element.name
|
||||
else -> return null
|
||||
}
|
||||
return PsiUtilCore.getQualifiedNameAfterRename(qualifiedName, newName)
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
val safeNewName = newName.quoteIfNeeded()
|
||||
|
||||
if (!newName.isIdentifier()) {
|
||||
allRenames[element] = safeNewName
|
||||
}
|
||||
|
||||
val declaration = element.namedUnwrappedElement as? KtNamedDeclaration
|
||||
if (declaration != null) {
|
||||
declaration.liftToExpected()?.let { expectDeclaration ->
|
||||
allRenames[expectDeclaration] = safeNewName
|
||||
expectDeclaration.actualsForExpected().forEach { allRenames[it] = safeNewName }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected var PsiElement.ambiguousImportUsages: List<UsageInfo>? by UserDataProperty(Key.create("AMBIGUOUS_IMPORT_USAGES"))
|
||||
|
||||
protected fun UsageInfo.isAmbiguousImportUsage(): Boolean {
|
||||
val ref = reference as? PsiPolyVariantReference ?: return false
|
||||
val refElement = ref.element
|
||||
return refElement.parents
|
||||
.any { (it is KtImportDirective && !it.isAllUnder) || (it is PsiImportStaticStatement && !it.isOnDemand) } && ref.multiResolve(
|
||||
false
|
||||
).mapNotNullTo(HashSet()) { it.element?.unwrapped }.size > 1
|
||||
}
|
||||
|
||||
protected fun renameMangledUsageIfPossible(usage: UsageInfo, element: PsiElement, newName: String): Boolean {
|
||||
val chosenName = (if (usage is MangledJavaRefUsageInfo) {
|
||||
KotlinTypeMapper.InternalNameMapper.mangleInternalName(newName, usage.manglingSuffix)
|
||||
} else {
|
||||
val reference = usage.reference
|
||||
if (reference is KtReference) {
|
||||
if (element is KtLightMethod && element.isMangled) {
|
||||
KotlinTypeMapper.InternalNameMapper.demangleInternalName(newName)
|
||||
} else null
|
||||
} else null
|
||||
}) ?: return false
|
||||
usage.reference?.handleElementRename(chosenName)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun renameElement(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
usages: Array<UsageInfo>,
|
||||
listener: RefactoringElementListener?
|
||||
) {
|
||||
val simpleUsages = ArrayList<UsageInfo>(usages.size)
|
||||
ForeignUsagesRenameProcessor.processAll(element, newName, usages, fallbackHandler = { usage ->
|
||||
if (renameMangledUsageIfPossible(usage, element, newName)) return@processAll
|
||||
simpleUsages += usage
|
||||
})
|
||||
|
||||
RenameUtil.doRenameGenericNamedElement(element, newName, simpleUsages.toTypedArray(), listener)
|
||||
}
|
||||
|
||||
override fun getPostRenameCallback(element: PsiElement, newName: String, elementListener: RefactoringElementListener): Runnable? {
|
||||
return Runnable {
|
||||
element.ambiguousImportUsages?.forEach {
|
||||
val ref = it.reference as? PsiPolyVariantReference ?: return@forEach
|
||||
if (ref.multiResolve(false).isEmpty()) {
|
||||
if (!renameMangledUsageIfPossible(it, element, newName)) {
|
||||
ref.handleElementRename(newName)
|
||||
}
|
||||
} else {
|
||||
ref.element.getStrictParentOfType<KtImportDirective>()?.let { importDirective ->
|
||||
val fqName = importDirective.importedFqName!!
|
||||
val newFqName = fqName.parent().child(Name.identifier(newName))
|
||||
val importList = importDirective.parent as KtImportList
|
||||
if (importList.imports.none { directive -> directive.importedFqName == newFqName }) {
|
||||
val newImportDirective = KtPsiFactory(element).createImportDirective(ImportPath(newFqName, false))
|
||||
importDirective.parent.addAfter(newImportDirective, importDirective)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
element.ambiguousImportUsages = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun findReferences(
|
||||
element: PsiElement,
|
||||
|
||||
-195
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.psi.util.PsiUtilCore
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||
import com.intellij.refactoring.rename.RenameUtil
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.references.getImportAlias
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinMethodReferencesSearchParameters
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
|
||||
import org.jetbrains.kotlin.idea.util.actualsForExpected
|
||||
import org.jetbrains.kotlin.idea.util.liftToExpected
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import java.util.ArrayList
|
||||
import kotlin.collections.*
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
abstract class RenameKotlinPsiProcessorCompat : RenamePsiElementProcessor() {
|
||||
class MangledJavaRefUsageInfo(
|
||||
val manglingSuffix: String,
|
||||
element: PsiElement,
|
||||
ref: PsiReference,
|
||||
referenceElement: PsiElement
|
||||
) : MoveRenameUsageInfo(
|
||||
referenceElement,
|
||||
ref,
|
||||
ref.getRangeInElement().getStartOffset(),
|
||||
ref.getRangeInElement().getEndOffset(),
|
||||
element,
|
||||
false
|
||||
)
|
||||
|
||||
override fun canProcessElement(element: PsiElement): Boolean = element is KtNamedDeclaration
|
||||
|
||||
protected fun findReferences(
|
||||
element: PsiElement,
|
||||
searchParameters: KotlinReferencesSearchParameters
|
||||
): Collection<PsiReference> {
|
||||
val references = ReferencesSearch.search(searchParameters).toMutableSet()
|
||||
if (element is KtNamedFunction || (element is KtProperty && !element.isLocal) || (element is KtParameter && element.hasValOrVar())) {
|
||||
element.toLightMethods().flatMapTo(references) { method ->
|
||||
MethodReferencesSearch.search(
|
||||
KotlinMethodReferencesSearchParameters(
|
||||
method,
|
||||
kotlinOptions = KotlinReferencesSearchOptions(
|
||||
acceptImportAlias = false
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return references.filter {
|
||||
// have to filter so far as
|
||||
// - text-matched reference could be named as imported alias and found in ReferencesSearch
|
||||
// - MethodUsagesSearcher could create its own MethodReferencesSearchParameters regardless provided one
|
||||
it.element.getNonStrictParentOfType<KtImportDirective>() != null || it.getImportAlias() == null
|
||||
}
|
||||
}
|
||||
|
||||
override fun createUsageInfo(element: PsiElement, ref: PsiReference, referenceElement: PsiElement): UsageInfo {
|
||||
if (ref !is KtReference) {
|
||||
val targetElement = ref.resolve()
|
||||
if (targetElement is KtLightMethod && targetElement.isMangled) {
|
||||
KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix(targetElement.name)?.let {
|
||||
return MangledJavaRefUsageInfo(
|
||||
it,
|
||||
element,
|
||||
ref,
|
||||
referenceElement
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.createUsageInfo(element, ref, referenceElement)
|
||||
}
|
||||
|
||||
override fun getElementToSearchInStringsAndComments(element: PsiElement): PsiElement? {
|
||||
val unwrapped = element.unwrapped ?: return null
|
||||
if ((unwrapped is KtDeclaration) && KtPsiUtil.isLocal(unwrapped)) return null
|
||||
return element
|
||||
}
|
||||
|
||||
override fun getQualifiedNameAfterRename(element: PsiElement, newName: String, nonJava: Boolean): String? {
|
||||
if (!nonJava) return newName
|
||||
|
||||
val qualifiedName = when (element) {
|
||||
is KtNamedDeclaration -> element.fqName?.asString() ?: element.name
|
||||
is PsiClass -> element.qualifiedName ?: element.name
|
||||
else -> return null
|
||||
}
|
||||
return PsiUtilCore.getQualifiedNameAfterRename(qualifiedName, newName)
|
||||
}
|
||||
|
||||
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||
val safeNewName = newName.quoteIfNeeded()
|
||||
|
||||
if (!newName.isIdentifier()) {
|
||||
allRenames[element] = safeNewName
|
||||
}
|
||||
|
||||
val declaration = element.namedUnwrappedElement as? KtNamedDeclaration
|
||||
if (declaration != null) {
|
||||
declaration.liftToExpected()?.let { expectDeclaration ->
|
||||
allRenames[expectDeclaration] = safeNewName
|
||||
expectDeclaration.actualsForExpected().forEach { allRenames[it] = safeNewName }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected var PsiElement.ambiguousImportUsages: List<UsageInfo>? by UserDataProperty(Key.create("AMBIGUOUS_IMPORT_USAGES"))
|
||||
|
||||
protected fun UsageInfo.isAmbiguousImportUsage(): Boolean {
|
||||
val ref = reference as? PsiPolyVariantReference ?: return false
|
||||
val refElement = ref.element
|
||||
return refElement.parents
|
||||
.any { (it is KtImportDirective && !it.isAllUnder) || (it is PsiImportStaticStatement && !it.isOnDemand) } && ref.multiResolve(
|
||||
false
|
||||
).mapNotNullTo(HashSet()) { it.element?.unwrapped }.size > 1
|
||||
}
|
||||
|
||||
protected fun renameMangledUsageIfPossible(usage: UsageInfo, element: PsiElement, newName: String): Boolean {
|
||||
val chosenName = (if (usage is MangledJavaRefUsageInfo) {
|
||||
KotlinTypeMapper.InternalNameMapper.mangleInternalName(newName, usage.manglingSuffix)
|
||||
} else {
|
||||
val reference = usage.reference
|
||||
if (reference is KtReference) {
|
||||
if (element is KtLightMethod && element.isMangled) {
|
||||
KotlinTypeMapper.InternalNameMapper.demangleInternalName(newName)
|
||||
} else null
|
||||
} else null
|
||||
}) ?: return false
|
||||
usage.reference?.handleElementRename(chosenName)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun renameElement(
|
||||
element: PsiElement,
|
||||
newName: String,
|
||||
usages: Array<UsageInfo>,
|
||||
listener: RefactoringElementListener?
|
||||
) {
|
||||
val simpleUsages = ArrayList<UsageInfo>(usages.size)
|
||||
ForeignUsagesRenameProcessor.processAll(element, newName, usages, fallbackHandler = { usage ->
|
||||
if (renameMangledUsageIfPossible(usage, element, newName)) return@processAll
|
||||
simpleUsages += usage
|
||||
})
|
||||
|
||||
RenameUtil.doRenameGenericNamedElement(element, newName, simpleUsages.toTypedArray(), listener)
|
||||
}
|
||||
|
||||
override fun getPostRenameCallback(element: PsiElement, newName: String, elementListener: RefactoringElementListener): Runnable? {
|
||||
return Runnable {
|
||||
element.ambiguousImportUsages?.forEach {
|
||||
val ref = it.reference as? PsiPolyVariantReference ?: return@forEach
|
||||
if (ref.multiResolve(false).isEmpty()) {
|
||||
if (!renameMangledUsageIfPossible(it, element, newName)) {
|
||||
ref.handleElementRename(newName)
|
||||
}
|
||||
} else {
|
||||
ref.element.getStrictParentOfType<KtImportDirective>()?.let { importDirective ->
|
||||
val fqName = importDirective.importedFqName!!
|
||||
val newFqName = fqName.parent().child(Name.identifier(newName))
|
||||
val importList = importDirective.parent as KtImportList
|
||||
if (importList.imports.none { directive -> directive.importedFqName == newFqName }) {
|
||||
val newImportDirective = KtPsiFactory(element).createImportDirective(ImportPath(newFqName, false))
|
||||
importDirective.parent.addAfter(newImportDirective, importDirective)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
element.ambiguousImportUsages = null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ abstract class AbstractTypingIndentationTestBase : KotlinLightPlatformCodeInsigh
|
||||
val originFilePath = testFileName + testFileExtension
|
||||
val originalFileText = FileUtil.loadFile(File(originFilePath), true)
|
||||
try {
|
||||
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project_))
|
||||
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project))
|
||||
if (!inverted) {
|
||||
configurator.configureSettings()
|
||||
} else {
|
||||
@@ -32,16 +32,16 @@ abstract class AbstractTypingIndentationTestBase : KotlinLightPlatformCodeInsigh
|
||||
|
||||
doNewlineTest(originFilePath, afterFilePath)
|
||||
} finally {
|
||||
CodeStyle.getSettings(project_).clearCodeStyleSettings()
|
||||
CodeStyle.getSettings(project).clearCodeStyleSettings()
|
||||
}
|
||||
}
|
||||
|
||||
private fun doNewlineTest(beforeFilePath: String, afterFilePath: String) {
|
||||
configureByFile(beforeFilePath)
|
||||
type('\n')
|
||||
val caretModel = editor_.caretModel
|
||||
val caretModel = editor.caretModel
|
||||
val offset = caretModel.offset
|
||||
val actualTextWithCaret = StringBuilder(editor_.document.text).insert(offset, EditorTestUtil.CARET_TAG).toString()
|
||||
val actualTextWithCaret = StringBuilder(editor.document.text).insert(offset, EditorTestUtil.CARET_TAG).toString()
|
||||
KotlinTestUtils.assertEqualsToFile(File(afterFilePath), actualTextWithCaret)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.move
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.refactoring.move.MoveHandlerDelegate
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
internal fun MoveHandlerDelegate.canMoveCompat(
|
||||
elements: Array<out PsiElement>,
|
||||
targetContainer: PsiElement?,
|
||||
reference: PsiReference?
|
||||
): Boolean = canMove(elements, targetContainer, reference)
|
||||
+32
-32
@@ -51,90 +51,90 @@ class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
||||
|
||||
fun testObjectLiteral() = doTest { rootDir, handler ->
|
||||
val objectDeclaration = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtObjectDeclaration>()!!
|
||||
assert(!handler.canMoveCompat(arrayOf<PsiElement>(objectDeclaration), null, null))
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(objectDeclaration), null, null))
|
||||
}
|
||||
|
||||
fun testLocalClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(!handler.canMoveCompat(arrayOf<PsiElement>(klass), null, null))
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||
}
|
||||
|
||||
fun testLocalFun() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(!handler.canMoveCompat(arrayOf<PsiElement>(function), null, null))
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||
}
|
||||
|
||||
fun testLocalVal() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(!handler.canMoveCompat(arrayOf<PsiElement>(property), null, null))
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||
}
|
||||
|
||||
fun testMemberFun() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(!handler.canMoveCompat(arrayOf<PsiElement>(function), null, null))
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||
}
|
||||
|
||||
fun testMemberVal() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(!handler.canMoveCompat(arrayOf<PsiElement>(property), null, null))
|
||||
assert(!handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||
}
|
||||
|
||||
fun testNestedClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(klass), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||
}
|
||||
|
||||
fun testInnerClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(klass), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||
}
|
||||
|
||||
fun testTopLevelClass() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(klass), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||
}
|
||||
|
||||
fun testTopLevelFun() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(function), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||
}
|
||||
|
||||
fun testTopLevelVal() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(property), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||
}
|
||||
|
||||
fun testMultipleNestedClasses() = doTest { rootDir, handler ->
|
||||
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
||||
assert(handler.canMoveCompat(classes.toTypedArray(), null, null))
|
||||
assert(handler.canMove(classes.toTypedArray(), null, null))
|
||||
}
|
||||
|
||||
fun testNestedAndTopLevelClass() = doTest { rootDir, handler ->
|
||||
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
||||
assert(!handler.canMoveCompat(classes.toTypedArray(), null, null))
|
||||
assert(!handler.canMove(classes.toTypedArray(), null, null))
|
||||
}
|
||||
|
||||
fun testMultipleTopLevelDeclarations() = doTest { rootDir, handler ->
|
||||
val declarations = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
||||
assert(handler.canMoveCompat(declarations.toTypedArray(), null, null))
|
||||
assert(handler.canMove(declarations.toTypedArray(), null, null))
|
||||
}
|
||||
|
||||
fun testMultipleTopLevelDeclarationsInDifferentFiles() = doTest { rootDir, handler ->
|
||||
val declarations = listOf("test.kt", "test2.kt").flatMap { getElementsAtCarets(rootDir, it) }
|
||||
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
||||
assert(handler.canMoveCompat(declarations.toTypedArray(), null, null))
|
||||
assert(handler.canMove(declarations.toTypedArray(), null, null))
|
||||
|
||||
val files = listOf("test.kt", "test2.kt").map { getPsiFile(rootDir, it) }
|
||||
assert(handler.canMoveCompat(files.toTypedArray(), null, null))
|
||||
assert(handler.canMove(files.toTypedArray(), null, null))
|
||||
}
|
||||
|
||||
fun testMultipleTopLevelDeclarationsInDifferentDirs() = doTest { rootDir, handler ->
|
||||
val declarations = listOf("test1/test.kt", "test2/test2.kt").flatMap { getElementsAtCarets(rootDir, it) }
|
||||
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
||||
assert(!handler.canMoveCompat(declarations.toTypedArray(), null, null))
|
||||
assert(!handler.canMove(declarations.toTypedArray(), null, null))
|
||||
|
||||
val files = listOf("test1/test.kt", "test2/test2.kt").map { getPsiFile(rootDir, it) }
|
||||
assert(!handler.canMoveCompat(files.toTypedArray(), null, null))
|
||||
assert(!handler.canMove(files.toTypedArray(), null, null))
|
||||
}
|
||||
|
||||
fun testFileAndTopLevelDeclarations() = doTest { rootDir, handler ->
|
||||
@@ -142,20 +142,20 @@ class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
||||
rootDir,
|
||||
"test2.kt"
|
||||
)
|
||||
assert(!handler.canMoveCompat(elements.toTypedArray(), null, null))
|
||||
assert(!handler.canMove(elements.toTypedArray(), null, null))
|
||||
}
|
||||
|
||||
fun testCommonTargets() = doTest { rootDir, handler ->
|
||||
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||
|
||||
val targetPackage = JavaPsiFacade.getInstance(project).findPackage("pack")!!
|
||||
assert(handler.canMoveCompat(elementsToMove, targetPackage, null))
|
||||
assert(handler.canMove(elementsToMove, targetPackage, null))
|
||||
|
||||
val targetDirectory = getPsiDirectory(rootDir, "pack")
|
||||
assert(handler.canMoveCompat(elementsToMove, targetDirectory, null))
|
||||
assert(handler.canMove(elementsToMove, targetDirectory, null))
|
||||
|
||||
val targetFile = getPsiFile(rootDir, "pack/test2.kt")
|
||||
assert(handler.canMoveCompat(elementsToMove, targetFile, null))
|
||||
assert(handler.canMove(elementsToMove, targetFile, null))
|
||||
}
|
||||
|
||||
fun testTopLevelClassToClass() = doTest { rootDir, handler ->
|
||||
@@ -164,14 +164,14 @@ class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
||||
|
||||
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||
assert(topLevelTarget.name == "B")
|
||||
assert(!handler.canMoveCompat(elementsToMove, topLevelTarget, null))
|
||||
assert(!handler.canMove(elementsToMove, topLevelTarget, null))
|
||||
|
||||
val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass
|
||||
assert(!handler.canMoveCompat(elementsToMove, annotationTarget, null))
|
||||
assert(!handler.canMove(elementsToMove, annotationTarget, null))
|
||||
|
||||
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
|
||||
assert(nestedTarget.name == "C")
|
||||
assert(!handler.canMoveCompat(elementsToMove, nestedTarget, null))
|
||||
assert(!handler.canMove(elementsToMove, nestedTarget, null))
|
||||
}
|
||||
|
||||
fun testNestedClassToClass() = doTest { rootDir, handler ->
|
||||
@@ -180,33 +180,33 @@ class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
||||
|
||||
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||
assert(topLevelTarget.name == "B")
|
||||
assert(handler.canMoveCompat(elementsToMove, topLevelTarget, null))
|
||||
assert(handler.canMove(elementsToMove, topLevelTarget, null))
|
||||
|
||||
val annotationTarget = targetFile.declarations.first { it.name == "Ann" } as KtClass
|
||||
assert(!handler.canMoveCompat(elementsToMove, annotationTarget, null))
|
||||
assert(!handler.canMove(elementsToMove, annotationTarget, null))
|
||||
|
||||
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
|
||||
assert(nestedTarget.name == "C")
|
||||
assert(handler.canMoveCompat(elementsToMove, nestedTarget, null))
|
||||
assert(handler.canMove(elementsToMove, nestedTarget, null))
|
||||
}
|
||||
|
||||
fun testTypeAlias() = doTest { rootDir, handler ->
|
||||
val typeAlias = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtTypeAlias>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(typeAlias), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(typeAlias), null, null))
|
||||
}
|
||||
|
||||
fun testTopLevelClassInScript() = doTest { rootDir, handler ->
|
||||
val klass = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtClass>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(klass), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(klass), null, null))
|
||||
}
|
||||
|
||||
fun testTopLevelFunInScript() = doTest { rootDir, handler ->
|
||||
val function = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtNamedFunction>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(function), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(function), null, null))
|
||||
}
|
||||
|
||||
fun testTopLevelValInScript() = doTest { rootDir, handler ->
|
||||
val property = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtProperty>()!!
|
||||
assert(handler.canMoveCompat(arrayOf<PsiElement>(property), null, null))
|
||||
assert(handler.canMove(arrayOf<PsiElement>(property), null, null))
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,6 @@ dependencies {
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
|
||||
compileOnly(intellijDep()) { includeJars("platform-api", "platform-impl", rootProject = rootProject) }
|
||||
|
||||
Platform[191].orLower {
|
||||
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
||||
}
|
||||
|
||||
Platform[192].orHigher {
|
||||
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||
|
||||
+4
-1
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.references.readWriteAccess
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.search.or
|
||||
import org.jetbrains.kotlin.idea.search.projectScope
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
@@ -201,7 +203,8 @@ private class ConvertGettersAndSettersToPropertyStatefulProcessing(
|
||||
|
||||
private fun KtParameter.rename(newName: String) {
|
||||
val renamer = RenamePsiElementProcessor.forElement(this)
|
||||
val findReferences = findReferences(renamer)
|
||||
val searchScope = project.projectScope() or useScope
|
||||
val findReferences = renamer.findReferences(this, searchScope, false)
|
||||
val usageInfos =
|
||||
findReferences.mapNotNull { reference ->
|
||||
val element = reference.element
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.postProcessing.processings
|
||||
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||
import org.jetbrains.kotlin.idea.search.or
|
||||
import org.jetbrains.kotlin.idea.search.projectScope
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
|
||||
// FIX ME WHEN BUNCH 191 REMOVED
|
||||
|
||||
internal fun KtParameter.findReferences(renamer: RenamePsiElementProcessor): MutableCollection<PsiReference> {
|
||||
val searchScope = this.project.projectScope() or this.useScope
|
||||
return renamer.findReferences(this, searchScope, false)
|
||||
}
|
||||
Reference in New Issue
Block a user