aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorMarcin Aman <marcin.aman@gmail.com>2020-07-07 15:45:32 +0200
committerGitHub <noreply@github.com>2020-07-07 15:45:32 +0200
commit63823e14794136c23359aab9f40b8d8dcfe504dd (patch)
treef65f3aee6e6d4086bd217387116261a14de5a6cb /plugins
parent6c1403cd8ffab5e13f12a2744846a70b31710b09 (diff)
downloaddokka-63823e14794136c23359aab9f40b8d8dcfe504dd.tar.gz
dokka-63823e14794136c23359aab9f40b8d8dcfe504dd.tar.bz2
dokka-63823e14794136c23359aab9f40b8d8dcfe504dd.zip
Javadoc signature provider (#1041)
Javadoc signature provider #1025
Diffstat (limited to 'plugins')
-rw-r--r--plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt3
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt15
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt94
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt24
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocContentNodes.kt18
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt36
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/pages/htmlGeneration.kt391
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt15
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt54
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/signatures/JavadocSignatureProvider.kt196
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/translators/documentables/JavadocPageContentBuilder.kt80
-rw-r--r--plugins/javadoc/src/main/resources/views/class.korte30
-rw-r--r--plugins/javadoc/src/test/kotlin/javadoc/AbstractJavadocTemplateMapTest.kt2
-rw-r--r--plugins/javadoc/src/test/kotlin/javadoc/JavadocClasslikeTemplateMapTest.kt239
-rw-r--r--plugins/javadoc/src/test/kotlin/javadoc/location/JavadocLocationTest.kt4
15 files changed, 669 insertions, 532 deletions
diff --git a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
index 2a242948..689f6db5 100644
--- a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
+++ b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
@@ -21,9 +21,6 @@ interface JvmSignatureUtils {
fun <T : Documentable> WithExtraProperties<T>.annotations(): SourceSetDependent<List<Annotations.Annotation>> =
extra[Annotations]?.content ?: emptyMap()
- private fun Annotations.Annotation.toSignatureString(): String =
- "@" + this.dri.classNames + "(" + this.params.entries.joinToString { it.key + "=" + it.value } + ")"
-
private fun PageContentBuilder.DocumentableContentBuilder.annotations(
d: Documentable,
ignored: Set<Annotations.Annotation>,
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index 5a55e3ec..5e03be6e 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -317,10 +317,15 @@ class DefaultPsiToDocumentableTranslator(
is PsiClassReferenceType -> {
val resolved: PsiClass = type.resolve()
?: return UnresolvedBound(type.presentableText)
- if (resolved.qualifiedName == "java.lang.Object") {
- JavaObject
- } else {
- TypeConstructor(DRI.from(resolved), type.parameters.map { getProjection(it) })
+ when {
+ resolved.qualifiedName == "java.lang.Object" -> JavaObject
+ resolved is PsiTypeParameter && resolved.owner != null ->
+ OtherParameter(
+ declarationDRI = DRI.from(resolved.owner!!),
+ name = resolved.name.orEmpty()
+ )
+ else ->
+ TypeConstructor(DRI.from(resolved), type.parameters.map { getProjection(it) })
}
}
is PsiArrayType -> TypeConstructor(
@@ -443,7 +448,7 @@ class DefaultPsiToDocumentableTranslator(
attributes.filter { it !is KtLightAbstractAnnotation }.mapNotNull { it.attributeName to it.toValue() }
.toMap(),
(psiElement as PsiClass).annotations.any {
- hasQualifiedName("java.lang.annotation.Documented")
+ it.hasQualifiedName("java.lang.annotation.Documented")
}
)
}
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt
index ebe223e5..1bafa111 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt
@@ -9,13 +9,12 @@ import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentCon
import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter
import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.model.doc.Description
+import org.jetbrains.dokka.model.doc.NamedTagWrapper
+import org.jetbrains.dokka.model.doc.Param
import org.jetbrains.dokka.model.doc.TagWrapper
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.ContentKind
-import org.jetbrains.dokka.pages.ContentNode
-import org.jetbrains.dokka.pages.ContentText
-import org.jetbrains.dokka.pages.DCI
+import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.utilities.DokkaLogger
open class JavadocPageCreator(
@@ -43,20 +42,20 @@ open class JavadocPageCreator(
name = c.name.orEmpty(),
content = contentForClasslike(c),
dri = setOf(c.dri),
- modifiers = listOfNotNull(c.visibility[jvm]?.name),
- signature = signatureProvider.signature(c).nodeForJvm(jvm),
+ signature = signatureForNode(c, jvm),
description = c.descriptionToContentNodes(),
constructors = (c as? WithConstructors)?.constructors?.mapNotNull { it.toJavadocFunction() }.orEmpty(),
methods = c.functions.mapNotNull { it.toJavadocFunction() },
entries = (c as? DEnum)?.entries?.map {
JavadocEntryNode(
- signatureProvider.signature(it).nodeForJvm(jvm), it.descriptionToContentNodes(jvm)
+ signatureForNode(it, jvm),
+ it.descriptionToContentNodes(jvm)
)
}.orEmpty(),
classlikes = c.classlikes.mapNotNull { pageForClasslike(it) },
properties = c.properties.map {
JavadocPropertyNode(
- signatureProvider.signature(it).nodeForJvm(jvm),
+ signatureForNode(it, jvm),
it.descriptionToContentNodes(jvm)
)
},
@@ -71,7 +70,7 @@ open class JavadocPageCreator(
JavadocContentKind.OverviewSummary,
m.jvmSourceSets.toSet()
) {
- title(m.name, m.brief(),"0.0.1", dri = setOf(m.dri), kind = ContentKind.Main)
+ title(m.name, m.brief(), "0.0.1", dri = setOf(m.dri), kind = ContentKind.Main)
list("Packages", "Package", setOf(m.dri), ContentKind.Packages, m.packages.sortedBy { it.name }.map { p ->
RowJavadocListEntry(
LinkJavadocListEntry(p.name, setOf(p.dri), JavadocContentKind.PackageSummary, sourceSets),
@@ -111,42 +110,21 @@ open class JavadocPageCreator(
)
}
- private fun signatureForProjection(p: Projection): String =
- when (p) {
- is OtherParameter -> p.name
- is TypeConstructor -> if (p.function)
- "TODO"
- else {
- val other = if (p.projections.isNotEmpty()) {
- p.projections.joinToString(prefix = "<", postfix = ">") { signatureForProjection(it) }
- } else {
- ""
- }
- "${p.dri.classNames.orEmpty()} $other"
- }
-
- is Variance -> "${p.kind} ${signatureForProjection(p.inner)}"
- is Star -> "*"
- is Nullable -> "${signatureForProjection(p.inner)}?"
- is JavaObject -> "Object"
- is Void -> "Void"
- is PrimitiveJavaType -> p.name
- is Dynamic -> "dynamic"
- is UnresolvedBound -> p.name
- }
-
private fun DFunction.toJavadocFunction() = highestJvmSourceSet?.let { jvm ->
JavadocFunctionNode(
name = name,
dri = dri,
- signature = signatureProvider.signature(this).nodeForJvm(jvm),
+ signature = signatureForNode(this, jvm),
brief = brief(jvm),
- parameters = parameters.map {
- JavadocParameterNode(
- name = it.name.orEmpty(),
- type = signatureForProjection(it.type),
- description = it.brief()
- )
+ parameters = parameters.mapNotNull {
+ val signature = signatureForNode(it, jvm)
+ signature.modifiers?.let { type ->
+ JavadocParameterNode(
+ name = it.name.orEmpty(),
+ type = type,
+ description = it.brief()
+ )
+ }
},
extras = extra
)
@@ -165,19 +143,28 @@ open class JavadocPageCreator(
private inline fun <reified T : TagWrapper> Documentable.findNodeInDocumentation(sourceSetData: DokkaSourceSet?): T? =
documentation[sourceSetData]?.firstChildOfTypeOrNull<T>()
- private fun Documentable.descriptionToContentNodes(sourceSet: DokkaSourceSet? = highestJvmSourceSet) = findNodeInDocumentation<Description>(sourceSet)?.let {
- DocTagToContentConverter.buildContent(
- it.root,
- DCI(setOf(dri), JavadocContentKind.OverviewSummary),
- sourceSets.toSet()
- )
- }.orEmpty()
+ private fun Documentable.descriptionToContentNodes(sourceSet: DokkaSourceSet? = highestJvmSourceSet) =
+ contentNodesFromType<Description>(sourceSet)
+
+ private fun DParameter.paramsToContentNodes(sourceSet: DokkaSourceSet? = highestJvmSourceSet) =
+ contentNodesFromType<Param>(sourceSet)
+
+ private inline fun <reified T : TagWrapper> Documentable.contentNodesFromType(sourceSet: DokkaSourceSet?) =
+ findNodeInDocumentation<T>(sourceSet)?.let {
+ DocTagToContentConverter.buildContent(
+ it.root,
+ DCI(setOf(dri), JavadocContentKind.OverviewSummary),
+ sourceSets.toSet()
+ )
+ }.orEmpty()
fun List<ContentNode>.nodeForJvm(jvm: DokkaSourceSet): ContentNode =
first { it.sourceSets.contains(jvm) }
- private fun Documentable.brief(sourceSet: DokkaSourceSet? = highestJvmSourceSet): List<ContentNode> {
- val description = descriptionToContentNodes(sourceSet)
+ private fun Documentable.brief(sourceSet: DokkaSourceSet? = highestJvmSourceSet): List<ContentNode> =
+ briefFromContentNodes(descriptionToContentNodes(sourceSet))
+
+ private fun briefFromContentNodes(description: List<ContentNode>): List<ContentNode> {
val contents = mutableListOf<ContentNode>()
for (node in description) {
if (node is ContentText && firstSentenceRegex.containsMatchIn(node.text)) {
@@ -189,5 +176,14 @@ open class JavadocPageCreator(
}
return contents
}
+
+ private fun DParameter.brief(sourceSet: DokkaSourceSet? = highestJvmSourceSet): List<ContentNode> =
+ briefFromContentNodes(paramsToContentNodes(sourceSet).dropWhile { it is ContentDRILink })
+
+ private fun ContentNode.asJavadocNode(): JavadocSignatureContentNode =
+ (this as ContentGroup).firstChildOfTypeOrNull<JavadocSignatureContentNode>() ?: throw IllegalStateException("No content for javadoc signature found")
+
+ private fun signatureForNode(documentable: Documentable, sourceSet: DokkaSourceSet): JavadocSignatureContentNode =
+ signatureProvider.signature(documentable).nodeForJvm(sourceSet).asJavadocNode()
}
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt
index 7b4aa64d..1a14e97e 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt
@@ -3,21 +3,24 @@ package org.jetbrains.dokka.javadoc
import javadoc.JavadocDocumentableToPageTranslator
import javadoc.location.JavadocLocationProviderFactory
import javadoc.renderer.KorteJavadocRenderer
+import javadoc.signatures.JavadocSignatureProvider
import org.jetbrains.dokka.CoreExtensions
import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.kotlinAsJava.KotlinAsJavaPlugin
import org.jetbrains.dokka.plugability.DokkaPlugin
import org.jetbrains.dokka.plugability.querySingle
class JavadocPlugin : DokkaPlugin() {
val dokkaBasePlugin by lazy { plugin<DokkaBase>() }
+ val kotinAsJavaPlugin by lazy { plugin<KotlinAsJavaPlugin>() }
val locationProviderFactory by extensionPoint<JavadocLocationProviderFactory>()
val dokkaJavadocPlugin by extending {
(CoreExtensions.renderer
providing { ctx -> KorteJavadocRenderer(dokkaBasePlugin.querySingle { outputWriter }, ctx, "views") }
- applyIf { format == "javadoc" }
+ applyIf { format == javadocFormat }
override dokkaBasePlugin.htmlRenderer)
}
@@ -28,13 +31,28 @@ class JavadocPlugin : DokkaPlugin() {
dokkaBasePlugin.querySingle { signatureProvider },
context.logger
)
- } override dokkaBasePlugin.documentableToPageTranslator
+ } override dokkaBasePlugin.documentableToPageTranslator applyIf { format == javadocFormat }
}
val javadocLocationProviderFactory by extending {
locationProviderFactory providing { context ->
JavadocLocationProviderFactory(context)
- }
+ } applyIf { format == javadocFormat }
+ }
+
+ val javadocSignatureProvider by extending {
+ val dokkaBasePlugin = plugin<DokkaBase>()
+ dokkaBasePlugin.signatureProvider providing { ctx ->
+ JavadocSignatureProvider(
+ ctx.single(
+ dokkaBasePlugin.commentsToContentConverter
+ ), ctx.logger
+ )
+ } override kotinAsJavaPlugin.javaSignatureProvider applyIf { format == javadocFormat }
+ }
+
+ companion object {
+ private val javadocFormat = "javadoc"
}
}
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocContentNodes.kt b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocContentNodes.kt
index c8593498..5e24ce9e 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocContentNodes.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocContentNodes.kt
@@ -86,13 +86,6 @@ fun JavaContentGroupBuilder.title(
list.add(TitleNode(title, subtitle, version, parent, dri, kind, sourceSets))
}
-data class TextNode(
- val text: String,
- override val sourceSets: Set<DokkaSourceSet>
-) : JavadocContentNode(emptySet(), ContentKind.Main, sourceSets) {
- override fun hasAnyContent(): Boolean = !text.isBlank()
-}
-
class ListNode(
val tabTitle: String,
val colTitle: String,
@@ -137,3 +130,14 @@ class LinkJavadocListEntry(
data class RowJavadocListEntry(val link: LinkJavadocListEntry, val doc: List<ContentNode>) : JavadocListEntry {
override val stringTag: String = ""
}
+
+data class JavadocSignatureContentNode(
+ val dri: DRI,
+ val kind: Kind = ContentKind.Symbol,
+ val annotations: ContentNode?,
+ val modifiers: ContentNode?,
+ val signatureWithoutModifiers: ContentNode,
+ val supertypes: ContentNode?
+): JavadocContentNode(setOf(dri), kind, signatureWithoutModifiers.sourceSets) {
+ override fun hasAnyContent(): Boolean = true
+}
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt
index 24e481e8..02e4b2d6 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt
@@ -26,8 +26,6 @@ class JavadocModulePageNode(
RootPageNode(),
JavadocPageNode {
- val version: String = "0.0.1"
-
override val documentable: Documentable? = null
override val embeddedResources: List<String> = emptyList()
override fun modified(name: String, children: List<PageNode>): RootPageNode =
@@ -82,44 +80,35 @@ class JavadocPackagePageNode(
}
data class JavadocEntryNode(
- val signature: ContentNode,
+ val signature: JavadocSignatureContentNode,
val brief: List<ContentNode>
)
data class JavadocParameterNode(
val name: String,
- val type: String,
+ val type: ContentNode,
val description: List<ContentNode>
)
data class JavadocPropertyNode(
- val signature: ContentNode,
+ val signature: JavadocSignatureContentNode,
val brief: List<ContentNode>
-) {
- val modifiersAndSignature: Pair<ContentNode, ContentNode>
- get() = (signature as ContentGroup).splitSignatureIntoModifiersAndName()
-}
+)
data class JavadocFunctionNode(
- val signature: ContentNode,
+ val signature: JavadocSignatureContentNode,
val brief: List<ContentNode>,
val parameters: List<JavadocParameterNode>,
val name: String,
val dri: DRI,
val extras: PropertyContainer<DFunction> = PropertyContainer.empty()
-) {
-
- val modifiersAndSignature: Pair<ContentNode, ContentNode>
- get() = (signature as ContentGroup).splitSignatureIntoModifiersAndName()
-
-}
+)
class JavadocClasslikePageNode(
override val name: String,
override val content: JavadocContentNode,
override val dri: Set<DRI>,
- val modifiers: List<String>,
- val signature: ContentNode,
+ val signature: JavadocSignatureContentNode,
val description: List<ContentNode>,
val constructors: List<JavadocFunctionNode>,
val methods: List<JavadocFunctionNode>,
@@ -142,7 +131,6 @@ class JavadocClasslikePageNode(
name,
content,
dri,
- modifiers,
signature,
description,
constructors,
@@ -167,7 +155,6 @@ class JavadocClasslikePageNode(
name,
content as JavadocContentNode,
dri,
- modifiers,
signature,
description,
constructors,
@@ -413,15 +400,6 @@ class TreeViewPage(
}
}
-private fun ContentGroup.splitSignatureIntoModifiersAndName(): Pair<ContentNode, ContentNode> {
- val signature = children.firstIsInstance<ContentGroup>()
- val modifiers = signature.children.takeWhile { it !is ContentLink }
- return Pair(
- signature.copy(children = modifiers),
- signature.copy(children = signature.children.drop(modifiers.size))
- )
-}
-
private fun Documentable.kind(): String? =
when (this) {
is DClass -> "class"
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/pages/htmlGeneration.kt b/plugins/javadoc/src/main/kotlin/javadoc/pages/htmlGeneration.kt
deleted file mode 100644
index 98aa2344..00000000
--- a/plugins/javadoc/src/main/kotlin/javadoc/pages/htmlGeneration.kt
+++ /dev/null
@@ -1,391 +0,0 @@
-package javadoc.pages
-
-import kotlinx.html.html
-import kotlinx.html.stream.createHTML
-import org.jetbrains.dokka.pages.ClasslikePageNode
-import org.jetbrains.dokka.pages.ModulePageNode
-import org.jetbrains.dokka.pages.PackagePageNode
-import org.jetbrains.dokka.pages.PageNode
-import java.time.LocalDate
-
-class NavbarGenerator(val page: PageNode) {
- val activeClass = "navBarCell1Rev"
- fun pathToRoot() = "???" // TODO
- val navItems = listOf("Overview", "Package", "Class", "Tree", "Deprecated", "Index", "Help")
-
- // private fun items = navItems.map {itemLink}
-// fun navItemLink()
- val x = createHTML().html {}
-
- private fun navList(content: String) = """<ul class="navList" title="Navigation">
- $content
- </ul>
- """.trimIndent()
-
-// private fun navList(): String {
-// when (page) {
-// is PackagePageNode ->
-// }
-// """
-//<li><a href="../index.html">Overview</a></li>
-//<li><a href="package-summary.html">Package</a></li>
-//<li class="navBarCell1Rev">Class</li>
-//"""
-// val classItem = if (page is ClasslikePageNode) {
-// "Class".wrapInTag("li", mapOf("class" to activeClass))
-// }
-// val treeItem = if (page is ModulePageNode) {
-// "<li><a href=\"overview-tree.html\">Tree</a></li>\n"
-// } else {
-// "<li><a href=\"package-tree.html\">Tree</a></li>\n"
-// }
-//
-// val navListEnd = """
-//<li><a href="${pathToRoot()}deprecated-list.html">Deprecated</a></li>
-//<li><a href="${pathToRoot()}index-all.html">Index</a></li>
-//<li><a href="${pathToRoot()}help-doc.html">Help</a></li>
-//""".trimIndent()
-// }
-
- private fun bottomNavbar(page: PageNode): String =
- """
- |<nav role="navigation">
- |<!-- ======= START OF BOTTOM NAVBAR ====== -->
- |<div class="bottomNav"><a id="navbar.bottom">
- |<!-- -->
- |</a>
- |<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
- |<a id="navbar.bottom.firstrow">
- |<!-- -->
- |</a>
- ${navList("????")}
- |</div>
- |<div class="subNav">
- |<div>
- |<ul class="subNavList">
- |<li>Summary:&nbsp;</li>
- |<li>Nested&nbsp;|&nbsp;</li>
- |<li>Field&nbsp;|&nbsp;</li>
- |<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
- |<li><a href="#method.summary">Method</a></li>
- |</ul>
- |<ul class="subNavList">
- |<li>Detail:&nbsp;</li>
- |<li>Field&nbsp;|&nbsp;</li>
- |<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
- |<li><a href="#method.detail">Method</a></li>
- |</ul>
- |</div>
- |</div>
- |<a id="skip.navbar.bottom">
- |<!-- -->
- |</a>
- |<!-- ======== END OF BOTTOM NAVBAR ======= -->
- |</nav>"""
-}
-
-internal fun pageStart(title: String, version: String, documentTitle: String, pathToRoot: String) = """
- |<!DOCTYPE HTML>
- |<!-- NewPage -->
- |<html lang="en">
- |<head>
- |<title>$documentTitle ($title $version API)</title>
- |<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- |<meta name="dc.created" content="${LocalDate.now()}">
- |<link rel="stylesheet" type="text/css" href="${pathToRoot}stylesheet.css" title="Style">
- |<link rel="stylesheet" type="text/css" href="${pathToRoot}jquery/jquery-ui.css" title="Style">
- |<script type="text/javascript" src="${pathToRoot}script.js"></script>
- |<script type="text/javascript" src="${pathToRoot}jquery/jszip/dist/jszip.min.js"></script>
- |<script type="text/javascript" src="${pathToRoot}jquery/jszip-utils/dist/jszip-utils.min.js"></script>
- |<!--[if IE]>
- |<script type="text/javascript" src="${pathToRoot}jquery/jszip-utils/dist/jszip-utils-ie.min.js"></script>
- |<![endif]-->
- |<script type="text/javascript" src="${pathToRoot}jquery/jquery-$jQueryVersion.js"></script>
- |<script type="text/javascript" src="${pathToRoot}jquery/jquery-migrate-$jQueryMigrateVersion.js"></script>
- |<script type="text/javascript" src="${pathToRoot}jquery/jquery-ui.js"></script>
- |</head>
- |<body>
- |<script type="text/javascript"><!--
- | try {
- | if (location.href.indexOf('is-external=true') == -1) {
- | parent.document.title="$documentTitle ($title $version API)";
- | }
- | }
- | catch(err) {
- | }
- |//-->
- |var pathtoroot = "$pathToRoot";
- |var useModuleDirectories = true;
- |loadScripts(document, 'script');</script>
- |<noscript>
- |<div>JavaScript is disabled on your browser.</div>
- |</noscript>
- |<header role="banner">
- |<nav role="navigation">
- |<div class="fixedNav">""".trimMargin("|")
-
-internal fun topNavbar(page: PageNode, pathToRoot: String): String = """
- |<!-- ========= START OF TOP NAVBAR ======= -->
- |<div class="topNav"><a id="navbar.top">
- |<!-- -->
- |</a>
- |<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
- |<a id="navbar.top.firstrow">
- |<!-- -->
- |</a>
- |<ul class="navList" title="Navigation">
- ${/*if ((page is JavadocPageNode) && page.pageType == PageType.Class)
- "<li><a href=\"${pathToRoot}index.html\">Overview</a></li>"
- else if (page is RootIndexPage)
- "<li class=\"navBarCell1Rev\">Overview</li>"
- else
- "<li><a href=\"package-summary.html\">Package</a></li>\n"}
- ${if ((page is JavadocPageNode) && page.pageType == PageType.Package)
- "<li class=\"navBarCell1Rev\">Package</li>"
- else
- "<li>Package</li>"*/ ""}
- |<li navBarCell1Rev>Class</li>
- |<li><a href="overview-tree.html">Tree</a></li>
- |<li><a href="${pathToRoot}deprecated-list.html">Deprecated</a></li>
- |<li><a href="${pathToRoot}index-all.html">Index</a></li>
- |<li><a href="${pathToRoot}help-doc.html">Help</a></li>
- |</ul>
- |</div>
- |<div class="subNav">
- |<ul class="navListSearch">
- |<li><label for="search">SEARCH:</label>
- |<input type="text" id="search" value="search" disabled="disabled">
- |<input type="reset" id="reset" value="reset" disabled="disabled">
- |</li>
- |</ul>
- |</div>
- |<a id="skip.navbar.top">
- |<!-- -->
- |</a>
- |<!-- ========= END OF TOP NAVBAR ========= -->""".trimMargin("|")
-
-internal fun indexPage(title: String, version: String, tabTitle: String, colTitle: String, packages: List<PageNode>) = """
- |</div>
- |<div class="navPadding">&nbsp;</div>
- |<script type="text/javascript"><!--
- |${'$'}('.navPadding').css('padding-top', ${'$'}('.fixedNav').css("height"));
- |//-->
- |</script>
- |</nav>
- |</header>
- |<main role="main">
- |<div class="header">
- |<h1 class="title">$title $version API</h1>
- |</div>
- |<div class="contentContainer">
- |<div class="overviewSummary">
- |<table>
- |<caption><span>$tabTitle</span><span class="tabEnd">&nbsp;</span></caption>
- |<tr>
- |<th class="colFirst" scope="col">$colTitle</th>
- |<th class="colLast" scope="col">Description</th>
- |</tr>
- |<tbody>
- ${packages.mapIndexed { i, e -> e.generateLink(i) }.joinToString("\n")}
- |</tbody>
- |</table>
- |</div>
- |</div>
- |</main>
- |<footer role="contentinfo">
- |<nav role="navigation">
- |<!-- ======= START OF BOTTOM NAVBAR ====== -->
- |<div class="bottomNav"><a id="navbar.bottom">
- |<!-- -->
- |</a>
- |<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
- |<a id="navbar.bottom.firstrow">
- |<!-- -->
- |</a>
- |<ul class="navList" title="Navigation">
- |<li class="navBarCell1Rev">Overview</li>
- |<li>Package</li>
- |<li>Class</li>
- |<li><a href="overview-tree.html">Tree</a></li>
- |<li><a href="deprecated-list.html">Deprecated</a></li>
- |<li><a href="index-all.html">Index</a></li>
- |<li><a href="help-doc.html">Help</a></li>
- |</ul>
- |</div>
- |<a id="skip.navbar.bottom">
- |<!-- -->
- |</a>
- |<!-- ======== END OF BOTTOM NAVBAR ======= -->
- |</nav>
- |</footer>
- |</body>
- |</html>
- |""".trimMargin("|")
-
-fun classData(name: String, extends: String) = """
- |<!-- ======== START OF CLASS DATA ======== -->
- |<div class="header">
- |<div class="subTitle">adaptation</div>
- |<h2 title="Class $name" class="title">Class $name</h2>
- |</div>
- |<div class="contentContainer">
- ${classInheritance()}
- |<div class="description">
- |<ul class="blockList">
- |<li class="blockList">
- |<hr>
- |<br>
- |<pre>public class <span class="typeNameLabel">$name</span>
- |extends $name</pre>
- |</li>
- |</ul>
- |</div>
- |<div class="summary">
- |<ul class="blockList">
- |<li class="blockList">
- |<!-- ======== NESTED CLASS SUMMARY ======== -->
- |<ul class="blockList">
- |<li class="blockList"><a name="nested.class.summary">
- |<!-- -->
- |</a>
- |<h3>Nested Class Summary</h3>
- |<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Nested Class Summary table, listing nested classes, and an explanation">
- |<caption><span>Nested Classes</span><span class="tabEnd">&nbsp;</span></caption>
- |<tr>
- |<th class="colFirst" scope="col">Modifier and Type</th>
- |<th class="colLast" scope="col">Class and Description</th>
- |</tr>
- |<tr class="altColor">
- |<td class="colFirst"><code>class&nbsp;</code></td>
- |<td class="colLast"><code><span class="memberNameLink"><a href="../adaptation/Adaptation.AdaptationInternalClass.html" title="class in adaptation">Adaptation.AdaptationInternalClass</a></span></code>&nbsp;</td>
- |</tr>
- |<tr class="rowColor">
- |<td class="colFirst"><code>static class&nbsp;</code></td>
- |<td class="colLast"><code><span class="memberNameLink"><a href="../adaptation/Adaptation.AdaptationInternalStaticClass.html" title="class in adaptation">Adaptation.AdaptationInternalStaticClass</a></span></code>&nbsp;</td>
- |</tr>
- |</table>
- |</li>
- |</ul>
- |<!-- ======== CONSTRUCTOR SUMMARY ======== -->
- |<ul class="blockList">
- |<li class="blockList"><a name="constructor.summary">
- |<!-- -->
- |</a>
- |<h3>Constructor Summary</h3>
- |<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
- |<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
- |<tr>
- |<th class="colOne" scope="col">Constructor and Description</th>
- |</tr>
- |<tr class="altColor">
- |<td class="colOne"><code><span class="memberNameLink"><a href="../adaptation/Adaptation.html#Adaptation--">Adaptation</a></span>()</code>&nbsp;</td>
- |</tr>
- |</table>
- |</li>
- |</ul>
- |<!-- ========== METHOD SUMMARY =========== -->
- |<ul class="blockList">
- |<li class="blockList"><a name="method.summary">
- |<!-- -->
- |</a>
- |<h3>Method Summary</h3>
- |<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
- |<caption><span id="t0" class="activeTableTab"><span>All Methods</span><span class="tabEnd">&nbsp;</span></span><span id="t1" class="tableTab"><span><a href="javascript:show(1);">Static Methods</a></span><span class="tabEnd">&nbsp;</span></span><span id="t4" class="tableTab"><span><a href="javascript:show(8);">Concrete Methods</a></span><span class="tabEnd">&nbsp;</span></span></caption>
- |<tr>
- |<th class="colFirst" scope="col">Modifier and Type</th>
- |<th class="colLast" scope="col">Method and Description</th>
- |</tr>
- |<tr id="i0" class="altColor">
- |<td class="colFirst"><code>static org.javatuples.Pair&lt;<a href="../model/ModelGraph.html" title="class in model">ModelGraph</a>,java.lang.Boolean&gt;</code></td>
- |<td class="colLast"><code><span class="memberNameLink"><a href="../adaptation/Adaptation.html#transform-model.ModelGraph-transformation.Transformation-">transform</a></span>(<a href="../model/ModelGraph.html" title="class in model">ModelGraph</a>&nbsp;graph,
- | <a href="../transformation/Transformation.html" title="interface in transformation">Transformation</a>&nbsp;transformation)</code>&nbsp;</td>
- |</tr>
- |</table>
- |<ul class="blockList">
- |<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
- |<!-- -->
- |</a>
- |<h3>Methods inherited from class&nbsp;java.lang.Object</h3>
- |<code>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</code></li>
- |</ul>
- |</li>
- |</ul>
- |</li>
- |</ul>
- |</div>
- |<div class="details">
- |<ul class="blockList">
- |<li class="blockList">
- |<!-- ========= CONSTRUCTOR DETAIL ======== -->
- |<ul class="blockList">
- |<li class="blockList"><a name="constructor.detail">
- |<!-- -->
- |</a>
- |<h3>Constructor Detail</h3>
- |<a name="Adaptation--">
- |<!-- -->
- |</a>
- |<ul class="blockListLast">
- |<li class="blockList">
- |<h4>Adaptation</h4>
- |<pre>public&nbsp;Adaptation()</pre>
- |</li>
- |</ul>
- |</li>
- |</ul>
- |<!-- ============ METHOD DETAIL ========== -->
- |<ul class="blockList">
- |<li class="blockList"><a name="method.detail">
- |<!-- -->
- |</a>
- |<h3>Method Detail</h3>
- |<a name="transform-model.ModelGraph-transformation.Transformation-">
- |<!-- -->
- |</a>
- |<ul class="blockListLast">
- |<li class="blockList">
- |<h4>transform</h4>
- |<pre>public static&nbsp;org.javatuples.Pair&lt;<a href="../model/ModelGraph.html" title="class in model">ModelGraph</a>,java.lang.Boolean&gt;&nbsp;transform(<a href="../model/ModelGraph.html" title="class in model">ModelGraph</a>&nbsp;graph,
- | <a href="../transformation/Transformation.html" title="interface in transformation">Transformation</a>&nbsp;transformation)</pre>
- |</li>
- |</ul>
- |</li>
- |</ul>
- |</li>
- |</ul>
- |</div>
- |</div>
- |<!-- ========= END OF CLASS DATA ========= -->
-""".trimIndent()
-
-fun classInheritance() = """
- |<ul class="inheritance">
- |<li>java.lang.Object</li>
- |<li>
- |<ul class="inheritance">
- |<li>adaptation.Adaptation</li>
- |</ul>
- |</li>
- |</ul>
- """
-
-internal fun String.wrapInTag(tag: String, options: Map<String, String>) =
- "<$tag ${options.map { it.key + "=\"" + it.value + '"' }.joinToString(" ")}>$this</$tag>"
-
-fun PageNode.generateLink(i: Int) = "\n<tr class=\"altColor\" id=\"i$i\">\n" + run {
- val path = /*if (this is JavadocPageNode && this.pageType != PageType.Package) "$filename.html" else*/ "$name/package-summary.html"
-
- name.wrapInTag("a", mapOf("href" to path))
- .wrapInTag(
- "th",
- mapOf("class" to "colFirst", "scope" to "row")
- ) + "<td class=\"colLast\">&nbsp;</td>\n</tr>"
-}
-
-internal enum class NavigableType {
- Overview, Package, Class, Tree, Deprecated, Index, Help
-}
-
-internal interface Navigable {
- val type: NavigableType
-} \ No newline at end of file
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt
index 7d6f37c0..df6490cf 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt
@@ -1,9 +1,10 @@
package javadoc.renderer
-import javadoc.pages.TextNode
+import javadoc.pages.JavadocSignatureContentNode
import org.jetbrains.dokka.base.resolvers.local.LocationProvider
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.utilities.htmlEscape
internal class JavadocContentToHtmlTranslator(
private val locationProvider: LocationProvider,
@@ -13,14 +14,14 @@ internal class JavadocContentToHtmlTranslator(
fun htmlForContentNode(node: ContentNode, relative: PageNode?): String =
when (node) {
is ContentGroup -> htmlForContentNodes(node.children, relative)
- is ContentText -> node.text
- is TextNode -> node.text
+ is ContentText -> node.text.htmlEscape()
is ContentDRILink -> buildLink(
locationProvider.resolve(node.address, node.sourceSets, relative),
htmlForContentNodes(node.children, relative)
)
is ContentResolvedLink -> buildLink(node.address, htmlForContentNodes(node.children, relative))
is ContentCode -> htmlForCode(node.children)
+ is JavadocSignatureContentNode -> htmlForSignature(node, relative)
else -> ""
}
@@ -35,6 +36,14 @@ internal class JavadocContentToHtmlTranslator(
}
}.joinToString("<br>", """<span class="code">""", "</span>") { it }
+ private fun htmlForSignature(node: JavadocSignatureContentNode, relative: PageNode?): String =
+ listOfNotNull(
+ node.annotations,
+ node.modifiers,
+ node.signatureWithoutModifiers,
+ node.supertypes
+ ).joinToString(separator = " ") { htmlForContentNode(it, relative) }
+
companion object {
fun buildLink(address: String, content: String) =
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
index e60b27c6..760647fa 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
@@ -49,20 +49,18 @@ internal class JavadocContentToTemplateMapTranslator(
}
}
- private fun String.toNormalized() = Paths.get(this).toNormalized()
-
private inner class InnerTranslator(val contextNode: PageNode) {
private val htmlTranslator = JavadocContentToHtmlTranslator(locationProvider, context)
- internal fun templateMapForAllClassesPage(node: AllClassesPage): TemplateMap {
+ fun templateMapForAllClassesPage(node: AllClassesPage): TemplateMap {
return mapOf(
"title" to "All Classes",
"list" to node.classEntries
)
}
- internal fun templateMapForTreeViewPage(node: TreeViewPage): TemplateMap {
+ fun templateMapForTreeViewPage(node: TreeViewPage): TemplateMap {
return mapOf(
"title" to node.title,
"name" to node.name,
@@ -73,45 +71,49 @@ internal class JavadocContentToTemplateMapTranslator(
)
}
- internal fun templateMapForPackagePageNode(node: JavadocPackagePageNode): TemplateMap {
+ fun templateMapForPackagePageNode(node: JavadocPackagePageNode): TemplateMap {
return mapOf(
"kind" to "package"
) + templateMapForJavadocContentNode(node.content)
}
- internal fun templateMapForFunctionNode(node: JavadocFunctionNode): TemplateMap {
- val (modifiers, signature) = node.modifiersAndSignature
+ fun templateMapForFunctionNode(node: JavadocFunctionNode): TemplateMap {
return mapOf(
- "signature" to htmlForContentNode(node.signature, contextNode),
"brief" to htmlForContentNodes(node.brief, contextNode),
"parameters" to node.parameters.map { templateMapForParameterNode(it) },
- "inlineParameters" to node.parameters.joinToString { "${it.type} ${it.name}" },
- "modifiers" to htmlForContentNode(modifiers, contextNode),
- "signatureWithoutModifiers" to htmlForContentNode(signature, contextNode),
+ "inlineParameters" to node.parameters.joinToString { renderInlineParameter(it) },
+ "signature" to templateMapForSignatureNode(node.signature),
"name" to node.name
)
}
- internal fun templateMapForClasslikeNode(node: JavadocClasslikePageNode): TemplateMap =
+ fun templateMapForClasslikeNode(node: JavadocClasslikePageNode): TemplateMap =
mapOf(
"constructors" to node.constructors.map { templateMapForFunctionNode(it) },
- "signature" to htmlForContentNode(node.signature, node),
+ "signature" to templateMapForSignatureNode(node.signature),
"methods" to templateMapForClasslikeMethods(node.methods),
"classlikeDocumentation" to htmlForContentNodes(node.description, node),
"entries" to node.entries.map { templateMapForEntryNode(it) },
"properties" to node.properties.map { templateMapForPropertyNode(it) },
"classlikes" to node.classlikes.map { templateMapForNestedClasslikeNode(it) },
- "implementedInterfaces" to templateMapForImplementedInterfaces(node),
+ "implementedInterfaces" to templateMapForImplementedInterfaces(node).sorted(),
"kind" to node.kind,
"packageName" to node.packageName,
"name" to node.name
) + templateMapForJavadocContentNode(node.content)
- internal fun templateMapForJavadocContentNode(node: JavadocContentNode): TemplateMap =
+ fun templateMapForSignatureNode(node: JavadocSignatureContentNode): TemplateMap =
+ mapOf(
+ "annotations" to node.annotations?.let { htmlForContentNode(it, contextNode) },
+ "signatureWithoutModifiers" to htmlForContentNode(node.signatureWithoutModifiers, contextNode),
+ "modifiers" to node.modifiers?.let { htmlForContentNode(it, contextNode) },
+ "supertypes" to node.supertypes?.let { htmlForContentNode(it, contextNode) }
+ )
+
+ fun templateMapForJavadocContentNode(node: JavadocContentNode): TemplateMap =
when (node) {
is TitleNode -> templateMapForTitleNode(node)
is JavadocContentGroup -> templateMapForJavadocContentGroup(node)
- is TextNode -> templateMapForTextNode(node)
is ListNode -> templateMapForListNode(node)
else -> emptyMap()
}
@@ -120,7 +122,7 @@ internal class JavadocContentToTemplateMapTranslator(
mapOf(
"description" to htmlForContentNodes(node.description, contextNode),
"name" to node.name,
- "type" to node.type
+ "type" to htmlForContentNode(node.type, contextNode)
)
private fun templateMapForImplementedInterfaces(node: JavadocClasslikePageNode) =
@@ -157,25 +159,24 @@ internal class JavadocContentToTemplateMapTranslator(
private fun templateMapForNestedClasslikeNode(node: JavadocClasslikePageNode): TemplateMap {
return mapOf(
- "modifiers" to (node.modifiers + "static" + node.kind).joinToString(separator = " "),
+ "modifiers" to node.signature.modifiers?.let { htmlForContentNode(it, contextNode) },
"signature" to node.name,
"description" to htmlForContentNodes(node.description, node)
)
}
private fun templateMapForPropertyNode(node: JavadocPropertyNode): TemplateMap {
- val (modifiers, signature) = node.modifiersAndSignature
return mapOf(
- "modifiers" to htmlForContentNode(modifiers, contextNode),
- "signature" to htmlForContentNode(signature, contextNode),
+ "modifiers" to node.signature.modifiers?.let { htmlForContentNode(it, contextNode) },
+ "signature" to htmlForContentNode(node.signature.signatureWithoutModifiers, contextNode),
"description" to htmlForContentNodes(node.brief, contextNode)
)
}
private fun templateMapForEntryNode(node: JavadocEntryNode): TemplateMap {
return mapOf(
- "signature" to htmlForContentNode(node.signature, contextNode),
- "brief" to node.brief
+ "signature" to templateMapForSignatureNode(node.signature),
+ "brief" to htmlForContentNodes(node.brief, contextNode)
)
}
@@ -194,10 +195,6 @@ internal class JavadocContentToTemplateMapTranslator(
}
}
- private fun templateMapForTextNode(node: TextNode): TemplateMap {
- return mapOf("text" to node.text)
- }
-
private fun templateMapForListNode(node: ListNode): TemplateMap {
return mapOf(
"tabTitle" to node.tabTitle,
@@ -206,6 +203,9 @@ internal class JavadocContentToTemplateMapTranslator(
)
}
+ private fun renderInlineParameter(parameter: JavadocParameterNode): String =
+ htmlForContentNode(parameter.type, contextNode) + " ${parameter.name}"
+
private fun htmlForContentNode(node: ContentNode, relativeNode: PageNode) =
htmlTranslator.htmlForContentNode(node, relativeNode)
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/signatures/JavadocSignatureProvider.kt b/plugins/javadoc/src/main/kotlin/javadoc/signatures/JavadocSignatureProvider.kt
new file mode 100644
index 00000000..11db9fe1
--- /dev/null
+++ b/plugins/javadoc/src/main/kotlin/javadoc/signatures/JavadocSignatureProvider.kt
@@ -0,0 +1,196 @@
+package javadoc.signatures
+
+import javadoc.translators.documentables.JavadocPageContentBuilder
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.signatures.JvmSignatureUtils
+import org.jetbrains.dokka.base.signatures.SignatureProvider
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.kotlinAsJava.signatures.JavaSignatureUtils
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.ContentKind
+import org.jetbrains.dokka.pages.ContentNode
+import org.jetbrains.dokka.utilities.DokkaLogger
+
+class JavadocSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider,
+ JvmSignatureUtils by JavaSignatureUtils {
+
+ private val contentBuilder = JavadocPageContentBuilder(ctcc, this, logger)
+
+ private val ignoredVisibilities = setOf(JavaVisibility.Default)
+
+ private val ignoredModifiers =
+ setOf(KotlinModifier.Open, JavaModifier.Empty, KotlinModifier.Empty, KotlinModifier.Sealed)
+
+ override fun signature(documentable: Documentable): List<ContentNode> = when (documentable) {
+ is DFunction -> signature(documentable)
+ is DProperty -> signature(documentable)
+ is DClasslike -> signature(documentable)
+ is DEnumEntry -> signature(documentable)
+ is DTypeParameter -> signature(documentable)
+ is DParameter -> signature(documentable)
+ else -> throw NotImplementedError(
+ "Cannot generate signature for ${documentable::class.qualifiedName} ${documentable.name}"
+ )
+ }
+
+ private fun signature(c: DClasslike): List<ContentNode> =
+ javadocSignature(c) {
+ annotations {
+ annotationsBlock(c)
+ }
+ modifiers {
+ text(c.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.plus(" ") ?: "")
+
+ if (c is DClass) {
+ text(c.modifier[it]?.takeIf { it !in ignoredModifiers }?.name?.plus(" ") ?: "")
+ text(c.modifiers()[it]?.toSignatureString() ?: "")
+ }
+
+ when (c) {
+ is DClass -> text("class")
+ is DInterface -> text("interface")
+ is DEnum -> text("enum")
+ is DObject -> text("class")
+ is DAnnotation -> text("@interface")
+ }
+ }
+ signatureWithoutModifiers {
+ link(c.name!!, c.dri)
+ if (c is WithGenerics) {
+ list(c.generics, prefix = "<", suffix = ">") {
+ +buildSignature(it)
+ }
+ }
+ }
+ supertypes {
+ if (c is WithSupertypes) {
+ c.supertypes.map { (p, dris) ->
+ list(dris, sourceSets = setOf(p)) {
+ link(it.fqName(), it, sourceSets = setOf(p))
+ }
+ }
+ }
+ }
+ }
+
+ private fun signature(f: DFunction): List<ContentNode> =
+ javadocSignature(f) {
+ annotations {
+ annotationsBlock(f)
+ }
+ modifiers {
+ text(f.modifier[it]?.takeIf { it !in ignoredModifiers }?.name?.plus(" ") ?: "")
+ text(f.modifiers()[it]?.toSignatureString() ?: "")
+ list(f.generics, prefix = "<", suffix = "> ") {
+ +buildSignature(it)
+ }
+ signatureForProjection(f.type)
+ }
+ signatureWithoutModifiers {
+ link(f.name, f.dri)
+ text("(")
+ list(f.parameters) {
+ annotationsInline(it)
+ text(it.modifiers()[it]?.toSignatureString() ?: "")
+ signatureForProjection(it.type)
+ text(Typography.nbsp.toString())
+ link(it.name!!, it.dri)
+ }
+ text(")")
+ }
+ }
+
+ private fun signature(p: DProperty): List<ContentNode> =
+ javadocSignature(p) {
+ annotations {
+ annotationsBlock(p)
+ }
+ modifiers {
+ text(p.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.plus(" ") ?: "")
+ text(p.modifier[it]?.name + " ")
+ text(p.modifiers()[it]?.toSignatureString() ?: "")
+ signatureForProjection(p.type)
+ }
+ signatureWithoutModifiers {
+ link(p.name, p.dri)
+ }
+ }
+
+ private fun signature(e: DEnumEntry): List<ContentNode> =
+ javadocSignature(e) {
+ annotations {
+ annotationsBlock(e)
+ }
+ modifiers {
+ text(e.modifiers()[it]?.toSignatureString() ?: "")
+ }
+ signatureWithoutModifiers {
+ link(e.name, e.dri)
+ }
+ }
+
+ private fun signature(t: DTypeParameter): List<ContentNode> =
+ javadocSignature(t) {
+ annotations {
+ annotationsBlock(t)
+ }
+ signatureWithoutModifiers {
+ text(t.name)
+ }
+ supertypes {
+ list(t.bounds, prefix = "extends ") {
+ signatureForProjection(it)
+ }
+ }
+ }
+
+ private fun signature(p: DParameter): List<ContentNode> =
+ javadocSignature(p) {
+ modifiers {
+ signatureForProjection(p.type)
+ }
+ signatureWithoutModifiers {
+ link(p.name.orEmpty(), p.dri)
+ }
+ }
+
+ private fun javadocSignature(
+ d: Documentable,
+ extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
+ block: JavadocPageContentBuilder.JavadocContentBuilder.(DokkaConfiguration.DokkaSourceSet) -> Unit
+ ): List<ContentNode> =
+ d.sourceSets.map { sourceSet ->
+ contentBuilder.contentFor(d, ContentKind.Main) {
+ with(contentBuilder) {
+ javadocGroup(d.dri, d.sourceSets, extra) {
+ block(sourceSet)
+ }
+ }
+ }
+ }
+
+ private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(p: Projection): Unit = when (p) {
+ is OtherParameter -> link(p.name, p.declarationDRI)
+ is TypeConstructor -> group {
+ link(p.dri.fqName(), p.dri)
+ list(p.projections, prefix = "<", suffix = ">") {
+ signatureForProjection(it)
+ }
+ }
+ is Variance -> group {
+ text(p.kind.toString() + " ")
+ signatureForProjection(p.inner)
+ }
+ is Star -> text("?")
+ is Nullable -> signatureForProjection(p.inner)
+ is JavaObject, is Dynamic -> link("java.lang.Object", DRI("java.lang", "Object"))
+ is Void -> text("void")
+ is PrimitiveJavaType -> text(p.name)
+ is UnresolvedBound -> text(p.name)
+ }
+
+ private fun DRI.fqName(): String = "${packageName.orEmpty()}.${classNames.orEmpty()}"
+}
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/translators/documentables/JavadocPageContentBuilder.kt b/plugins/javadoc/src/main/kotlin/javadoc/translators/documentables/JavadocPageContentBuilder.kt
new file mode 100644
index 00000000..17b474b0
--- /dev/null
+++ b/plugins/javadoc/src/main/kotlin/javadoc/translators/documentables/JavadocPageContentBuilder.kt
@@ -0,0 +1,80 @@
+package javadoc.translators.documentables
+
+import javadoc.pages.JavadocSignatureContentNode
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.signatures.SignatureProvider
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.ContentKind
+import org.jetbrains.dokka.pages.ContentNode
+import org.jetbrains.dokka.utilities.DokkaLogger
+import java.lang.IllegalStateException
+
+class JavadocPageContentBuilder(
+ commentsConverter: CommentsToContentConverter,
+ signatureProvider: SignatureProvider,
+ logger: DokkaLogger
+) : PageContentBuilder(commentsConverter, signatureProvider, logger) {
+
+ fun PageContentBuilder.DocumentableContentBuilder.javadocGroup(
+ dri: DRI = mainDRI.first(),
+ sourceSets: Set<DokkaConfiguration.DokkaSourceSet> = mainSourcesetData,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: JavadocContentBuilder.() -> Unit
+ ) {
+ +JavadocContentBuilder(
+ mainDri = dri,
+ mainExtra = extra,
+ mainSourceSet = sourceSets,
+ ).apply(block).build()
+ }
+
+ open inner class JavadocContentBuilder(
+ private val mainDri: DRI,
+ private val mainExtra: PropertyContainer<ContentNode>,
+ private val mainSourceSet: Set<DokkaConfiguration.DokkaSourceSet>,
+ ) {
+ var annotations: ContentNode? = null
+ var modifiers: ContentNode? = null
+ var signatureWithoutModifiers: ContentNode? = null
+ var supertypes: ContentNode? = null
+
+ fun annotations(block: PageContentBuilder.DocumentableContentBuilder.() -> Unit) {
+ val built = buildContentForBlock(block)
+ if(built.hasAnyContent()) annotations = built
+ }
+
+ fun modifiers(block: PageContentBuilder.DocumentableContentBuilder.() -> Unit) {
+ val built = buildContentForBlock(block)
+ if(built.hasAnyContent()) modifiers = built
+ }
+
+ fun signatureWithoutModifiers(block: PageContentBuilder.DocumentableContentBuilder.() -> Unit) {
+ signatureWithoutModifiers = buildContentForBlock(block)
+ }
+
+ fun supertypes(block: PageContentBuilder.DocumentableContentBuilder.() -> Unit) {
+ val built = buildContentForBlock(block)
+ if(built.hasAnyContent()) supertypes = built
+ }
+
+ private fun buildContentForBlock(block: PageContentBuilder.DocumentableContentBuilder.() -> Unit) =
+ contentFor(
+ dri = mainDri,
+ sourceSets = mainSourceSet,
+ kind = ContentKind.Symbol,
+ extra = mainExtra,
+ block = block
+ )
+
+ fun build(): JavadocSignatureContentNode = JavadocSignatureContentNode(
+ dri = mainDri,
+ annotations = annotations,
+ modifiers = modifiers,
+ signatureWithoutModifiers = signatureWithoutModifiers ?: throw IllegalStateException("JavadocSignatureContentNode should have at least a signature"),
+ supertypes = supertypes
+ )
+ }
+} \ No newline at end of file
diff --git a/plugins/javadoc/src/main/resources/views/class.korte b/plugins/javadoc/src/main/resources/views/class.korte
index 6585e6b4..22793d69 100644
--- a/plugins/javadoc/src/main/resources/views/class.korte
+++ b/plugins/javadoc/src/main/resources/views/class.korte
@@ -32,7 +32,11 @@
</dl>
{% endif %}
<hr>
- <pre>{{ signature|raw }}</pre>
+ <pre>
+{% if signature.annotations != null %}{{ signature.annotations|raw }} {% endif %}
+{{ signature.modifiers }} <span class="typeNameLabel">{{ signature.signatureWithoutModifiers|raw }}</span>
+{% if signature.supertypes != null %}extends {{signature.supertypes|raw}} {% endif %}
+ </pre>
<div class="block">{{ classlikeDocumentation|raw }}</div>
</li>
</ul>
@@ -114,7 +118,7 @@
{% for constructor in constructors %}
<tr class="{{ rowColor(loop.index0) }}">
<th class="colConstructorName" scope="row"><code><span class="memberNameLink"><a
- href="#%3Cinit%3E({{ constructor.inlineParameters }})">{{ constructor.name }}</a></span>({{ constructor.inlineParameters }})</code></th>
+ href="#%3Cinit%3E({{ constructor.inlineParameters }})">{{ constructor.name }}</a></span>({{ constructor.inlineParameters|raw }})</code></th>
<td class="colLast">{{ constructor.brief|raw }}</td>
</tr>
{% endfor %}
@@ -142,7 +146,7 @@
{% for entry in entries %}
<tr class="{{ rowColor(loop.index0) }}">
<th class="colFirst" scope="row"><code><span class="memberNameLink"><a
- href="TODO">{{ entry.signature|raw }}</a></span></code></th>
+ href="TODO">{{ entry.signature.signatureWithoutModifiers|raw }}</a></span></code></th>
<td class="colLast">{{ entry.brief|raw }}</td>
</tr>
{% endfor %}
@@ -173,9 +177,9 @@
</tr>
{% for method in methods.own %}
<tr id="i{{ loop.index0 }}" class="{{ rowColor(loop.index0) }}">
- <td class="colFirst"><code>{{ method.modifiers|raw }}</code>
+ <td class="colFirst"><code>{{ method.signature.modifiers|raw }}</code>
</td>
- <th class="colSecond" scope="row"><code>{{ method.signatureWithoutModifiers|raw }} </code>
+ <th class="colSecond" scope="row"><code>{{ method.signature.signatureWithoutModifiers|raw }} </code>
</th>
<td class="colLast">{{ method.brief|raw }}</td>
</tr>
@@ -222,14 +226,14 @@
<ul class="blockList">
<li class="blockList">
<h4>{{ constructor.name }}</h4>
- <pre>{{ constructor.name }}({{ constructor.inlineParameters }})</pre>
+ <pre>{{ constructor.name }}({{ constructor.inlineParameters|raw }})</pre>
<div class="block">{{ constructor.brief|raw}}</div>
{% if constructor.parameters.size != 0 && hasAnyDescription(constructor.parameters) %}
<dl>
<dt><span class="paramLabel">Parameters:</span></dt>
{% for parameter in constructor.parameters %}
{% if parameter.description != "" %}
- <dd><code>{{ parameter.name }}</code> - {{ parameter.description }}</dd>
+ <dd><code>{{ parameter.name }}</code> - {{ parameter.description|raw }}</dd>
{% endif %}
{% endfor %}
</dl>
@@ -256,8 +260,18 @@
<ul class="blockListLast">
<li class="blockList">
<h4>{{ method.name }}</h4>
- <pre class="methodSignature">{{ method.signature|raw }}</pre>
+ <pre class="methodSignature">{{ method.signature.annotations|raw }} {{ method.signature.modifiers|raw }} {{ method.signature.signatureWithoutModifiers|raw}}</pre>
<div class="block">{{ method.brief|raw }}</div>
+ {% if method.parameters.size != 0 && hasAnyDescription(method.parameters) %}
+ <dl>
+ <dt><span class="paramLabel">Parameters:</span></dt>
+ {% for parameter in method.parameters %}
+ {% if parameter.description != "" %}
+ <dd><code>{{ parameter.name }}</code> - {{ parameter.description|raw }}</dd>
+ {% endif %}
+ {% endfor %}
+ </dl>
+ {% endif %}
<!-- TODO missing return annotation -->
</li>
</ul>
diff --git a/plugins/javadoc/src/test/kotlin/javadoc/AbstractJavadocTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/javadoc/AbstractJavadocTemplateMapTest.kt
index 4fa65c58..7cd42942 100644
--- a/plugins/javadoc/src/test/kotlin/javadoc/AbstractJavadocTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/javadoc/AbstractJavadocTemplateMapTest.kt
@@ -101,7 +101,7 @@ internal abstract class AbstractJavadocTemplateMapTest : AbstractCoreTest() {
throw AssertionError(
"Kotlin and Java Code failed assertions\n" +
"Kotlin: ${kotlinException.message}\n" +
- "Java: ${javaException.message}",
+ "Java : ${javaException.message}",
kotlinException
)
}
diff --git a/plugins/javadoc/src/test/kotlin/javadoc/JavadocClasslikeTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/javadoc/JavadocClasslikeTemplateMapTest.kt
index 0f95894b..dc1573e1 100644
--- a/plugins/javadoc/src/test/kotlin/javadoc/JavadocClasslikeTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/javadoc/JavadocClasslikeTemplateMapTest.kt
@@ -36,7 +36,7 @@ internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest(
assertEquals("com.test.package0", map["packageName"])
assertEquals("Documentation for TestClass", map["classlikeDocumentation"])
assertEquals("Documentation for TestClass", map["subtitle"])
- assertEquals("public final class <a href=TestClass.html>TestClass</a>", map["signature"])
+ assertEquals("public final class <a href=TestClass.html>TestClass</a>", map.signatureWithModifiers())
}
}
@@ -81,21 +81,252 @@ internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest(
assertEquals("com.test.package0", map["packageName"])
assertEquals("Documentation for TestClass", map["classlikeDocumentation"])
assertEquals("Documentation for TestClass", map["subtitle"])
- assertEquals("public final class <a href=TestClass.html>TestClass</a>", map["signature"])
+ assertEquals("public final class", map.modifiers())
+ assertEquals("<a href=TestClass.html>TestClass</a>", map.signatureWithoutModifiers())
val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
val ownMethods = assertIsInstance<List<*>>(methods["own"])
assertEquals(1, ownMethods.size, "Expected only one method")
- val method = assertIsInstance<Map<Any, Any?>>(ownMethods.single())
+ val method = assertIsInstance<Map<String, Any?>>(ownMethods.single())
assertEquals("Documentation for testFunction", method["brief"])
assertEquals("testFunction", method["name"])
assertEquals(
0, assertIsInstance<List<*>>(method["parameters"]).size,
"Expected no parameters"
)
+ assertEquals("final <a href=.html>java.lang.String</a>", method.modifiers())
+ assertEquals("<a href=.html>testFunction</a>()", method.signatureWithoutModifiers())
+ }
+ }
+
+ @Test
+ fun `class with annotation`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ @MustBeDocumented
+ annotation class Author(val name: String)
+
+ @Author(
+ name = "Benjamin Franklin"
+ )
+ class TestClass {`
+
+ @Author(
+ name = "Franklin D. Roosevelt"
+ )
+ fun testFunction(): String = ""
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/Author.java
+ package com.test.package0
+ import java.lang.annotation.Documented;
+
+ @Documented
+ public @interface Author {
+ String name();
+ }
+ /src/com/test/package0/TestClass.java
+ package com.test.package0
+
+ @Author(
+ name = "Benjamin Franklin"
+ )
+ public final class TestClass {
+
+ @Author(
+ name = "Franklin D. Roosevelt"
+ )
+ public final String testFunction() {
+ return "";
+ }
+ }
+ """
+ ){
+ val map = allPagesOfType<JavadocClasslikePageNode>().first { it.name == "TestClass" }.templateMap
+ assertEquals("TestClass", map["name"])
+ val signature = assertIsInstance<Map<String, Any?>>(map["signature"])
+ assertEquals("@<a href=Author.html>Author</a>(name = \"Benjamin Franklin\")", signature["annotations"])
+
+ val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
+ val ownMethods = assertIsInstance<List<*>>(methods["own"])
+ val method = assertIsInstance<Map<String, Any?>>(ownMethods.single())
+ val methodSignature = assertIsInstance<Map<String, Any?>>(method["signature"])
+ assertEquals("@<a href=Author.html>Author</a>(name = \"Franklin D. Roosevelt\")", methodSignature["annotations"])
+ }
+ }
+
+ @Test
+ fun `simple enum`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ enum class ClockDays {
+ /**
+ * Sample docs for first
+ */
+ FIRST,
+ /**
+ * Sample docs for second
+ */
+ SECOND
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ enum ClockDays {
+ /**
+ * Sample docs for first
+ */
+ FIRST,
+ /**
+ * Sample docs for second
+ */
+ SECOND
+ }
+ """
+ ){
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("ClockDays", map["name"])
+ assertEquals("enum", map["kind"])
+ val entries = assertIsInstance<List<Map<String, Any?>>>(map["entries"])
+ assertEquals(2, entries.size)
+
+ val (first, second) = entries
+ assertEquals("Sample docs for first", first["brief"])
+ assertEquals("Sample docs for second", second["brief"])
+
+ assertEquals("<a href=.html>FIRST</a>", first.signatureWithoutModifiers())
+ assertEquals("<a href=.html>SECOND</a>", second.signatureWithoutModifiers())
+ }
+ }
+
+ @Test
+ fun `documented function parameters`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ class TestClass {
+ /**
+ * Simple parameters list to check out
+ * @param simple simple String parameter
+ * @param parameters simple Integer parameter
+ * @param list simple Boolean parameter
+ * @return just a String
+ */
+ fun testFunction(simple: String?, parameters: Int?, list: Boolean?): String {
+ return ""
+ }
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/TestClass.java
+ package com.test.package0;
+ public final class TestClass {
+ /**
+ * Simple parameters list to check out
+ * @param simple simple String parameter
+ * @param parameters simple Integer parameter
+ * @param list simple Boolean parameter
+ * @return just a String
+ */
+ public final String testFunction(String simple, Integer parameters, Boolean list) {
+ return "";
+ }
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("TestClass", map["name"])
+
+ val methods = assertIsInstance<Map<String, Any?>>(map["methods"])
+ val testFunction = assertIsInstance<List<Map<String, Any?>>>(methods["own"]).single()
+ assertEquals("Simple parameters list to check out", testFunction["brief"])
+
+ val (first, second, third) = assertIsInstance<List<Map<String, Any?>>>(testFunction["parameters"])
+ assertParameterNode(
+ node = first,
+ expectedName = "simple",
+ expectedType = "<a href=.html>java.lang.String</a>",
+ expectedDescription = "simple String parameter"
+ )
+ assertParameterNode(
+ node = second,
+ expectedName = "parameters",
+ expectedType = "<a href=.html>java.lang.Integer</a>",
+ expectedDescription = "simple Integer parameter"
+ )
+ assertParameterNode(
+ node = third,
+ expectedName = "list",
+ expectedType = "<a href=.html>java.lang.Boolean</a>",
+ expectedDescription = "simple Boolean parameter"
+ )
+ }
+ }
+
+ @Test
+ fun `with generic parameters`(){
+ dualTestTemplateMapInline(
+ kotlin =
+ """
+ /src/source0.kt
+ package com.test.package0
+ import java.io.Serializable
+
+ class Generic<T : Serializable?> {
+ fun <D : T> sampleFunction(): D = TODO()
+ }
+ """,
+ java =
+ """
+ /src/com/test/package0/Generic.java
+ package com.test.package0;
+ import java.io.Serializable;
+
+ public final class Generic<T extends Serializable> {
+ public final <D extends T> D sampleFunction(){
+ return null;
+ }
+ }
+ """
+ ) {
+ val map = singlePageOfType<JavadocClasslikePageNode>().templateMap
+ assertEquals("Generic", map["name"])
+
assertEquals(
- "final <a href=.html>String</a> <a href=.html>testFunction</a>()", method["signature"]
+ "public final class <a href=Generic.html>Generic</a>&lt;T extends <a href=.html>java.io.Serializable</a>&gt;",
+ map.signatureWithModifiers()
)
+ val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
+ val ownMethods = assertIsInstance<List<*>>(methods["own"]).first()
+ val sampleFunction = assertIsInstance<Map<String, Any?>>(ownMethods)
+
+ assertEquals("final &lt;D extends <a href=Generic.html>T</a>&gt; <a href=.html>D</a> <a href=.html>sampleFunction</a>()", sampleFunction.signatureWithModifiers())
}
}
+
+ private fun assertParameterNode(node: Map<String, Any?>, expectedName: String, expectedType: String, expectedDescription: String){
+ assertEquals(expectedName, node["name"])
+ assertEquals(expectedType, node["type"])
+ assertEquals(expectedDescription, node["description"])
+ }
+
+ private fun Map<String, Any?>.signatureWithModifiers(): String = "${modifiers()} ${signatureWithoutModifiers()}"
+
+ private fun Map<String, Any?>.signatureWithoutModifiers(): String = (get("signature") as Map<String, Any?>)["signatureWithoutModifiers"] as String
+
+ private fun Map<String, Any?>.modifiers(): String = (get("signature") as Map<String, Any?>)["modifiers"] as String
+
}
diff --git a/plugins/javadoc/src/test/kotlin/javadoc/location/JavadocLocationTest.kt b/plugins/javadoc/src/test/kotlin/javadoc/location/JavadocLocationTest.kt
index a47f0142..92620f78 100644
--- a/plugins/javadoc/src/test/kotlin/javadoc/location/JavadocLocationTest.kt
+++ b/plugins/javadoc/src/test/kotlin/javadoc/location/JavadocLocationTest.kt
@@ -54,8 +54,8 @@ class JavadocTest : AbstractCoreTest() {
val testClass = rootPageNode.firstChildOfType<JavadocPackagePageNode>()
.firstChildOfType<JavadocClasslikePageNode>()
assert(
- "public final class <a href=javadoc/Test.html>Test</a> extends <a href=https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html>Cloneable</a>"
- == transformer.htmlForContentNode(testClass.signature, null)
+ "<a href=https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html>java.lang.Cloneable</a>"
+ == transformer.htmlForContentNode(testClass.signature.supertypes!!, null)
)
}
}