Expand "Create expected..." also to a members if an expect class doesn't exist

#KT-31272 Fixed
This commit is contained in:
Dmitry Gridin
2019-05-21 12:03:57 +07:00
parent 47e3a26749
commit f2bd58c030
7 changed files with 78 additions and 11 deletions
@@ -74,27 +74,39 @@ sealed class CreateExpectedFix<D : KtNamedDeclaration>(
// For function we allow it, because overloads are possible // For function we allow it, because overloads are possible
if (compatibility.isNotEmpty() && declaration !is KtFunction) return emptyList() if (compatibility.isNotEmpty() && declaration !is KtFunction) return emptyList()
val containingClass = declaration.containingClassOrObject val (actualDeclaration, expectedContainingClass) = findFirstActualWithExpectedClass(declaration)
val expectedContainingClass = containingClass?.liftToExpected() as? KtClassOrObject if (compatibility.isNotEmpty() && actualDeclaration !is KtFunction) return emptyList()
if (containingClass != null && expectedContainingClass == null) {
// In this case fix should be invoked on containingClass
return emptyList()
}
// If there is already an expected class, we suggest only for its module, // If there is already an expected class, we suggest only for its module,
// otherwise we suggest for all relevant expected modules // otherwise we suggest for all relevant expected modules
val expectedModules = expectedContainingClass?.module?.let { listOf(it) } val expectedModules = expectedContainingClass?.module?.let { listOf(it) }
?: declaration.module?.implementedModules ?: actualDeclaration.module?.implementedModules
?: return emptyList() ?: return emptyList()
return when (declaration) { return when (actualDeclaration) {
is KtClassOrObject -> expectedModules.map { CreateExpectedClassFix(declaration, expectedContainingClass, it) } is KtClassOrObject -> expectedModules.map { CreateExpectedClassFix(actualDeclaration, expectedContainingClass, it) }
is KtFunction -> expectedModules.map { CreateExpectedFunctionFix(declaration, expectedContainingClass, it) } is KtFunction -> expectedModules.map { CreateExpectedFunctionFix(actualDeclaration, expectedContainingClass, it) }
is KtProperty, is KtParameter -> expectedModules.map { CreateExpectedPropertyFix(declaration, expectedContainingClass, it) } is KtProperty, is KtParameter -> expectedModules.map {
CreateExpectedPropertyFix(
actualDeclaration,
expectedContainingClass,
it
)
}
else -> emptyList() else -> emptyList()
} }
} }
} }
} }
private tailrec fun findFirstActualWithExpectedClass(declaration: KtNamedDeclaration): Pair<KtNamedDeclaration, KtClassOrObject?> {
val containingClass = declaration.containingClassOrObject
val expectedContainingClass = containingClass?.liftToExpected() as? KtClassOrObject
return if (containingClass != null && expectedContainingClass == null)
findFirstActualWithExpectedClass(containingClass)
else
declaration to expectedContainingClass
}
class CreateExpectedClassFix( class CreateExpectedClassFix(
klass: KtClassOrObject, klass: KtClassOrObject,
outerExpectedClass: KtClassOrObject?, outerExpectedClass: KtClassOrObject?,
@@ -1,6 +1,7 @@
// "Create expected function in common module testModule_Common" "false" // "Create expected function in common module testModule_Common" "false"
// ACTION: Convert member to extension // ACTION: Convert member to extension
// ACTION: Convert to block body // ACTION: Convert to block body
// ACTION: Create expected class in common module testModule_Common
// ACTION: Move to companion object // ACTION: Move to companion object
// ACTION: Remove 'actual' modifier // ACTION: Remove 'actual' modifier
// ACTION: Remove explicit type specification // ACTION: Remove explicit type specification
@@ -0,0 +1,11 @@
expect class <caret>My {
fun foo(param: String): Int
fun String.bar(y: Double): Boolean
fun baz()
constructor(flag: Boolean)
val isGood: Boolean
var status: Int
}
@@ -0,0 +1,19 @@
// "Create expected class in common module testModule_Common" "true"
// DISABLE-ERRORS
actual class My {
actual fun <caret>foo(param: String): Int = 42
actual fun String.bar(y: Double): Boolean = true
actual fun baz() {}
actual constructor(flag: Boolean) {}
actual val isGood: Boolean
get() = true
actual var status: Int
get() = 0
set(value) {}
}
@@ -0,0 +1,19 @@
// "Create expected class in common module testModule_Common" "true"
// DISABLE-ERRORS
actual class My {
actual fun <caret>foo(param: String): Int = 42
actual fun String.bar(y: Double): Boolean = true
actual fun baz() {}
actual constructor(flag: Boolean) {}
actual val isGood: Boolean
get() = true
actual var status: Int
get() = 0
set(value) {}
}
@@ -299,6 +299,11 @@ public class QuickFixMultiModuleTestGenerated extends AbstractQuickFixMultiModul
runTest("idea/testData/multiModuleQuickFix/expectClassNoAccessOnMember/"); runTest("idea/testData/multiModuleQuickFix/expectClassNoAccessOnMember/");
} }
@TestMetadata("expectClassOnMember")
public void testExpectClassOnMember() throws Exception {
runTest("idea/testData/multiModuleQuickFix/expectClassOnMember/");
}
@TestMetadata("expectClassProperty") @TestMetadata("expectClassProperty")
public void testExpectClassProperty() throws Exception { public void testExpectClassProperty() throws Exception {
runTest("idea/testData/multiModuleQuickFix/expectClassProperty/"); runTest("idea/testData/multiModuleQuickFix/expectClassProperty/");