Cleanup 191 patchset logic (KTI-267)
This commit is contained in:
+1
-1
@@ -200,7 +200,7 @@ extra["intellijSeparateSdks"] = intellijSeparateSdks
|
|||||||
|
|
||||||
extra["IntellijCoreDependencies"] =
|
extra["IntellijCoreDependencies"] =
|
||||||
listOf(
|
listOf(
|
||||||
if (Platform[191].orHigher()) "asm-all-7.0.1" else "asm-all",
|
"asm-all-7.0.1",
|
||||||
"guava",
|
"guava",
|
||||||
"jdom",
|
"jdom",
|
||||||
"jna",
|
"jna",
|
||||||
|
|||||||
@@ -30,9 +30,6 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", "groovy-all", rootProject = rootProject) }
|
testCompile(intellijDep()) { includeJars("util", "idea", "idea_rt", "groovy-all", rootProject = rootProject) }
|
||||||
Platform[191].orLower {
|
|
||||||
testCompile(intellijDep()) { includeJars("jps-builders") }
|
|
||||||
}
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
testCompile(intellijPluginDep("java")) { includeJars("jps-builders") }
|
testCompile(intellijPluginDep("java")) { includeJars("jps-builders") }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,6 @@ dependencies {
|
|||||||
includeJars("extensions", "idea_rt", "util", "asm-all", rootProject = rootProject)
|
includeJars("extensions", "idea_rt", "util", "asm-all", rootProject = rootProject)
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform[191].orLower {
|
|
||||||
testCompileOnly(intellijDep()) { includeJars("java-api") }
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api") }
|
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api") }
|
||||||
testRuntimeOnly(intellijPluginDep("java"))
|
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.project.Project
|
||||||
import com.intellij.openapi.util.SimpleModificationTracker
|
import com.intellij.openapi.util.SimpleModificationTracker
|
||||||
import com.intellij.pom.tree.TreeAspect
|
import com.intellij.pom.tree.TreeAspect
|
||||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl
|
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,61 +20,32 @@ class KotlinCodeBlockModificationListener(
|
|||||||
treeAspect: TreeAspect
|
treeAspect: TreeAspect
|
||||||
) : KotlinCodeBlockModificationListenerCompat(project) {
|
) : 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 {
|
||||||
init(
|
init(
|
||||||
treeAspect,
|
treeAspect,
|
||||||
incOCBCounter = { ktFile ->
|
incOCBCounter = { ktFile ->
|
||||||
if (isLanguageTrackerEnabled) {
|
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
||||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, true)
|
|
||||||
} else {
|
|
||||||
perModuleOutOfCodeBlockTrackerUpdater.onKotlinPhysicalFileOutOfBlockChange(ktFile, false)
|
|
||||||
// Increment counter and process changes in PsiModificationTracker.Listener
|
|
||||||
modificationTrackerImpl.incCounter()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
kotlinOutOfCodeBlockTrackerProducer = {
|
kotlinOutOfCodeBlockTrackerProducer = {
|
||||||
if (isLanguageTrackerEnabled) {
|
SimpleModificationTracker()
|
||||||
SimpleModificationTracker()
|
|
||||||
} else {
|
|
||||||
object : SimpleModificationTracker() {
|
|
||||||
override fun getModificationCount(): Long {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
return modificationTrackerImpl.outOfCodeBlockModificationCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
psiModificationTrackerListener = {
|
psiModificationTrackerListener = {
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
if (isLanguageTrackerEnabled) {
|
val kotlinTrackerInternalIDECount =
|
||||||
val kotlinTrackerInternalIDECount =
|
modificationTrackerImpl.forLanguage(KotlinLanguage.INSTANCE).modificationCount
|
||||||
modificationTrackerImpl.forLanguage(KotlinLanguage.INSTANCE).modificationCount
|
if (kotlinModificationTracker == kotlinTrackerInternalIDECount) {
|
||||||
if (kotlinModificationTracker == kotlinTrackerInternalIDECount) {
|
// Some update that we are not sure is from Kotlin language, as Kotlin language tracker wasn't changed
|
||||||
// Some update that we are not sure is from Kotlin language, as Kotlin language tracker wasn't changed
|
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
||||||
kotlinOutOfCodeBlockTrackerImpl.incModificationCount()
|
} else {
|
||||||
} else {
|
kotlinModificationTracker = kotlinTrackerInternalIDECount
|
||||||
kotlinModificationTracker = kotlinTrackerInternalIDECount
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
perModuleOutOfCodeBlockTrackerUpdater.onPsiModificationTrackerUpdate(customIncrement)
|
perModuleOutOfCodeBlockTrackerUpdater.onPsiModificationTrackerUpdate()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun treeChanged(event: PsiTreeChangeEventImpl) {
|
|
||||||
assert(isLanguageTrackerEnabled)
|
|
||||||
super.treeChanged(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(project: Project): KotlinCodeBlockModificationListener =
|
fun getInstance(project: Project): KotlinCodeBlockModificationListener =
|
||||||
project.getComponent(KotlinCodeBlockModificationListener::class.java)
|
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)
|
val problemDescriptor = manager.createProblemDescriptor(element, range, description, highlightType, isOnTheFly, *fixes)
|
||||||
registerProblem(problemDescriptor)
|
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")
|
@Suppress("unused")
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ dependencies {
|
|||||||
testCompileOnly(intellijDep())
|
testCompileOnly(intellijDep())
|
||||||
testRuntime(intellijDep())
|
testRuntime(intellijDep())
|
||||||
|
|
||||||
if (Platform[191].orLower()) {
|
|
||||||
testRuntimeOnly(intellijPluginDep("Groovy"))
|
|
||||||
}
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
testCompileOnly(intellijPluginDep("java"))
|
testCompileOnly(intellijPluginDep("java"))
|
||||||
testRuntime(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())
|
sourceSet.setSources(sourcesWithTypes.toMap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -952,8 +950,6 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtensionComp
|
|||||||
sourceSet.targetCompatibility = ktSourceSetData.targetCompatibility
|
sourceSet.targetCompatibility = ktSourceSetData.targetCompatibility
|
||||||
sourceSet.dependencies += ktSourceSet.dependencies.mapNotNull { mppModel.dependencyMap[it] }
|
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(
|
sourceSet.setSources(linkedMapOf(
|
||||||
ktSourceSet.sourceType to DefaultExternalSourceDirectorySet().also { dirSet ->
|
ktSourceSet.sourceType to DefaultExternalSourceDirectorySet().also { dirSet ->
|
||||||
dirSet.srcDirs = ktSourceSet.sourceDirs
|
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.GradleBuildSrcProjectsResolver;
|
||||||
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil;
|
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil;
|
||||||
import org.jetbrains.plugins.gradle.service.task.GradleTaskManager;
|
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.settings.GradleSettings;
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
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.service.execution.ExternalSystemRunConfiguration.PROGRESS_LISTENER_KEY;
|
||||||
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
|
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
|
||||||
import static com.intellij.openapi.util.text.StringUtil.*;
|
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;
|
import static org.jetbrains.plugins.gradle.execution.GradleRunnerUtil.resolveProjectPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,7 +180,7 @@ class KotlinMPPGradleProjectTaskRunner extends ProjectTaskRunner
|
|||||||
final ModuleBuildTask moduleBuildTask = (ModuleBuildTask) projectTask;
|
final ModuleBuildTask moduleBuildTask = (ModuleBuildTask) projectTask;
|
||||||
final Module module = moduleBuildTask.getModule();
|
final Module module = moduleBuildTask.getModule();
|
||||||
|
|
||||||
if (! isDelegatedBuild(module)) {
|
if (module.getProject().getPresentableUrl() != null && GradleProjectSettings.isDelegatedBuildEnabled(module)) {
|
||||||
return false;
|
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.GradleBuildSrcProjectsResolver;
|
||||||
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil;
|
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil;
|
||||||
import org.jetbrains.plugins.gradle.service.task.GradleTaskManager;
|
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.settings.GradleSettings;
|
||||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
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.service.execution.ExternalSystemRunConfiguration.PROGRESS_LISTENER_KEY;
|
||||||
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
|
import static com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.*;
|
||||||
import static com.intellij.openapi.util.text.StringUtil.*;
|
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;
|
import static org.jetbrains.plugins.gradle.execution.GradleRunnerUtil.resolveProjectPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,7 +177,7 @@ class KotlinMPPGradleProjectTaskRunner extends ProjectTaskRunner
|
|||||||
final ModuleBuildTask moduleBuildTask = (ModuleBuildTask) projectTask;
|
final ModuleBuildTask moduleBuildTask = (ModuleBuildTask) projectTask;
|
||||||
final Module module = moduleBuildTask.getModule();
|
final Module module = moduleBuildTask.getModule();
|
||||||
|
|
||||||
if (! isDelegatedBuild(module)) {
|
if (module.getProject().getPresentableUrl() != null && GradleProjectSettings.isDelegatedBuildEnabled(module)) {
|
||||||
return false;
|
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"))
|
compileOnly(intellijPluginDep("maven"))
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform[191].orLower {
|
|
||||||
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||||
testCompileOnly(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
|
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.testFramework.LightPlatformCodeInsightTestCase
|
||||||
import com.intellij.util.ThrowableRunnable
|
import com.intellij.util.ThrowableRunnable
|
||||||
|
|
||||||
// FIX ME WHEN BUNCH 191 REMOVED
|
|
||||||
abstract class KotlinLightPlatformCodeInsightTestCase : LightPlatformCodeInsightTestCase() {
|
abstract class KotlinLightPlatformCodeInsightTestCase : LightPlatformCodeInsightTestCase() {
|
||||||
protected inline val project_: Project get() = project
|
|
||||||
protected inline val editor_: Editor get() = editor
|
|
||||||
|
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
enableKotlinOfficialCodeStyle(project_)
|
enableKotlinOfficialCodeStyle(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tearDown() = runAll(
|
override fun tearDown() = runAll(
|
||||||
ThrowableRunnable { disableKotlinOfficialCodeStyle(project_) },
|
ThrowableRunnable { disableKotlinOfficialCodeStyle(project) },
|
||||||
ThrowableRunnable { super.tearDown() },
|
ThrowableRunnable { super.tearDown() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,6 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.testFramework.LightIdeaTestCase
|
import com.intellij.testFramework.LightIdeaTestCase
|
||||||
|
|
||||||
// FIX ME WHEN BUNCH as36 REMOVED
|
// FIX ME WHEN BUNCH as36 REMOVED
|
||||||
// FIX ME WHEN BUNCH 191 REMOVED
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use KotlinLightCodeInsightFixtureTestCase instead")
|
@Deprecated("Use KotlinLightCodeInsightFixtureTestCase instead")
|
||||||
abstract class KotlinLightCodeInsightTestCase : com.intellij.testFramework.LightCodeInsightTestCase() {
|
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 as36 REMOVED
|
||||||
// FIX ME WHEN BUNCH 191 REMOVED
|
|
||||||
abstract class KotlinLightIdeaTestCase : LightIdeaTestCase() {
|
abstract class KotlinLightIdeaTestCase : LightIdeaTestCase() {
|
||||||
protected inline val project_: Project get() = project
|
protected inline val project_: Project get() = project
|
||||||
protected inline val module_: Module get() = module
|
protected inline val module_: Module get() = module
|
||||||
|
|||||||
-2
@@ -16,7 +16,6 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.testFramework.LightIdeaTestCase
|
import com.intellij.testFramework.LightIdeaTestCase
|
||||||
|
|
||||||
// FIX ME WHEN BUNCH as36 REMOVED
|
// FIX ME WHEN BUNCH as36 REMOVED
|
||||||
// FIX ME WHEN BUNCH 191 REMOVED
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use KotlinLightCodeInsightFixtureTestCase instead")
|
@Deprecated("Use KotlinLightCodeInsightFixtureTestCase instead")
|
||||||
abstract class KotlinLightCodeInsightTestCase : com.intellij.testFramework.LightCodeInsightTestCase() {
|
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 as36 REMOVED
|
||||||
// FIX ME WHEN BUNCH 191 REMOVED
|
|
||||||
abstract class KotlinLightIdeaTestCase : LightIdeaTestCase() {
|
abstract class KotlinLightIdeaTestCase : LightIdeaTestCase() {
|
||||||
protected inline val project_: Project get() = project
|
protected inline val project_: Project get() = project
|
||||||
protected inline val module_: Module get() = module
|
protected inline val module_: Module get() = module
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ dependencies {
|
|||||||
|
|
||||||
testCompile(intellijPluginDep("stream-debugger"))
|
testCompile(intellijPluginDep("stream-debugger"))
|
||||||
|
|
||||||
Platform[191].orLower {
|
|
||||||
testCompileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl", "aether-dependency-resolver") }
|
testCompileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl", "aether-dependency-resolver") }
|
||||||
testRuntime(intellijPluginDep("java"))
|
testRuntime(intellijPluginDep("java"))
|
||||||
|
|||||||
+4
-4
@@ -33,7 +33,7 @@ abstract class AbstractPerformanceTypingIndentationTest : KotlinLightPlatformCod
|
|||||||
val originalFileText = FileUtil.loadFile(File(originFilePath), true)
|
val originalFileText = FileUtil.loadFile(File(originFilePath), true)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project_))
|
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project))
|
||||||
configurator.configureSettings()
|
configurator.configureSettings()
|
||||||
|
|
||||||
performanceTest<Unit, Unit> {
|
performanceTest<Unit, Unit> {
|
||||||
@@ -48,8 +48,8 @@ abstract class AbstractPerformanceTypingIndentationTest : KotlinLightPlatformCod
|
|||||||
executeAction(IdeActions.ACTION_EDITOR_ENTER)
|
executeAction(IdeActions.ACTION_EDITOR_ENTER)
|
||||||
}
|
}
|
||||||
tearDown {
|
tearDown {
|
||||||
val actualTextWithCaret = StringBuilder(editor_.document.text).insert(
|
val actualTextWithCaret = StringBuilder(editor.document.text).insert(
|
||||||
editor_.caretModel.offset,
|
editor.caretModel.offset,
|
||||||
EditorTestUtil.CARET_TAG
|
EditorTestUtil.CARET_TAG
|
||||||
).toString()
|
).toString()
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ abstract class AbstractPerformanceTypingIndentationTest : KotlinLightPlatformCod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} 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.KotlinBundle
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler
|
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.idea.util.string.collapseSpaces
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -148,7 +148,7 @@ class KotlinElementDescriptionProvider : ElementDescriptionProvider {
|
|||||||
is KtImportAlias -> KotlinBundle.message("find.usages.import.alias")
|
is KtImportAlias -> KotlinBundle.message("find.usages.import.alias")
|
||||||
is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper -> KotlinBundle.message("find.usages.property")
|
is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper -> KotlinBundle.message("find.usages.property")
|
||||||
is KtLightClassForFacade -> KotlinBundle.message("find.usages.facade.class")
|
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
|
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.psi.*
|
||||||
import com.intellij.refactoring.RefactoringBundle
|
import com.intellij.refactoring.RefactoringBundle
|
||||||
import com.intellij.refactoring.move.MoveCallback
|
import com.intellij.refactoring.move.MoveCallback
|
||||||
|
import com.intellij.refactoring.move.MoveHandlerDelegate
|
||||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesImpl
|
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesImpl
|
||||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
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.core.getPackage
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
|
||||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
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.KotlinAwareMoveFilesOrDirectoriesDialog
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinSelectNestedClassRefactoringDialog
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinSelectNestedClassRefactoringDialog
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinNestedClassesDialog
|
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) :
|
class MoveKotlinDeclarationsHandler internal constructor(private val handlerActions: MoveKotlinDeclarationsHandlerActions) :
|
||||||
MoveHandlerDelegateCompat() {
|
MoveHandlerDelegate() {
|
||||||
|
|
||||||
constructor() : this(defaultHandlerActions)
|
constructor() : this(defaultHandlerActions)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -13,9 +13,9 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.refactoring.move.MoveCallback
|
import com.intellij.refactoring.move.MoveCallback
|
||||||
import com.intellij.refactoring.move.MoveHandler
|
import com.intellij.refactoring.move.MoveHandler
|
||||||
|
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesHandler
|
||||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
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.logFusForMoveRefactoring
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesModel
|
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.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandlerCompat() {
|
class KotlinMoveFilesOrDirectoriesHandler : MoveFilesOrDirectoriesHandler() {
|
||||||
private fun adjustElements(elements: Array<out PsiElement>): Array<PsiFileSystemItem>? {
|
private fun adjustElements(elements: Array<out PsiElement>): Array<PsiFileSystemItem>? {
|
||||||
return elements.map {
|
return elements.map {
|
||||||
when {
|
when {
|
||||||
|
|||||||
+120
-2
@@ -5,12 +5,130 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.rename
|
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiReference
|
import com.intellij.psi.PsiReference
|
||||||
import com.intellij.psi.search.SearchScope
|
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 : RenameKotlinPsiProcessor() {
|
||||||
class RenameKotlinClassifierProcessor : RenameKotlinClassifierProcessorCompat() {
|
|
||||||
|
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(
|
override fun findReferences(
|
||||||
element: PsiElement,
|
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
|
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.psi.PsiReference
|
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.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 : RenameKotlinPsiProcessor() {
|
||||||
class RenameKotlinFunctionProcessor : RenameKotlinFunctionProcessorCompat() {
|
|
||||||
|
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(
|
override fun findReferences(
|
||||||
element: PsiElement,
|
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
|
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.navigation.NavigationItem
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.psi.PsiReference
|
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.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.listeners.RefactoringElementListener
|
||||||
|
import com.intellij.refactoring.rename.RenameProcessor
|
||||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||||
|
import com.intellij.refactoring.util.RefactoringUtil
|
||||||
import com.intellij.usageView.UsageInfo
|
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.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.propertyNameByAccessor
|
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
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.isEnumCompanionPropertyWithEntryConflict
|
||||||
import org.jetbrains.kotlin.idea.core.unquote
|
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.refactoring.dropOverrideKeywordIfNecessary
|
||||||
|
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||||
import org.jetbrains.kotlin.idea.references.KtReference
|
import org.jetbrains.kotlin.idea.references.KtReference
|
||||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
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.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
import org.jetbrains.kotlin.psi.psiUtil.findPropertyByName
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
|
import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
|
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
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 : RenameKotlinPsiProcessor() {
|
||||||
class RenameKotlinPropertyProcessor : RenameKotlinPropertyProcessorCompat() {
|
|
||||||
|
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(
|
override fun findReferences(
|
||||||
element: PsiElement,
|
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
|
package org.jetbrains.kotlin.idea.refactoring.rename
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.psi.PsiReference
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.search.SearchScope
|
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.KotlinReferencesSearchOptions
|
||||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
|
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 : RenamePsiElementProcessor() {
|
||||||
abstract class RenameKotlinPsiProcessor : RenameKotlinPsiProcessorCompat() {
|
|
||||||
|
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(
|
override fun findReferences(
|
||||||
element: PsiElement,
|
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 originFilePath = testFileName + testFileExtension
|
||||||
val originalFileText = FileUtil.loadFile(File(originFilePath), true)
|
val originalFileText = FileUtil.loadFile(File(originFilePath), true)
|
||||||
try {
|
try {
|
||||||
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project_))
|
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project))
|
||||||
if (!inverted) {
|
if (!inverted) {
|
||||||
configurator.configureSettings()
|
configurator.configureSettings()
|
||||||
} else {
|
} else {
|
||||||
@@ -32,16 +32,16 @@ abstract class AbstractTypingIndentationTestBase : KotlinLightPlatformCodeInsigh
|
|||||||
|
|
||||||
doNewlineTest(originFilePath, afterFilePath)
|
doNewlineTest(originFilePath, afterFilePath)
|
||||||
} finally {
|
} finally {
|
||||||
CodeStyle.getSettings(project_).clearCodeStyleSettings()
|
CodeStyle.getSettings(project).clearCodeStyleSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doNewlineTest(beforeFilePath: String, afterFilePath: String) {
|
private fun doNewlineTest(beforeFilePath: String, afterFilePath: String) {
|
||||||
configureByFile(beforeFilePath)
|
configureByFile(beforeFilePath)
|
||||||
type('\n')
|
type('\n')
|
||||||
val caretModel = editor_.caretModel
|
val caretModel = editor.caretModel
|
||||||
val offset = caretModel.offset
|
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)
|
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 ->
|
fun testObjectLiteral() = doTest { rootDir, handler ->
|
||||||
val objectDeclaration = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtObjectDeclaration>()!!
|
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 ->
|
fun testLocalClass() = doTest { rootDir, handler ->
|
||||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
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 ->
|
fun testLocalFun() = doTest { rootDir, handler ->
|
||||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
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 ->
|
fun testLocalVal() = doTest { rootDir, handler ->
|
||||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
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 ->
|
fun testMemberFun() = doTest { rootDir, handler ->
|
||||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
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 ->
|
fun testMemberVal() = doTest { rootDir, handler ->
|
||||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
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 ->
|
fun testNestedClass() = doTest { rootDir, handler ->
|
||||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
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 ->
|
fun testInnerClass() = doTest { rootDir, handler ->
|
||||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
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 ->
|
fun testTopLevelClass() = doTest { rootDir, handler ->
|
||||||
val klass = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!
|
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 ->
|
fun testTopLevelFun() = doTest { rootDir, handler ->
|
||||||
val function = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtNamedFunction>()!!
|
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 ->
|
fun testTopLevelVal() = doTest { rootDir, handler ->
|
||||||
val property = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtProperty>()!!
|
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 ->
|
fun testMultipleNestedClasses() = doTest { rootDir, handler ->
|
||||||
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
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 ->
|
fun testNestedAndTopLevelClass() = doTest { rootDir, handler ->
|
||||||
val classes = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtClass>()!! }
|
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 ->
|
fun testMultipleTopLevelDeclarations() = doTest { rootDir, handler ->
|
||||||
val declarations = getElementsAtCarets(rootDir, "test.kt").map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
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 ->
|
fun testMultipleTopLevelDeclarationsInDifferentFiles() = doTest { rootDir, handler ->
|
||||||
val declarations = listOf("test.kt", "test2.kt").flatMap { getElementsAtCarets(rootDir, it) }
|
val declarations = listOf("test.kt", "test2.kt").flatMap { getElementsAtCarets(rootDir, it) }
|
||||||
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
.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) }
|
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 ->
|
fun testMultipleTopLevelDeclarationsInDifferentDirs() = doTest { rootDir, handler ->
|
||||||
val declarations = listOf("test1/test.kt", "test2/test2.kt").flatMap { getElementsAtCarets(rootDir, it) }
|
val declarations = listOf("test1/test.kt", "test2/test2.kt").flatMap { getElementsAtCarets(rootDir, it) }
|
||||||
.map { it.getNonStrictParentOfType<KtNamedDeclaration>()!! }
|
.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) }
|
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 ->
|
fun testFileAndTopLevelDeclarations() = doTest { rootDir, handler ->
|
||||||
@@ -142,20 +142,20 @@ class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
|||||||
rootDir,
|
rootDir,
|
||||||
"test2.kt"
|
"test2.kt"
|
||||||
)
|
)
|
||||||
assert(!handler.canMoveCompat(elements.toTypedArray(), null, null))
|
assert(!handler.canMove(elements.toTypedArray(), null, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testCommonTargets() = doTest { rootDir, handler ->
|
fun testCommonTargets() = doTest { rootDir, handler ->
|
||||||
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
val elementsToMove = arrayOf<PsiElement>(getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtClass>()!!)
|
||||||
|
|
||||||
val targetPackage = JavaPsiFacade.getInstance(project).findPackage("pack")!!
|
val targetPackage = JavaPsiFacade.getInstance(project).findPackage("pack")!!
|
||||||
assert(handler.canMoveCompat(elementsToMove, targetPackage, null))
|
assert(handler.canMove(elementsToMove, targetPackage, null))
|
||||||
|
|
||||||
val targetDirectory = getPsiDirectory(rootDir, "pack")
|
val targetDirectory = getPsiDirectory(rootDir, "pack")
|
||||||
assert(handler.canMoveCompat(elementsToMove, targetDirectory, null))
|
assert(handler.canMove(elementsToMove, targetDirectory, null))
|
||||||
|
|
||||||
val targetFile = getPsiFile(rootDir, "pack/test2.kt")
|
val targetFile = getPsiFile(rootDir, "pack/test2.kt")
|
||||||
assert(handler.canMoveCompat(elementsToMove, targetFile, null))
|
assert(handler.canMove(elementsToMove, targetFile, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testTopLevelClassToClass() = doTest { rootDir, handler ->
|
fun testTopLevelClassToClass() = doTest { rootDir, handler ->
|
||||||
@@ -164,14 +164,14 @@ class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
|||||||
|
|
||||||
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||||
assert(topLevelTarget.name == "B")
|
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
|
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>()
|
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
|
||||||
assert(nestedTarget.name == "C")
|
assert(nestedTarget.name == "C")
|
||||||
assert(!handler.canMoveCompat(elementsToMove, nestedTarget, null))
|
assert(!handler.canMove(elementsToMove, nestedTarget, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testNestedClassToClass() = doTest { rootDir, handler ->
|
fun testNestedClassToClass() = doTest { rootDir, handler ->
|
||||||
@@ -180,33 +180,33 @@ class MoveKotlinDeclarationsHandlerTest : KotlinMultiFileTestCase() {
|
|||||||
|
|
||||||
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
val topLevelTarget = targetFile.declarations.firstIsInstance<KtClass>()
|
||||||
assert(topLevelTarget.name == "B")
|
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
|
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>()
|
val nestedTarget = topLevelTarget.declarations.firstIsInstance<KtClass>()
|
||||||
assert(nestedTarget.name == "C")
|
assert(nestedTarget.name == "C")
|
||||||
assert(handler.canMoveCompat(elementsToMove, nestedTarget, null))
|
assert(handler.canMove(elementsToMove, nestedTarget, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testTypeAlias() = doTest { rootDir, handler ->
|
fun testTypeAlias() = doTest { rootDir, handler ->
|
||||||
val typeAlias = getElementAtCaret(rootDir, "test.kt").getNonStrictParentOfType<KtTypeAlias>()!!
|
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 ->
|
fun testTopLevelClassInScript() = doTest { rootDir, handler ->
|
||||||
val klass = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtClass>()!!
|
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 ->
|
fun testTopLevelFunInScript() = doTest { rootDir, handler ->
|
||||||
val function = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtNamedFunction>()!!
|
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 ->
|
fun testTopLevelValInScript() = doTest { rootDir, handler ->
|
||||||
val property = getElementAtCaret(rootDir, "test.kts").getNonStrictParentOfType<KtProperty>()!!
|
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(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
|
||||||
compileOnly(intellijDep()) { includeJars("platform-api", "platform-impl", rootProject = rootProject) }
|
compileOnly(intellijDep()) { includeJars("platform-api", "platform-impl", rootProject = rootProject) }
|
||||||
|
|
||||||
Platform[191].orLower {
|
|
||||||
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform[192].orHigher {
|
Platform[192].orHigher {
|
||||||
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||||
testCompileOnly(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.mainReference
|
||||||
import org.jetbrains.kotlin.idea.references.readWriteAccess
|
import org.jetbrains.kotlin.idea.references.readWriteAccess
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
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.search.usagesSearch.descriptor
|
||||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
@@ -201,7 +203,8 @@ private class ConvertGettersAndSettersToPropertyStatefulProcessing(
|
|||||||
|
|
||||||
private fun KtParameter.rename(newName: String) {
|
private fun KtParameter.rename(newName: String) {
|
||||||
val renamer = RenamePsiElementProcessor.forElement(this)
|
val renamer = RenamePsiElementProcessor.forElement(this)
|
||||||
val findReferences = findReferences(renamer)
|
val searchScope = project.projectScope() or useScope
|
||||||
|
val findReferences = renamer.findReferences(this, searchScope, false)
|
||||||
val usageInfos =
|
val usageInfos =
|
||||||
findReferences.mapNotNull { reference ->
|
findReferences.mapNotNull { reference ->
|
||||||
val element = reference.element
|
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