Expect/actual markers: handle secondary constructors correctly
So #KT-20309 Fixed
This commit is contained in:
@@ -44,8 +44,8 @@ fun ModuleDescriptor.actualsFor(descriptor: MemberDescriptor, checkCompatible: B
|
||||
}
|
||||
}
|
||||
|
||||
fun getPlatformActualTooltip(declaration: KtDeclaration): String? {
|
||||
val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return null
|
||||
fun getPlatformActualTooltip(declaration: KtDeclaration?): String? {
|
||||
val descriptor = declaration?.toDescriptor() as? MemberDescriptor ?: return null
|
||||
val commonModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
||||
|
||||
val platformModulesWithActuals = commonModuleDescriptor.implementingDescriptors.filter {
|
||||
@@ -58,13 +58,13 @@ fun getPlatformActualTooltip(declaration: KtDeclaration): String? {
|
||||
}
|
||||
}
|
||||
|
||||
fun navigateToPlatformActual(e: MouseEvent?, declaration: KtDeclaration) {
|
||||
val actuals = declaration.actualsForExpected()
|
||||
if (actuals.isEmpty()) return
|
||||
fun navigateToPlatformActual(e: MouseEvent?, declaration: KtDeclaration?) {
|
||||
val actualDeclarations = declaration?.actualsForExpected() ?: return
|
||||
if (actualDeclarations.isEmpty()) return
|
||||
|
||||
val renderer = DefaultPsiElementCellRenderer()
|
||||
PsiElementListNavigator.openTargets(e,
|
||||
actuals.toTypedArray(),
|
||||
actualDeclarations.toTypedArray(),
|
||||
"Choose actual for ${declaration.name}",
|
||||
"Actuals for ${declaration.name}",
|
||||
renderer)
|
||||
|
||||
@@ -58,8 +58,8 @@ private fun ModuleDescriptor.declarationOf(descriptor: MemberDescriptor): Declar
|
||||
descriptor.findCompatibleExpectedForActual(this@declarationOf).firstOrNull()
|
||||
}
|
||||
|
||||
fun getExpectedDeclarationTooltip(declaration: KtDeclaration): String? {
|
||||
val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return null
|
||||
fun getExpectedDeclarationTooltip(declaration: KtDeclaration?): String? {
|
||||
val descriptor = declaration?.toDescriptor() as? MemberDescriptor ?: return null
|
||||
val platformModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
||||
|
||||
val commonModuleDescriptor = platformModuleDescriptor.commonModuleOrNull() ?: return null
|
||||
@@ -68,8 +68,8 @@ fun getExpectedDeclarationTooltip(declaration: KtDeclaration): String? {
|
||||
return "Has declaration in common module"
|
||||
}
|
||||
|
||||
fun navigateToExpectedDeclaration(declaration: KtDeclaration) {
|
||||
declaration.expectedDeclarationIfAny()?.navigate(false)
|
||||
fun navigateToExpectedDeclaration(declaration: KtDeclaration?) {
|
||||
declaration?.expectedDeclarationIfAny()?.navigate(false)
|
||||
}
|
||||
|
||||
internal fun MemberDescriptor.expectedDescriptor() = module.commonModuleOrNull()?.declarationOf(this)
|
||||
|
||||
@@ -182,22 +182,25 @@ private val OVERRIDDEN_PROPERTY = object : MarkerType(
|
||||
}
|
||||
}
|
||||
|
||||
private val PsiElement.markerDeclaration
|
||||
get() = (this as? KtDeclaration) ?: (parent as? KtDeclaration)
|
||||
|
||||
private val PLATFORM_ACTUAL = MarkerType(
|
||||
"PLATFORM_ACTUAL",
|
||||
{ it?.let { getPlatformActualTooltip(it.parent as KtDeclaration) } },
|
||||
{ it?.let { getPlatformActualTooltip(it.markerDeclaration) } },
|
||||
object : LineMarkerNavigator() {
|
||||
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||
element?.let { navigateToPlatformActual(e, it.parent as KtDeclaration) }
|
||||
element?.let { navigateToPlatformActual(e, it.markerDeclaration) }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private val EXPECTED_DECLARATION = MarkerType(
|
||||
"EXPECTED_DECLARATION",
|
||||
{ it?.let { getExpectedDeclarationTooltip(it.parent as KtDeclaration) } },
|
||||
{ it?.let { getExpectedDeclarationTooltip(it.markerDeclaration) } },
|
||||
object : LineMarkerNavigator() {
|
||||
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||
element?.let { navigateToExpectedDeclaration(it.parent as KtDeclaration) }
|
||||
element?.let { navigateToExpectedDeclaration(it.markerDeclaration) }
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -286,6 +289,9 @@ private fun collectOverriddenPropertyAccessors(properties: Collection<KtNamedDec
|
||||
}
|
||||
}
|
||||
|
||||
private val KtNamedDeclaration.expectOrActualAnchor
|
||||
get() = nameIdentifier ?: (this as? KtConstructor<*>)?.getConstructorKeyword() ?: this
|
||||
|
||||
private fun collectActualMarkers(declaration: KtNamedDeclaration,
|
||||
result: MutableCollection<LineMarkerInfo<*>>) {
|
||||
|
||||
@@ -294,7 +300,7 @@ private fun collectActualMarkers(declaration: KtNamedDeclaration,
|
||||
|
||||
if (commonModuleDescriptor.implementingDescriptors.none { it.hasActualsFor(descriptor) }) return
|
||||
|
||||
val anchor = declaration.nameIdentifier ?: declaration
|
||||
val anchor = declaration.expectOrActualAnchor
|
||||
|
||||
result.add(LineMarkerInfo(
|
||||
anchor,
|
||||
@@ -315,7 +321,7 @@ private fun collectExpectedMarkers(declaration: KtNamedDeclaration,
|
||||
val commonModuleDescriptor = platformModuleDescriptor.commonModuleOrNull() ?: return
|
||||
if (!commonModuleDescriptor.hasDeclarationOf(descriptor)) return
|
||||
|
||||
val anchor = declaration.nameIdentifier ?: declaration
|
||||
val anchor = declaration.expectOrActualAnchor
|
||||
|
||||
result.add(LineMarkerInfo(
|
||||
anchor,
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// !CHECK_HIGHLIGHTING
|
||||
|
||||
expect class SecondaryConstructor{
|
||||
constructor(name: String, surname: String)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
actual class <lineMarker>SecondaryConstructor</lineMarker> {
|
||||
actual <lineMarker>constructor</lineMarker>(name: String, surname: String) {}
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
expect class <lineMarker>SecondaryConstructor</lineMarker>{
|
||||
constructor(name: String, surname: String)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// !CHECK_HIGHLIGHTING
|
||||
|
||||
actual class SecondaryConstructor {
|
||||
actual constructor(name: String, surname: String) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,14 @@ class MultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() {
|
||||
|
||||
override fun doTestLineMarkers() = true
|
||||
|
||||
fun testFromActualSecondaryConstructor() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||
}
|
||||
|
||||
fun testFromClassToAlias() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||
}
|
||||
|
||||
fun testFromCommonToJvmHeader() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||
}
|
||||
@@ -42,18 +50,10 @@ class MultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||
}
|
||||
|
||||
fun testFromClassToAlias() {
|
||||
fun testFromExpectedSecondaryConstructor() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||
}
|
||||
|
||||
fun testWithOverloads() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||
}
|
||||
|
||||
fun testSuspendImplInPlatformModules() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6], TargetPlatformKind.JavaScript)
|
||||
}
|
||||
|
||||
fun testKotlinTestAnnotations() {
|
||||
doMultiPlatformTest(TargetPlatformKind.JavaScript,
|
||||
configureModule = { module, _ ->
|
||||
@@ -66,6 +66,10 @@ class MultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() {
|
||||
})
|
||||
}
|
||||
|
||||
fun testSuspendImplInPlatformModules() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6], TargetPlatformKind.JavaScript)
|
||||
}
|
||||
|
||||
fun testTransitive() {
|
||||
val commonModule = module("common", TestJdkKind.MOCK_JDK)
|
||||
commonModule.createFacet(TargetPlatformKind.Common, false)
|
||||
@@ -84,4 +88,8 @@ class MultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() {
|
||||
|
||||
checkHighlightingInAllFiles()
|
||||
}
|
||||
|
||||
fun testWithOverloads() {
|
||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user