Implement liftToExpected correctly for primary constructor properties
Before this commit, we always tried to find expect property in this case. However, there is at least one case when we should find parameter of expect primary constructor instead (safe delete). So #KT-25321 Fixed
This commit is contained in:
@@ -12,11 +12,12 @@ import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors
|
||||
import org.jetbrains.kotlin.idea.caches.project.implementingDescriptors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.setVisibility
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
||||
@@ -60,13 +61,19 @@ fun KtDeclaration.liftToExpected(): KtDeclaration? {
|
||||
return DescriptorToSourceUtils.descriptorToDeclaration(expectedDescriptor) as? KtDeclaration
|
||||
}
|
||||
|
||||
fun KtParameter.liftToExpected(): KtParameter? {
|
||||
val parameterDescriptor = resolveToParameterDescriptorIfAny()
|
||||
val expectedDescriptor = parameterDescriptor?.liftToExpected() ?: return null
|
||||
return DescriptorToSourceUtils.descriptorToDeclaration(expectedDescriptor) as? KtParameter
|
||||
}
|
||||
|
||||
fun ModuleDescriptor.hasDeclarationOf(descriptor: MemberDescriptor) = declarationOf(descriptor) != null
|
||||
|
||||
private fun ModuleDescriptor.declarationOf(descriptor: MemberDescriptor): DeclarationDescriptor? =
|
||||
with(ExpectedActualResolver) {
|
||||
val expectedCompatibilityMap = findExpectedForActual(descriptor, this@declarationOf)
|
||||
expectedCompatibilityMap?.get(ExpectedActualResolver.Compatibility.Compatible)?.firstOrNull()
|
||||
?: expectedCompatibilityMap?.values?.flatten()?.firstOrNull()
|
||||
?: expectedCompatibilityMap?.values?.flatten()?.firstOrNull()
|
||||
}
|
||||
|
||||
fun ModuleDescriptor.hasActualsFor(descriptor: MemberDescriptor) =
|
||||
|
||||
+1
-1
@@ -457,7 +457,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
): Collection<PsiElement>? {
|
||||
when (element) {
|
||||
is KtParameter -> {
|
||||
val expectParameter = element.liftToExpected() as? KtParameter
|
||||
val expectParameter = element.liftToExpected()
|
||||
if (expectParameter != null && expectParameter != element) {
|
||||
return if (shouldAllowPropagationToExpected(element)) {
|
||||
listOf(expectParameter)
|
||||
|
||||
+1
-1
@@ -449,7 +449,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
): Collection<PsiElement>? {
|
||||
when (element) {
|
||||
is KtParameter -> {
|
||||
val expectParameter = element.liftToExpected() as? KtParameter
|
||||
val expectParameter = element.liftToExpected()
|
||||
if (expectParameter != null && expectParameter != element) {
|
||||
if (shouldAllowPropagationToExpected(element)) {
|
||||
return listOf(expectParameter)
|
||||
|
||||
+1
-1
@@ -459,7 +459,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
): Collection<PsiElement>? {
|
||||
when (element) {
|
||||
is KtParameter -> {
|
||||
val expectParameter = element.liftToExpected() as? KtParameter
|
||||
val expectParameter = element.liftToExpected()
|
||||
if (expectParameter != null && expectParameter != element) {
|
||||
if (shouldAllowPropagationToExpected(element)) {
|
||||
return listOf(expectParameter)
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="Common (experimental) " useProjectSettings="false">
|
||||
<compilerSettings/>
|
||||
<compilerArguments/>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
expect class Foo()
|
||||
|
||||
fun test() {
|
||||
Foo()
|
||||
Foo()
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="JavaScript " useProjectSettings="false">
|
||||
<implements>Common</implements>
|
||||
<compilerSettings/>
|
||||
<compilerArguments/>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="Common" />
|
||||
</component>
|
||||
</module>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
actual class Foo actual constructor() {
|
||||
constructor(s: String): this(0)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
Foo("1")
|
||||
Foo(s = "1")
|
||||
Foo()
|
||||
Foo()
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="JVM 1.6" useProjectSettings="false">
|
||||
<implements>Common</implements>
|
||||
<compilerSettings/>
|
||||
<compilerArguments/>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="Common" />
|
||||
</component>
|
||||
</module>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
actual class Foo(s: String) {
|
||||
actual constructor(): this("") {
|
||||
val x = n + 1
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
Foo("1")
|
||||
Foo(s = "1")
|
||||
Foo()
|
||||
Foo()
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="Common (experimental) " useProjectSettings="false">
|
||||
<compilerSettings/>
|
||||
<compilerArguments/>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
expect class Foo(n: Int)
|
||||
|
||||
fun test() {
|
||||
Foo(1)
|
||||
Foo(n = 1)
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="JavaScript " useProjectSettings="false">
|
||||
<implements>Common</implements>
|
||||
<compilerSettings/>
|
||||
<compilerArguments/>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="Common" />
|
||||
</component>
|
||||
</module>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
actual class Foo actual constructor(val <caret>n: Int) {
|
||||
constructor(s: String): this(0)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
Foo("1")
|
||||
Foo(s = "1")
|
||||
Foo(1)
|
||||
Foo(n = 1)
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="2" platform="JVM 1.6" useProjectSettings="false">
|
||||
<implements>Common</implements>
|
||||
<compilerSettings/>
|
||||
<compilerArguments/>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="Common" />
|
||||
</component>
|
||||
</module>
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
actual class Foo(s: String) {
|
||||
actual constructor(n: Int): this("") {
|
||||
val x = n + 1
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
Foo("1")
|
||||
Foo(s = "1")
|
||||
Foo(1)
|
||||
Foo(n = 1)
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
parameter n has 2 usages that are not safe to delete.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"mainFile": "JS/src/test/test.kt",
|
||||
"elementClass": "org.jetbrains.kotlin.psi.KtParameter"
|
||||
}
|
||||
Generated
+5
@@ -54,6 +54,11 @@ public class MultiModuleSafeDeleteTestGenerated extends AbstractMultiModuleSafeD
|
||||
runTest("idea/testData/refactoring/safeDeleteMultiModule/byActualClassPrimaryConstructorParameterLiftingToExpect/expectsAndActualsByActualClassPrimaryConstructorParameter.test");
|
||||
}
|
||||
|
||||
@TestMetadata("byActualClassPrimaryConstructorPropertyLiftingToExpect/expectsAndActualsByActualClassPrimaryConstructorProperty.test")
|
||||
public void testByActualClassPrimaryConstructorPropertyLiftingToExpect_ExpectsAndActualsByActualClassPrimaryConstructorProperty() throws Exception {
|
||||
runTest("idea/testData/refactoring/safeDeleteMultiModule/byActualClassPrimaryConstructorPropertyLiftingToExpect/expectsAndActualsByActualClassPrimaryConstructorProperty.test");
|
||||
}
|
||||
|
||||
@TestMetadata("byActualClassSecondaryConstructor/byActualClassSecondaryConstructor.test")
|
||||
public void testByActualClassSecondaryConstructor_ByActualClassSecondaryConstructor() throws Exception {
|
||||
runTest("idea/testData/refactoring/safeDeleteMultiModule/byActualClassSecondaryConstructor/byActualClassSecondaryConstructor.test");
|
||||
|
||||
Reference in New Issue
Block a user