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? {
|
fun getPlatformActualTooltip(declaration: KtDeclaration?): String? {
|
||||||
val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return null
|
val descriptor = declaration?.toDescriptor() as? MemberDescriptor ?: return null
|
||||||
val commonModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
val commonModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
||||||
|
|
||||||
val platformModulesWithActuals = commonModuleDescriptor.implementingDescriptors.filter {
|
val platformModulesWithActuals = commonModuleDescriptor.implementingDescriptors.filter {
|
||||||
@@ -58,13 +58,13 @@ fun getPlatformActualTooltip(declaration: KtDeclaration): String? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToPlatformActual(e: MouseEvent?, declaration: KtDeclaration) {
|
fun navigateToPlatformActual(e: MouseEvent?, declaration: KtDeclaration?) {
|
||||||
val actuals = declaration.actualsForExpected()
|
val actualDeclarations = declaration?.actualsForExpected() ?: return
|
||||||
if (actuals.isEmpty()) return
|
if (actualDeclarations.isEmpty()) return
|
||||||
|
|
||||||
val renderer = DefaultPsiElementCellRenderer()
|
val renderer = DefaultPsiElementCellRenderer()
|
||||||
PsiElementListNavigator.openTargets(e,
|
PsiElementListNavigator.openTargets(e,
|
||||||
actuals.toTypedArray(),
|
actualDeclarations.toTypedArray(),
|
||||||
"Choose actual for ${declaration.name}",
|
"Choose actual for ${declaration.name}",
|
||||||
"Actuals for ${declaration.name}",
|
"Actuals for ${declaration.name}",
|
||||||
renderer)
|
renderer)
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ private fun ModuleDescriptor.declarationOf(descriptor: MemberDescriptor): Declar
|
|||||||
descriptor.findCompatibleExpectedForActual(this@declarationOf).firstOrNull()
|
descriptor.findCompatibleExpectedForActual(this@declarationOf).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getExpectedDeclarationTooltip(declaration: KtDeclaration): String? {
|
fun getExpectedDeclarationTooltip(declaration: KtDeclaration?): String? {
|
||||||
val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return null
|
val descriptor = declaration?.toDescriptor() as? MemberDescriptor ?: return null
|
||||||
val platformModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
val platformModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
||||||
|
|
||||||
val commonModuleDescriptor = platformModuleDescriptor.commonModuleOrNull() ?: return null
|
val commonModuleDescriptor = platformModuleDescriptor.commonModuleOrNull() ?: return null
|
||||||
@@ -68,8 +68,8 @@ fun getExpectedDeclarationTooltip(declaration: KtDeclaration): String? {
|
|||||||
return "Has declaration in common module"
|
return "Has declaration in common module"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToExpectedDeclaration(declaration: KtDeclaration) {
|
fun navigateToExpectedDeclaration(declaration: KtDeclaration?) {
|
||||||
declaration.expectedDeclarationIfAny()?.navigate(false)
|
declaration?.expectedDeclarationIfAny()?.navigate(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun MemberDescriptor.expectedDescriptor() = module.commonModuleOrNull()?.declarationOf(this)
|
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(
|
private val PLATFORM_ACTUAL = MarkerType(
|
||||||
"PLATFORM_ACTUAL",
|
"PLATFORM_ACTUAL",
|
||||||
{ it?.let { getPlatformActualTooltip(it.parent as KtDeclaration) } },
|
{ it?.let { getPlatformActualTooltip(it.markerDeclaration) } },
|
||||||
object : LineMarkerNavigator() {
|
object : LineMarkerNavigator() {
|
||||||
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
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(
|
private val EXPECTED_DECLARATION = MarkerType(
|
||||||
"EXPECTED_DECLARATION",
|
"EXPECTED_DECLARATION",
|
||||||
{ it?.let { getExpectedDeclarationTooltip(it.parent as KtDeclaration) } },
|
{ it?.let { getExpectedDeclarationTooltip(it.markerDeclaration) } },
|
||||||
object : LineMarkerNavigator() {
|
object : LineMarkerNavigator() {
|
||||||
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
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,
|
private fun collectActualMarkers(declaration: KtNamedDeclaration,
|
||||||
result: MutableCollection<LineMarkerInfo<*>>) {
|
result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
|
||||||
@@ -294,7 +300,7 @@ private fun collectActualMarkers(declaration: KtNamedDeclaration,
|
|||||||
|
|
||||||
if (commonModuleDescriptor.implementingDescriptors.none { it.hasActualsFor(descriptor) }) return
|
if (commonModuleDescriptor.implementingDescriptors.none { it.hasActualsFor(descriptor) }) return
|
||||||
|
|
||||||
val anchor = declaration.nameIdentifier ?: declaration
|
val anchor = declaration.expectOrActualAnchor
|
||||||
|
|
||||||
result.add(LineMarkerInfo(
|
result.add(LineMarkerInfo(
|
||||||
anchor,
|
anchor,
|
||||||
@@ -315,7 +321,7 @@ private fun collectExpectedMarkers(declaration: KtNamedDeclaration,
|
|||||||
val commonModuleDescriptor = platformModuleDescriptor.commonModuleOrNull() ?: return
|
val commonModuleDescriptor = platformModuleDescriptor.commonModuleOrNull() ?: return
|
||||||
if (!commonModuleDescriptor.hasDeclarationOf(descriptor)) return
|
if (!commonModuleDescriptor.hasDeclarationOf(descriptor)) return
|
||||||
|
|
||||||
val anchor = declaration.nameIdentifier ?: declaration
|
val anchor = declaration.expectOrActualAnchor
|
||||||
|
|
||||||
result.add(LineMarkerInfo(
|
result.add(LineMarkerInfo(
|
||||||
anchor,
|
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
|
override fun doTestLineMarkers() = true
|
||||||
|
|
||||||
|
fun testFromActualSecondaryConstructor() {
|
||||||
|
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFromClassToAlias() {
|
||||||
|
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||||
|
}
|
||||||
|
|
||||||
fun testFromCommonToJvmHeader() {
|
fun testFromCommonToJvmHeader() {
|
||||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||||
}
|
}
|
||||||
@@ -42,18 +50,10 @@ class MultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() {
|
|||||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testFromClassToAlias() {
|
fun testFromExpectedSecondaryConstructor() {
|
||||||
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
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() {
|
fun testKotlinTestAnnotations() {
|
||||||
doMultiPlatformTest(TargetPlatformKind.JavaScript,
|
doMultiPlatformTest(TargetPlatformKind.JavaScript,
|
||||||
configureModule = { module, _ ->
|
configureModule = { module, _ ->
|
||||||
@@ -66,6 +66,10 @@ class MultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testSuspendImplInPlatformModules() {
|
||||||
|
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6], TargetPlatformKind.JavaScript)
|
||||||
|
}
|
||||||
|
|
||||||
fun testTransitive() {
|
fun testTransitive() {
|
||||||
val commonModule = module("common", TestJdkKind.MOCK_JDK)
|
val commonModule = module("common", TestJdkKind.MOCK_JDK)
|
||||||
commonModule.createFacet(TargetPlatformKind.Common, false)
|
commonModule.createFacet(TargetPlatformKind.Common, false)
|
||||||
@@ -84,4 +88,8 @@ class MultiModuleLineMarkerTest : AbstractMultiModuleHighlightingTest() {
|
|||||||
|
|
||||||
checkHighlightingInAllFiles()
|
checkHighlightingInAllFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testWithOverloads() {
|
||||||
|
doMultiPlatformTest(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user