Create actual: put top-level actual declarations in the same file
When multiple expect declarations are in the same file, and some of them already have actual declarations for this platform, then "Create actual fix" put other declarations into the same file with existing actual declarations So #KT-17058 Fixed So #KT-21082 Fixed
This commit is contained in:
@@ -21,6 +21,7 @@ import com.intellij.ide.util.DefaultPsiElementCellRenderer
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||
import org.jetbrains.kotlin.idea.facet.implementingDescriptors
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.getMultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
import java.awt.event.MouseEvent
|
||||
|
||||
@@ -87,8 +89,11 @@ private fun DeclarationDescriptor.actualsForExpected(): Collection<DeclarationDe
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
internal fun KtDeclaration.actualsForExpected(): Set<KtDeclaration> {
|
||||
return unsafeResolveToDescriptor().actualsForExpected().mapNotNullTo(LinkedHashSet()) {
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(it) as? KtDeclaration
|
||||
}
|
||||
}
|
||||
// null means "any platform" here
|
||||
internal fun KtDeclaration.actualsForExpected(platform: MultiTargetPlatform? = null): Set<KtDeclaration> =
|
||||
resolveToDescriptorIfAny(BodyResolveMode.FULL)
|
||||
?.actualsForExpected()
|
||||
?.filter { platform == null || it.module.getMultiTargetPlatform() == platform }
|
||||
?.mapNotNullTo(LinkedHashSet()) {
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(it) as? KtDeclaration
|
||||
} ?: emptySet()
|
||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.core.*
|
||||
import org.jetbrains.kotlin.idea.facet.implementingModules
|
||||
import org.jetbrains.kotlin.idea.highlighter.markers.actualsForExpected
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||
@@ -40,6 +41,7 @@ import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.getMultiTargetPlatform
|
||||
|
||||
@@ -94,6 +96,15 @@ sealed class CreateActualFix<out D : KtNamedDeclaration>(
|
||||
|
||||
private fun getOrCreateImplementationFile(): KtFile? {
|
||||
val declaration = element as? KtNamedDeclaration ?: return null
|
||||
val parent = declaration.parent
|
||||
if (parent is KtFile) {
|
||||
for (otherDeclaration in parent.declarations) {
|
||||
if (otherDeclaration === declaration) continue
|
||||
if (!otherDeclaration.hasExpectModifier()) continue
|
||||
val actualDeclaration = otherDeclaration.actualsForExpected(actualPlatform).singleOrNull() ?: continue
|
||||
return actualDeclaration.containingKtFile
|
||||
}
|
||||
}
|
||||
val name = declaration.name ?: return null
|
||||
|
||||
val expectedDir = declaration.containingFile.containingDirectory
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// "Create actual function for platform JVM" "true"
|
||||
|
||||
expect fun bar()
|
||||
|
||||
expect fun <caret>foo(arg: Int): String
|
||||
@@ -0,0 +1,5 @@
|
||||
// "Create actual function for platform JVM" "true"
|
||||
|
||||
expect fun bar()
|
||||
|
||||
expect fun foo(arg: Int): String
|
||||
@@ -0,0 +1,3 @@
|
||||
// foo: to be implemented
|
||||
|
||||
actual fun bar() {}
|
||||
@@ -0,0 +1,6 @@
|
||||
// foo: to be implemented
|
||||
|
||||
actual fun bar() {}
|
||||
actual fun foo(arg: Int): String {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create actual class for platform JS" "true"
|
||||
|
||||
expect sealed class Sealed
|
||||
|
||||
expect object Obj : Sealed
|
||||
|
||||
expect class <caret>Klass(x: Int) : Sealed
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Create actual class for platform JS" "true"
|
||||
|
||||
expect sealed class Sealed
|
||||
|
||||
expect object Obj : Sealed
|
||||
|
||||
expect class Klass(x: Int) : Sealed
|
||||
@@ -0,0 +1,5 @@
|
||||
// Sealed: to be implemented
|
||||
|
||||
actual sealed class Sealed
|
||||
|
||||
actual object Obj : Sealed()
|
||||
@@ -0,0 +1,6 @@
|
||||
// Sealed: to be implemented
|
||||
|
||||
actual sealed class Sealed
|
||||
|
||||
actual object Obj : Sealed()
|
||||
actual class Klass actual constructor(x: Int) : Sealed
|
||||
@@ -23,9 +23,9 @@ import org.junit.Test
|
||||
|
||||
class QuickFixMultiModuleTest : AbstractQuickFixMultiModuleTest() {
|
||||
private fun doMultiPlatformTest(
|
||||
expectName: String = "header", // todo: change dir name
|
||||
vararg impls: Pair<String, TargetPlatformKind<*>> = arrayOf("jvm" to TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]),
|
||||
withTests: Boolean = false
|
||||
expectName: String = "header", // todo: change dir name
|
||||
vararg impls: Pair<String, TargetPlatformKind<*>> = arrayOf("jvm" to TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]),
|
||||
withTests: Boolean = false
|
||||
) {
|
||||
val commonModule = module(expectName, hasTestRoot = withTests)
|
||||
commonModule.createFacet(TargetPlatformKind.Common, false)
|
||||
@@ -40,7 +40,7 @@ class QuickFixMultiModuleTest : AbstractQuickFixMultiModuleTest() {
|
||||
doQuickFixTest()
|
||||
}
|
||||
|
||||
private fun doTestHeaderWithJvmAndJs(expectName: String = "header") {
|
||||
private fun doTestHeaderWithJvmAndJs() {
|
||||
doMultiPlatformTest(impls = *arrayOf("jvm" to TargetPlatformKind.Jvm[JvmTarget.JVM_1_6], "js" to TargetPlatformKind.JavaScript))
|
||||
}
|
||||
|
||||
@@ -109,6 +109,11 @@ class QuickFixMultiModuleTest : AbstractQuickFixMultiModuleTest() {
|
||||
doMultiPlatformTest()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFunctionSameFile() {
|
||||
doMultiPlatformTest()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInterface() {
|
||||
doMultiPlatformTest()
|
||||
@@ -169,6 +174,11 @@ class QuickFixMultiModuleTest : AbstractQuickFixMultiModuleTest() {
|
||||
doMultiPlatformTest(impls = *arrayOf("js" to TargetPlatformKind.JavaScript))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSealedSubclass() {
|
||||
doMultiPlatformTest(impls = *arrayOf("js" to TargetPlatformKind.JavaScript))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSecondaryConstructorAbsence() {
|
||||
doMultiPlatformTest()
|
||||
@@ -265,14 +275,14 @@ class QuickFixMultiModuleTest : AbstractQuickFixMultiModuleTest() {
|
||||
fun testCreateVarInExpectClass() = doMultiPlatformTest()
|
||||
|
||||
@Test
|
||||
fun testConvertExpectSealedClassToEnum() = doTestHeaderWithJvmAndJs("header")
|
||||
fun testConvertExpectSealedClassToEnum() = doTestHeaderWithJvmAndJs()
|
||||
|
||||
@Test
|
||||
fun testConvertActualSealedClassToEnum() = doTestHeaderWithJvmAndJs("js")
|
||||
fun testConvertActualSealedClassToEnum() = doTestHeaderWithJvmAndJs()
|
||||
|
||||
@Test
|
||||
fun testConvertExpectEnumToSealedClass() = doTestHeaderWithJvmAndJs("header")
|
||||
fun testConvertExpectEnumToSealedClass() = doTestHeaderWithJvmAndJs()
|
||||
|
||||
@Test
|
||||
fun testConvertActualEnumToSealedClass() = doTestHeaderWithJvmAndJs("js")
|
||||
fun testConvertActualEnumToSealedClass() = doTestHeaderWithJvmAndJs()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user