Expect/actual markers: handle secondary constructors correctly

So #KT-20309 Fixed
This commit is contained in:
Mikhail Glukhikh
2017-10-06 17:27:13 +03:00
parent 26136cd0fe
commit ceab148b09
8 changed files with 59 additions and 25 deletions
@@ -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,
@@ -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) {}
}
@@ -0,0 +1,3 @@
expect class <lineMarker>SecondaryConstructor</lineMarker>{
constructor(name: String, surname: String)
}
@@ -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])
}
}