From 7b3bc6f97ee46981bd88852a50ee4a351bd4879d Mon Sep 17 00:00:00 2001
From: Marcin Aman <marcin.aman@gmail.com>
Date: Wed, 16 Dec 2020 10:25:34 +0100
Subject: Resolve an issue with cross package linking in javadoc (#1659)

---
 .../javadoc/location/JavadocLocationProvider.kt    |  6 ++--
 .../dokka/javadoc/location/JavadocLocationTest.kt  | 33 ++++++++++++++++++----
 2 files changed, 31 insertions(+), 8 deletions(-)

(limited to 'plugins')

diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
index 440bfc2f..11d8420a 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationProvider.kt
@@ -63,9 +63,9 @@ class JavadocLocationProvider(pageRoot: RootPageNode, dokkaContext: DokkaContext
     private operator fun IdentityHashMap<PageNode, List<String>>.get(dri: DRI) = this[nodeIndex[dri]]
 
     private fun List<String>.relativeTo(context: List<String>): String {
-        val contextPath = context.dropLast(1)
-        val commonPathElements = zip(contextPath).takeWhile { (a, b) -> a == b }.count()
-        return (List(contextPath.size - commonPathElements) { ".." } + this.drop(commonPathElements)).joinToString("/")
+        val contextPath = context.dropLast(1).flatMap { it.split("/") }
+        val commonPathElements = flatMap { it.split("/") }.zip(contextPath).takeWhile { (a, b) -> a == b }.count()
+        return (List(contextPath.size - commonPathElements) { ".." } + this.flatMap { it.split("/") }.drop(commonPathElements)).joinToString("/")
     }
 
     private fun JavadocClasslikePageNode.findAnchorableByDRI(dri: DRI): AnchorableJavadocNode? =
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
index 26a6aaff..7abbeca8 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
@@ -40,6 +40,13 @@ class JavadocLocationTest : BaseAbstractTest() {
             |   fun test2(s: String) {}
             |   fun <T> test3(a: A, t: T) {}
             |}
+            |
+            |/jvmSrc/another/javadoc/example/Referenced.kt
+            |package javadoc.example.another
+            |/**
+            |  * Referencing element from another package: [javadoc.test.Test]
+            | */
+            |class Referenced {}
         """.trimIndent(),
             config,
             cleanupOutput = false,
@@ -52,7 +59,7 @@ class JavadocLocationTest : BaseAbstractTest() {
 
         locationTestInline { rootPageNode, dokkaContext ->
             val transformer = htmlTranslator(rootPageNode, dokkaContext)
-            val testClass = rootPageNode.firstChildOfType<JavadocPackagePageNode>()
+            val testClass = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
                 .firstChildOfType<JavadocClasslikePageNode>()
             assertEquals(
                 " implements <a href=https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html>Serializable</a>, <a href=https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html>Cloneable</a>",
@@ -66,7 +73,7 @@ class JavadocLocationTest : BaseAbstractTest() {
 
         locationTestInline { rootPageNode, dokkaContext ->
             val transformer = htmlTranslator(rootPageNode, dokkaContext)
-            val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode>()
+            val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
                 .firstChildOfType<JavadocClasslikePageNode> { it.name == "Test" }
             val testFunctionNode = testClassNode.methods.first { it.name == "test" }
             assertEquals(
@@ -84,7 +91,7 @@ class JavadocLocationTest : BaseAbstractTest() {
 
         locationTestInline { rootPageNode, dokkaContext ->
             val transformer = htmlTranslator(rootPageNode, dokkaContext)
-            val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode>()
+            val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
                 .firstChildOfType<JavadocClasslikePageNode> { it.name == "Test" }
             val testFunctionNode = testClassNode.methods.first { it.name == "test2" }
             assertEquals(
@@ -102,7 +109,7 @@ class JavadocLocationTest : BaseAbstractTest() {
 
         locationTestInline { rootPageNode, dokkaContext ->
             val transformer = htmlTranslator(rootPageNode, dokkaContext)
-            val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode>()
+            val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.test" }
                 .firstChildOfType<JavadocClasslikePageNode> { it.name == "Test" }
             val testFunctionNode = testClassNode.methods.first { it.name == "test3" }
             assertEquals(
@@ -121,13 +128,29 @@ class JavadocLocationTest : BaseAbstractTest() {
         locationTestInline { rootPageNode, dokkaContext ->
             val locationProvider = dokkaContext.plugin<JavadocPlugin>().querySingle { locationProviderFactory }
                 .getLocationProvider(rootPageNode)
-            val packageNode = rootPageNode.firstChildOfType<JavadocPackagePageNode>()
+            val packageNode = rootPageNode.firstChildOfType<JavadocPackagePageNode>() { it.name == "javadoc.test" }
             val packagePath = locationProvider.resolve(packageNode)
 
             assertEquals("javadoc/test/package-summary", packagePath)
         }
     }
 
+    @Test
+    fun `resolve link from another package`(){
+        locationTestInline { rootPageNode, dokkaContext ->
+            val transformer = htmlTranslator(rootPageNode, dokkaContext)
+            val testClassNode = rootPageNode.firstChildOfType<JavadocPackagePageNode> { it.name == "javadoc.example.another" }
+                .firstChildOfType<JavadocClasslikePageNode> { it.name == "Referenced" }
+            assertEquals(
+                """<p>Referencing element from another package: <a href=../../test/Test.html>javadoc.test.Test</a></p>""",
+                transformer.htmlForContentNode(
+                    testClassNode.description.single(),
+                    testClassNode
+                )
+            )
+        }
+    }
+
     private fun htmlTranslator(rootPageNode: RootPageNode, dokkaContext: DokkaContext): JavadocContentToHtmlTranslator {
         val locationProvider = dokkaContext.plugin<JavadocPlugin>().querySingle { locationProviderFactory }
             .getLocationProvider(rootPageNode) as JavadocLocationProvider
-- 
cgit