diff options
7 files changed, 258 insertions, 1 deletions
diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt index 1a0763f4d..5c740eb98 100644 --- a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt +++ b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt @@ -2,8 +2,13 @@ package org.jetbrains.dokka.Formats import org.jetbrains.dokka.DocumentationModule import org.jetbrains.dokka.ExternalDocumentationLinkResolver.Companion.DOKKA_PARAM_PREFIX +import org.jetbrains.dokka.InboundExternalLinkResolutionService import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.PackageListService +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject +import org.jetbrains.kotlin.types.KotlinType class JavaLayoutHtmlPackageListService : PackageListService { @@ -19,10 +24,91 @@ class JavaLayoutHtmlPackageListService : PackageListService { return buildString { appendParam("format", "java-layout-html") + appendParam("mode", "kotlin") for (p in packages) { appendln(p) } } } +} + +class JavaLayoutHtmlInboundLinkResolutionService(private val paramMap: Map<String, List<String>>) : InboundExternalLinkResolutionService { + private fun getContainerPath(symbol: DeclarationDescriptor): String? { + return when (symbol) { + is PackageFragmentDescriptor -> symbol.fqName.asString() + "/" + is ClassifierDescriptor -> getContainerPath(symbol.findPackage()) + symbol.nameWithOuter() + ".html" + else -> null + } + } + + private fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor = + generateSequence(this) { it.containingDeclaration }.filterIsInstance<PackageFragmentDescriptor>().first() + + private fun ClassifierDescriptor.nameWithOuter(): String = + generateSequence(this) { it.containingDeclaration as? ClassifierDescriptor } + .toList().asReversed().joinToString(".") { it.name.asString() } + + private fun getPagePath(symbol: DeclarationDescriptor): String? { + return when (symbol) { + is PackageFragmentDescriptor -> getContainerPath(symbol) + "package-summary.html" + is ClassifierDescriptor -> getContainerPath(symbol) + "#" + is FunctionDescriptor, is PropertyDescriptor -> getContainerPath(symbol.containingDeclaration!!) + "#" + symbol.signatureForAnchorUrlEncoded() + else -> null + } + } + + private fun DeclarationDescriptor.signatureForAnchor(): String? { + + fun ReceiverParameterDescriptor.extractReceiverName(): String { + var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!! + if (receiverClass.isCompanionObject()) { + receiverClass = receiverClass.containingDeclaration!! + } else if (receiverClass is TypeParameterDescriptor) { + val upperBoundClass = receiverClass.upperBounds.singleOrNull()?.constructor?.declarationDescriptor + if (upperBoundClass != null) { + receiverClass = upperBoundClass + } + } + + return receiverClass.name.asString() + } + + fun KotlinType.qualifiedNameForSignature(): String { + val desc = constructor.declarationDescriptor + return desc?.fqNameUnsafe?.asString() ?: "<ERROR TYPE NAME>" + } + + fun StringBuilder.appendReceiverAndCompanion(desc: CallableDescriptor) { + if (desc.containingDeclaration.isCompanionObject()) { + append("Companion.") + } + desc.extensionReceiverParameter?.let { + append("(") + append(it.extractReceiverName()) + append(").") + } + } + + return when(this) { + is FunctionDescriptor -> buildString { + appendReceiverAndCompanion(this@signatureForAnchor) + append(name.asString()) + valueParameters.joinTo(this, prefix = "(", postfix = ")") { + it.type.qualifiedNameForSignature() + } + } + is PropertyDescriptor -> buildString { + appendReceiverAndCompanion(this@signatureForAnchor) + append(name.asString()) + append(":") + append(returnType?.qualifiedNameForSignature()) + } + else -> null + } + } + + private fun DeclarationDescriptor.signatureForAnchorUrlEncoded(): String? = signatureForAnchor()?.urlEncoded() + + override fun getPath(symbol: DeclarationDescriptor) = getPagePath(symbol) }
\ No newline at end of file diff --git a/core/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties b/core/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties new file mode 100644 index 000000000..3b61eabe7 --- /dev/null +++ b/core/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.JavaLayoutHtmlInboundLinkResolutionService +description=Resolver for JavaLayoutHtml
\ No newline at end of file diff --git a/core/src/test/kotlin/format/JavaLayoutHtmlFormatTest.kt b/core/src/test/kotlin/format/JavaLayoutHtmlFormatTest.kt index 160b3cb43..fae8f275d 100644 --- a/core/src/test/kotlin/format/JavaLayoutHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/JavaLayoutHtmlFormatTest.kt @@ -1,8 +1,10 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.* import org.jetbrains.dokka.Formats.JavaLayoutHtmlFormatDescriptor -import org.jetbrains.dokka.NodeKind import org.junit.Test +import java.io.File +import java.net.URL class JavaLayoutHtmlFormatTest : JavaLayoutHtmlFormatTestCase() { override val formatDescriptor = JavaLayoutHtmlFormatDescriptor() @@ -55,4 +57,49 @@ class JavaLayoutHtmlFormatTest : JavaLayoutHtmlFormatTestCase() { fun constJava() { verifyNode("ConstJava.java", noStdlibLink = true) } + + @Test + fun inboundLinksInKotlinMode() { + val root = "./testdata/format/java-layout-html" + + val options = DocumentationOptions( + "", + "java-layout-html", + sourceLinks = listOf(), + generateIndexPages = false, + noStdlibLink = true, + apiVersion = null, + languageVersion = null, + perPackageOptions = listOf(PackageOptionsImpl("foo", suppress = true)), + externalDocumentationLinks = + listOf( + DokkaConfiguration.ExternalDocumentationLink.Builder( + URL("file:///"), + File(root, "inboundLinksTestPackageList").toURI().toURL() + ).build() + ) + ) + + + val sourcePath = "$root/inboundLinksInKotlinMode.kt" + val documentation = DocumentationModule("test") + + appendDocumentation( + documentation, + contentRootFromPath(sourcePath), + contentRootFromPath("$root/inboundLinksInKotlinMode.Dep.kt"), + withJdk = false, + withKotlinRuntime = false, + options = options + ) + documentation.prepareForGeneration(options) + + verifyModelOutput(documentation, ".html", sourcePath) { model, output -> + buildPagesAndReadInto( + model, + model.members.single { it.name == "bar" }.members, + output + ) + } + } }
\ No newline at end of file diff --git a/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.Dep.kt b/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.Dep.kt new file mode 100644 index 000000000..610ebb221 --- /dev/null +++ b/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.Dep.kt @@ -0,0 +1,23 @@ +package foo + + +fun foobar() { + +} + + +val v = 22 + +class G { + + fun oo() = "" + + val og = 11 + + companion object { + + fun dg() = "22" + + val dv = 12 + } +}
\ No newline at end of file diff --git a/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.html b/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.html new file mode 100644 index 000000000..7025fc771 --- /dev/null +++ b/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.html @@ -0,0 +1,80 @@ +<!-- File: /test/bar/X.html# --> +<html> + <head> + <meta charset="UTF-8"> + </head> + <body> + <h1>X</h1> + <pre><span class="keyword">class </span><span class="identifier">X</span></pre> + <table> + <tr> + <td><a href="#">bar.X</a></td> + </tr> + </table> + <p>See <a href="file:/foo/#foobar%28%29">foo.foobar</a> +See <a href="file:/foo/#v%3Akotlin.Int">foo.v</a> +See <a href="file:/foo/G.html#">foo.G</a> +See <a href="file:/foo/G.html#oo%28%29">foo.G.oo</a> +See <a href="file:/foo/G.html#og%3Akotlin.Int">foo.G.og</a> +See <a href="file:/foo/G.Companion.html#Companion.dg%28%29">foo.G.Companion.dg</a> +See <a href="file:/foo/G.Companion.html#Companion.dv%3Akotlin.Int">foo.G.Companion.dv</a></p> + <h2>Summary</h2> + <table> + <thead> + <tr> + <td> + <h3>Constructors</h3> + </td> + </tr> + </thead> + <tbody> + <tr> + <td> + <div><code><a href="#%3Cinit%3E%28%29"><init></a>()</code></div> + <p>See <a href="file:/foo/#foobar%28%29">foo.foobar</a> +See <a href="file:/foo/#v%3Akotlin.Int">foo.v</a> +See <a href="file:/foo/G.html#">foo.G</a> +See <a href="file:/foo/G.html#oo%28%29">foo.G.oo</a> +See <a href="file:/foo/G.html#og%3Akotlin.Int">foo.G.og</a> +See <a href="file:/foo/G.Companion.html#Companion.dg%28%29">foo.G.Companion.dg</a> +See <a href="file:/foo/G.Companion.html#Companion.dv%3Akotlin.Int">foo.G.Companion.dv</a></p> + </td> + </tr> + </tbody> + </table> + <table> + <thead> + <tr> + <td> + <h3>Functions</h3> + </td> + </tr> + </thead> + <tbody> + <tr> + <td><span class="identifier">String</span></td> + <td> + <div><code><a href="file:/foo/G.html#"><span class="identifier">G</span></a>.<a href="#%28foo.G%29.ext%28%29">ext</a>()</code></div> + </td> + </tr> + </tbody> + </table> + <h2>Constructors</h2> + <div id="<init>()"> + <h3><init></h3> + <pre><span class="identifier">X</span><span class="symbol">(</span><span class="symbol">)</span></pre> + <p>See <a href="file:/foo/#foobar%28%29">foo.foobar</a> +See <a href="file:/foo/#v%3Akotlin.Int">foo.v</a> +See <a href="file:/foo/G.html#">foo.G</a> +See <a href="file:/foo/G.html#oo%28%29">foo.G.oo</a> +See <a href="file:/foo/G.html#og%3Akotlin.Int">foo.G.og</a> +See <a href="file:/foo/G.Companion.html#Companion.dg%28%29">foo.G.Companion.dg</a> +See <a href="file:/foo/G.Companion.html#Companion.dv%3Akotlin.Int">foo.G.Companion.dv</a></p> + </div> + <h2>Functions</h2> + <div id="(foo.G).ext()"> + <h3>ext</h3> + <pre><span class="keyword">fun </span><a href="file:/foo/G.html#"><span class="identifier">G</span></a><span class="symbol">.</span><span class="identifier">ext</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">String</span></pre> + </div> + </body> +</html> diff --git a/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.kt b/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.kt new file mode 100644 index 000000000..6420d7876 --- /dev/null +++ b/core/testdata/format/java-layout-html/inboundLinksInKotlinMode.kt @@ -0,0 +1,16 @@ +package bar + +/** + * See [foo.foobar] + * See [foo.v] + * See [foo.G] + * See [foo.G.oo] + * See [foo.G.og] + * See [foo.G.Companion.dg] + * See [foo.G.Companion.dv] + */ +class X { + + fun (foo.G).ext() = this.oo() +} + diff --git a/core/testdata/format/java-layout-html/inboundLinksTestPackageList b/core/testdata/format/java-layout-html/inboundLinksTestPackageList new file mode 100644 index 000000000..64d25c312 --- /dev/null +++ b/core/testdata/format/java-layout-html/inboundLinksTestPackageList @@ -0,0 +1,3 @@ +$dokka.format:java-layout-html +$dokka.mode:kotlin +foo |