diff options
-rw-r--r-- | core/src/main/kotlin/links/DRI.kt | 70 | ||||
-rw-r--r-- | core/src/main/kotlin/pages/ContentNodes.kt | 76 | ||||
-rw-r--r-- | core/src/main/kotlin/pages/PageNodes.kt | 39 | ||||
-rw-r--r-- | core/src/main/kotlin/renderers/DefaultRenderer.kt | 61 | ||||
-rw-r--r-- | core/src/main/kotlin/renderers/FileWriter.kt | 32 | ||||
-rw-r--r-- | core/src/main/kotlin/renderers/HtmlRenderer.kt | 51 | ||||
-rw-r--r-- | core/src/main/kotlin/renderers/Renderer.kt | 14 | ||||
-rw-r--r-- | core/src/main/kotlin/resolvers/DefaultLocationProvider.kt | 80 | ||||
-rw-r--r-- | core/src/main/kotlin/resolvers/ExternalLocationProvider.kt | 98 | ||||
-rw-r--r-- | core/src/main/kotlin/resolvers/LocationProvider.kt | 10 | ||||
-rw-r--r-- | core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt | 29 | ||||
-rw-r--r-- | core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt | 8 | ||||
-rw-r--r-- | core/src/test/kotlin/dri/DRITest.kt | 37 | ||||
-rw-r--r-- | core/src/test/kotlin/externalLocationProviders/ExternalLocationProviderTest.kt | 25 | ||||
-rw-r--r-- | core/src/test/kotlin/linkResolvers/LinkResolverTest.kt | 92 |
15 files changed, 722 insertions, 0 deletions
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt new file mode 100644 index 00000000..64989701 --- /dev/null +++ b/core/src/main/kotlin/links/DRI.kt @@ -0,0 +1,70 @@ +package org.jetbrains.dokka.links + +import java.text.ParseException + +/** + * [DRI] stands for DokkaResourceIdentifier + */ +data class DRI(val packageName: String? = null, + val classNames: String? = null, + val callable: Callable? = null, + val target: Int? = null, + val extra: String? = null) { + + constructor(packageName: String? = null, + classNames: String? = null, + callableName: String? = null, + signature: String? = null, + target: Int? = null, + extra: String? = null) : this(packageName, classNames, Callable.from(callableName, signature), target, extra) + + override fun toString(): String = + "${packageName.orEmpty()}/${classNames.orEmpty()}/${callable?.name.orEmpty()}/${callable?.signature().orEmpty()}/${target?.toString().orEmpty()}/${extra.orEmpty()}" + + companion object { + fun from(s: String): DRI = try { + s.split('/') + .map { it.takeIf(String::isNotBlank) } + .let { (packageName, classNames, callableName, callableSignature, target, ext) -> + DRI( + packageName, + classNames, + try { Callable.from(callableName, callableSignature) } catch(e: ParseException) { null }, + target?.toInt(), + ext + ) + } + } catch (e: Throwable) { + throw ParseException(s, 0) + } + } +} + +data class Callable(val name: String, val receiver: String, val returnType: String, val params: List<String>) { + fun signature() = "$receiver.$returnType.${params.joinToString(".")}" + companion object { + fun from(name: String?, signature: String?): Callable = try { + signature.toString() + .split('#', ignoreCase = false, limit = 3) + .let { (receiver, returnType, params) -> + Callable( + name.toString(), + receiver, + returnType, + params.split('#') + ) + } + } catch (e: Throwable) { + throw ParseException(signature, 0) + } + + fun from(s: String): Callable = try { + s.split('/').let { (name, signature) -> from(name, signature) } + } catch (e: Throwable) { + throw ParseException(s, 0) + } + } +} + +private operator fun <T> List<T>.component6(): T = get(5) + diff --git a/core/src/main/kotlin/pages/ContentNodes.kt b/core/src/main/kotlin/pages/ContentNodes.kt new file mode 100644 index 00000000..6519c313 --- /dev/null +++ b/core/src/main/kotlin/pages/ContentNodes.kt @@ -0,0 +1,76 @@ +package org.jetbrains.dokka.pages + +import org.jetbrains.dokka.links.DRI + +interface ContentNode { + val platforms: List<PlatformData> + val annotations: List<Annotation> +} + +/** Comment consisting of parts, eg. [ContentText]s, [ContentLink]s and so on */ +data class ContentComment(val parts: List<ContentNode>, + override val platforms: List<PlatformData>, + override val annotations: List<Annotation> = emptyList() +): ContentNode + +/** Simple text */ +data class ContentText(val text: String, + override val platforms: List<PlatformData>, + override val annotations: List<Annotation> = emptyList() +): ContentNode + +///** Headers */ TODO for next iteration +//data class ContentHeader(val text: String, +// val level: Int, +// override val platforms: List<PlatformData>, +// override val annotations: List<Annotation> = emptyList() +//): ContentNode +// +///** Lists */ +//data class ContentList(val items: List<ContentNode>, +// val ordered: Boolean, +// override val platforms: List<PlatformData>, +// override val annotations: List<Annotation> = emptyList() +//): ContentNode +// +///** Styled elements, eg. bold, strikethrough, emphasis and so on **/ +//data class ContentStyle(val items: List<ContentNode>, +// val ordered: Boolean, +// override val platforms: List<PlatformData>, +// override val annotations: List<Annotation> = emptyList() +//): ContentNode + +/** Code blocks */ +data class ContentCode(val code: String, + override val platforms: List<PlatformData>, + override val annotations: List<Annotation> = emptyList() +): ContentNode + +/** Symbols, eg. `open fun foo(): String`, or `class Bar`, consisting of parts like [ContentText] and [ContentLink] */ +data class ContentSymbol(val parts: List<ContentNode>, + override val platforms: List<PlatformData>, + override val annotations: List<Annotation> = emptyList() +): ContentNode + +/** All links that have te be resolved */ +data class ContentLink(val text: String, + val address: DRI, + override val platforms: List<PlatformData>, + override val annotations: List<Annotation> = emptyList() +): ContentNode + +/** Blocks of [ContentNode]s with name, eg. Functions, Types, Properties, etc. */ +data class ContentBlock(val name: String, + val children: List<ContentNode>, + override val platforms: List<PlatformData>, + override val annotations: List<Annotation> = emptyList() +): ContentNode + +/** Logical grouping of [ContentNode]s, eg. [ContentLink], [ContentText] and [ContentSymbol] for one entity */ +data class ContentGroup(val children: List<ContentNode>, + override val platforms: List<PlatformData>, + override val annotations: List<Annotation> = emptyList() +): ContentNode + +/** All annotations */ +data class Annotation(val name: String) diff --git a/core/src/main/kotlin/pages/PageNodes.kt b/core/src/main/kotlin/pages/PageNodes.kt new file mode 100644 index 00000000..1bd7f02f --- /dev/null +++ b/core/src/main/kotlin/pages/PageNodes.kt @@ -0,0 +1,39 @@ +package org.jetbrains.dokka.pages + +import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.links.DRI + +abstract class PageNode( + val name: String, + val content: List<ContentNode>, + val parent: PageNode?, + val dri: DRI? +// val declarationNode: DeclarationNode +) { + val children: List<PageNode> + get() = _children + + private val _children: MutableList<PageNode> = mutableListOf() + + fun appendChildren(children: List<PageNode>) = _children.addAll(children) + fun appendChild(child: PageNode) = _children.add(child) + +} + +class ModulePageNode(name: String, content: List<ContentNode>, parent: PageNode?): PageNode(name, content, parent, null) +class PackagePageNode(name: String, content: List<ContentNode>, parent: PageNode, dri: DRI): PageNode(name, content, parent, dri) +class ClassPageNode(name: String, content: List<ContentNode>, parent: PageNode, dri: DRI): PageNode(name, content, parent, dri) // class, companion object +class MemberPageNode(name: String, content: List<ContentNode>, parent: PageNode, dri: DRI): PageNode(name, content, parent, dri) // functions, extension functions, properties + + +data class PlatformData(val platformName: String, val platformType: Platform) + +fun PageNode.platforms(): List<PlatformData> = this.content.flatMap { it.platforms }.distinct() // TODO: Override equals??? +fun PageNode.dfs(predicate: (PageNode) -> Boolean): PageNode? = if (predicate(this)) { this } else { this.children.asSequence().mapNotNull { it.dfs(predicate) }.firstOrNull() } + + + +// Navigation?? + +// content modifier? +//data class ContentLink(val link: String): ContentNode
\ No newline at end of file diff --git a/core/src/main/kotlin/renderers/DefaultRenderer.kt b/core/src/main/kotlin/renderers/DefaultRenderer.kt new file mode 100644 index 00000000..b2647d22 --- /dev/null +++ b/core/src/main/kotlin/renderers/DefaultRenderer.kt @@ -0,0 +1,61 @@ +package org.jetbrains.dokka.renderers + +import org.jetbrains.dokka.pages.* +import org.jetbrains.dokka.resolvers.LocationProvider + +abstract class DefaultRenderer(val outputDir: String, val fileWriter: FileWriter, val locationProvider: LocationProvider): Renderer { + + protected abstract fun buildHeader(level: Int, text: String): String + protected abstract fun buildNewLine(): String + protected abstract fun buildLink(text: String, address: String): String + protected abstract fun buildCode(code: String): String + protected abstract fun buildNavigation(): String // TODO + protected open fun buildText(text: String): String = text + protected open fun buildGroup(children: List<ContentNode>): String = children.joinToString { it.build() } + protected open fun buildComment(parts: List<ContentNode>): String = parts.joinToString { it.build() } + protected open fun buildSymbol(parts: List<ContentNode>): String = parts.joinToString { it.build() } + protected open fun buildBlock(name: String, content: List<ContentNode>) = buildHeader(2, name) + content.joinToString("\n") { it.build() } + + protected open fun ContentNode.build(): String = + when(this) { + is ContentText -> buildText(this.text) + is ContentComment -> buildComment(this.parts) + is ContentSymbol -> buildSymbol(this.parts) + is ContentCode -> buildCode(this.code) + is ContentBlock -> buildBlock(this.name, this.children) + is ContentLink -> buildLink(this.text, locationProvider.resolve(this.address, this.platforms)) + is ContentGroup -> buildGroup(this.children) + else -> "" + } + + protected open fun buildPageContent(page: PageNode): String = + buildHeader(1, page.name) + page.content.joinToString("\n") { it.build() } + + protected open fun renderPage(page: PageNode) = fileWriter.write(locationProvider.resolve(page), buildPageContent(page)) + + protected open fun renderPages(root: PageNode) { + renderPage(root) + root.children.forEach { renderPages(it) } + } + + protected open fun renderPackageList(root: PageNode) = + getPackageNamesAndPlatforms(root) + .keys + .joinToString("\n") + .also { fileWriter.write("package-list", it, "") } + + protected open fun getPackageNamesAndPlatforms(root: PageNode): Map<String, List<PlatformData>> = + root.children + .map(::getPackageNamesAndPlatforms) + .fold(emptyMap<String, List<PlatformData>>()) { e, acc -> acc + e } + + if (root is PackagePageNode) { + mapOf(root.name to root.platforms()) + } else { + emptyMap() + } + + override fun render(root: PageNode) { + renderPackageList(root) + renderPages(root) + } +} diff --git a/core/src/main/kotlin/renderers/FileWriter.kt b/core/src/main/kotlin/renderers/FileWriter.kt new file mode 100644 index 00000000..319926dd --- /dev/null +++ b/core/src/main/kotlin/renderers/FileWriter.kt @@ -0,0 +1,32 @@ +package org.jetbrains.dokka.renderers + +import java.io.File +import java.io.IOException +import java.nio.file.Paths + +class FileWriter(val root: String, val extension: String){ + private val createdFiles: MutableMap<String, Int> = mutableMapOf() + + fun write(path: String, text: String, ext: String = extension){ + if (createdFiles.getOrDefault(path, 0) > 0) { + println("ERROR. An attempt to write $root/$path several times!") + return + } + + try { + println("Writing $root/$path$ext") + val dir = Paths.get(root, path.dropLastWhile { it != '/' }).toFile() + dir.mkdirsOrFail() + Paths.get(root, "$path$ext").toFile().writeText(text) + } catch (e : Throwable) { + println("Failed to write $this. ${e.message}") + e.printStackTrace() + } + } + + private fun File.mkdirsOrFail() { + if (!mkdirs() && !exists()) { + throw IOException("Failed to create directory $this") + } + } +}
\ No newline at end of file diff --git a/core/src/main/kotlin/renderers/HtmlRenderer.kt b/core/src/main/kotlin/renderers/HtmlRenderer.kt new file mode 100644 index 00000000..3a6e1576 --- /dev/null +++ b/core/src/main/kotlin/renderers/HtmlRenderer.kt @@ -0,0 +1,51 @@ +package org.jetbrains.dokka.renderers + +import org.jetbrains.dokka.pages.ContentLink +import org.jetbrains.dokka.pages.ContentNode +import org.jetbrains.dokka.pages.PageNode +import org.jetbrains.dokka.resolvers.LocationProvider + +open class HtmlRenderer(outputDir: String, fileWriter: FileWriter, locationProvider: LocationProvider): DefaultRenderer(outputDir, fileWriter, locationProvider) { + + override fun buildComment(parts: List<ContentNode>): String = "<p>${super.buildComment(parts)}</p>" + + override fun buildSymbol(parts: List<ContentNode>): String = "<code>${super.buildSymbol(parts)}</code>" + + override fun buildHeader(level: Int, text: String): String = "<h$level>$text</h$level>\n" + + override fun buildNewLine(): String = "<br/>" + + override fun buildLink(text: String, address: String): String = "<a href=\"$address\">$text</a>" + + override fun buildCode(code: String): String = "<code>$code</code>" + + override fun buildNavigation(): String = "" // TODO implement + + override fun buildGroup(children: List<ContentNode>): String = "<tr>\n" + + "<td>" + children.find { it is ContentLink }?.build() + "</td>\n" + + "<td>" + children.filterNot { it is ContentLink }.joinToString("\n") { it.build() } + "</td>\n" + + "</tr>\n" + + override fun buildBlock(name: String, content: List<ContentNode>): String = + buildHeader(2, name) + "<table>\n" + content.joinToString("\n") { it.build() } + "</table>" + + override fun renderPage(page: PageNode) { + val pageText = buildStartHtml(page) + buildPageContent(page) + buildEndHtml() + fileWriter.write(locationProvider.resolve(page), pageText) + } + + protected open fun buildStartHtml(page: PageNode) = """<!DOCTYPE html> + |<html> + |<head> + |<title>${page.name}</title> + |</head> + |<body> + |""".trimMargin() + + protected open fun buildEndHtml() = + """ + | + |</body> + |</html> + """.trimMargin() +}
\ No newline at end of file diff --git a/core/src/main/kotlin/renderers/Renderer.kt b/core/src/main/kotlin/renderers/Renderer.kt new file mode 100644 index 00000000..24e01cdb --- /dev/null +++ b/core/src/main/kotlin/renderers/Renderer.kt @@ -0,0 +1,14 @@ +package org.jetbrains.dokka.renderers + +import org.jetbrains.dokka.pages.PageNode + +interface Renderer { + fun render(root: PageNode) +} + +//class Renderers{ +// abstract class Renderer(resolvers: List[Resolver]) +// class HtmlRenderer(list) +// fun toHtml() = { +// new HtmlRenderer(a, b,c) +//}
\ No newline at end of file diff --git a/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt b/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt new file mode 100644 index 00000000..6120e65e --- /dev/null +++ b/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt @@ -0,0 +1,80 @@ +package org.jetbrains.dokka.resolvers + +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.htmlEscape +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.pages.* + +open class DefaultLocationProvider(private val pageGraphRoot: PageNode, val configuration: DokkaConfiguration, val extension: String): LocationProvider { // TODO: cache + override fun resolve(node: PageNode): String = pathTo(node) + extension + + override fun resolve(dri: DRI, platforms: List<PlatformData>): String { + findInPageGraph(dri, platforms)?.let { return resolve(it) } + // Not found in PageGraph, that means it's an external link + + val externalDocs = configuration.passesConfigurations + .filter { passConfig -> passConfig.targets.toSet() == platforms.toSet() } // TODO: change targets to something better? + .flatMap { it.externalDocumentationLinks }.map { it.packageListUrl }.distinct() + + return ExternalLocationProvider.getLocation(dri, externalDocs) + } + + protected open fun findInPageGraph(dri: DRI, platforms: List<PlatformData>): PageNode? = pageGraphRoot.dfs { it.dri == dri } + + protected open fun pathTo(node: PageNode): String { // TODO: can be refactored probably, also we should think about root + fun parentPath(parent: PageNode?): String { + if(parent == null) return "" + val parts = parent.parent?.let(::parentPath) ?: "" + return if(parent is PackagePageNode) {"$parts/${parent.name}"} else { "$parts/${identifierToFilename(parent.name)}" } + } + + return parentPath(node.parent) + "/${identifierToFilename(node.name)}" + + if (node.children.isEmpty()) { + "" + } else { + "/index" + } + } +} + +fun DRI.toJavadocLocation(jdkVersion: Int): String { // TODO: classes without packages? + val packageLink = packageName?.replace(".", "/") + if (classNames == null) { + return "$packageLink/package-summary.html".htmlEscape() + } + val classLink = if (packageLink == null) { "$classNames.html" } else { "$packageLink/$classNames.html" } + if (callable == null) { + return classLink.htmlEscape() + } + + val callableLink = "$classLink#${callable.name}" + when { + jdkVersion < 8 -> "(${callable.params.joinToString(", ")})" + jdkVersion < 10 -> "-${callable.params.joinToString("-")}-" + else -> "(${callable.params.joinToString(",")})" + } + + return callableLink.htmlEscape() +} + +fun DRI.toDokkaLocation(extension: String): String { // TODO: classes without packages? + if (classNames == null) { + return "$packageName/index$extension" + } + val classLink = if (packageName == null) { "" } else { "$packageName/" } + + classNames.split('.').joinToString("/", transform = ::identifierToFilename) + + if (callable == null) { + return "$classLink/index$extension" + } + + return "$classLink/${identifierToFilename(callable.name)}$extension" +} + +private val reservedFilenames = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out") + +private fun identifierToFilename(name: String): String { + if (name.isEmpty()) return "--root--" + val escaped = name.replace('<', '-').replace('>', '-') + val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() } + return if (lowercase in reservedFilenames) "--$lowercase--" else lowercase +} diff --git a/core/src/main/kotlin/resolvers/ExternalLocationProvider.kt b/core/src/main/kotlin/resolvers/ExternalLocationProvider.kt new file mode 100644 index 00000000..e9181148 --- /dev/null +++ b/core/src/main/kotlin/resolvers/ExternalLocationProvider.kt @@ -0,0 +1,98 @@ +package org.jetbrains.dokka.resolvers + +import org.jetbrains.dokka.links.DRI +import java.net.HttpURLConnection +import java.net.URL +import java.net.URLConnection + +object ExternalLocationProvider { // TODO: Refactor this!!! + private const val DOKKA_PARAM_PREFIX = "\$dokka." + + private val cache: MutableMap<URL, LocationInfo> = mutableMapOf() + + fun getLocation(dri: DRI, packageLocations: List<URL>): String { + val toResolve: MutableList<URL> = mutableListOf() + for(url in packageLocations){ + val info = cache[url] + if(info == null) { + toResolve.add(url) + } else if(info.packages.contains(dri.packageName)) { + return getLink(dri, info) + } + } + // Not in cache, resolve packageLists + while (toResolve.isNotEmpty()){ + val loc = toResolve.first().also { toResolve.remove(it) } + val locationInfo = loadPackageList(loc) + if(locationInfo.packages.contains(dri.packageName)) { + return getLink(dri, locationInfo) + } + } + return "" + } + + private fun getLink(dri: DRI, locationInfo: LocationInfo): String = when(locationInfo.format) { + "javadoc" -> dri.toJavadocLocation(8) + "kotlin-website-html", "html" -> locationInfo.locations[dri.packageName + "." + dri.classNames] ?: dri.toDokkaLocation(".html") + "markdown" -> locationInfo.locations[dri.packageName + "." + dri.classNames] ?: dri.toDokkaLocation(".md") + // TODO: rework this + else -> throw RuntimeException("Unrecognized format") + } + + + private fun loadPackageList(url: URL): LocationInfo { + val packageListStream = url.doOpenConnectionToReadContent().getInputStream() + val (params, packages) = + packageListStream + .bufferedReader() + .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } } + + val paramsMap = params.asSequence() + .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) } + .groupBy({ (key, _) -> key }, { (_, value) -> value }) + + val format = paramsMap["format"]?.singleOrNull() ?: "javadoc" + + val locations = paramsMap["location"].orEmpty() + .map { it.split("\u001f", limit = 2) } + .map { (key, value) -> key to value } + .toMap() + + val info = LocationInfo(format, packages.toSet(), locations) + cache[url] = info + return info + } + + private fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection { + val connection = this.openConnection().apply { + connectTimeout = timeout + readTimeout = timeout + } + + when (connection) { + is HttpURLConnection -> { + return when (connection.responseCode) { + in 200..299 -> { + connection + } + HttpURLConnection.HTTP_MOVED_PERM, + HttpURLConnection.HTTP_MOVED_TEMP, + HttpURLConnection.HTTP_SEE_OTHER -> { + if (redirectsAllowed > 0) { + val newUrl = connection.getHeaderField("Location") + URL(newUrl).doOpenConnectionToReadContent(timeout, redirectsAllowed - 1) + } else { + throw RuntimeException("Too many redirects") + } + } + else -> { + throw RuntimeException("Unhandled http code: ${connection.responseCode}") + } + } + } + else -> return connection + } + } + data class LocationInfo(val format: String, val packages: Set<String>, val locations: Map<String, String>) + +} diff --git a/core/src/main/kotlin/resolvers/LocationProvider.kt b/core/src/main/kotlin/resolvers/LocationProvider.kt new file mode 100644 index 00000000..b62aa999 --- /dev/null +++ b/core/src/main/kotlin/resolvers/LocationProvider.kt @@ -0,0 +1,10 @@ +package org.jetbrains.dokka.resolvers + +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.pages.PageNode +import org.jetbrains.dokka.pages.PlatformData + +interface LocationProvider { + fun resolve(dri: DRI, platforms: List<PlatformData>): String + fun resolve(node: PageNode): String +} diff --git a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt new file mode 100644 index 00000000..13e9b0d0 --- /dev/null +++ b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt @@ -0,0 +1,29 @@ +package org.jetbrains.dokka.transformers + +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.DocumentationNodes +import org.jetbrains.dokka.pages.ContentNode +import org.jetbrains.dokka.pages.ContentSymbol +import org.jetbrains.dokka.pages.ModulePageNode +import org.jetbrains.dokka.pages.PageNode + +//class DefaultDocumentationToPageTransformer: DocumentationToPageTransformer { +// override fun transform(d: DocumentationNode): PageNode { +// assert(d is DocumentationNodes.Module) // TODO: remove this if it's true. Fix this it it's not +// val rootPage = ModulePageNode(d.name, contentFor(d), null) +// +// // TODO +// +// return rootPage +// } +// +// private fun contentFor(d: DocumentationNode): List<ContentNode> { +// val symbol = ContentSymbol() +// } +// private fun moduleContent(d: DocumentationNodes.Module) +// +// private fun symbolFor(d: DocumentationNode): List<ContentNode> { +// +// } +// +//}
\ No newline at end of file diff --git a/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt new file mode 100644 index 00000000..5a155dc1 --- /dev/null +++ b/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt @@ -0,0 +1,8 @@ +package org.jetbrains.dokka.transformers + +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.pages.PageNode + +interface DocumentationToPageTransformer { + fun transform (d: DocumentationNode): PageNode +}
\ No newline at end of file diff --git a/core/src/test/kotlin/dri/DRITest.kt b/core/src/test/kotlin/dri/DRITest.kt new file mode 100644 index 00000000..b763bce8 --- /dev/null +++ b/core/src/test/kotlin/dri/DRITest.kt @@ -0,0 +1,37 @@ +package org.jetbrains.dokka.tests.dri + +import org.jetbrains.dokka.links.Callable +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.resolvers.toJavadocLocation +import org.junit.Test +import kotlin.test.assertEquals + +class DRITest { + @Test + fun onlyClassNames() { + val expected = DRI(classNames = "className1.className2") + val actual = DRI.from("/className1.className2////") + assertEquals(expected, actual) + } + + @Test + fun fullDRI() { + val expected = DRI("org.dokka", "className1.className2", Callable("<init>", "", "", listOf("Int")), 2, "something" ) + val actual = DRI.from("org.dokka/className1.className2/<init>/..Int/2/something") + assertEquals(expected, actual) + } + + @Test + fun onlyExtra() { + val expected = DRI(null, null, null, null, "extra" ) + val actual = DRI.from("/////extra") + assertEquals(expected, actual) + } + + @Test + fun javadoc8Location() { + val dri = DRI("org.jetbrains.dokka", "DRITest", "javadocLocation", ".void.") + assertEquals("org/jetbrains/dokka/DRITest.html#javadocLocation--", dri.toJavadocLocation(8)) + } +} + diff --git a/core/src/test/kotlin/externalLocationProviders/ExternalLocationProviderTest.kt b/core/src/test/kotlin/externalLocationProviders/ExternalLocationProviderTest.kt new file mode 100644 index 00000000..860f4534 --- /dev/null +++ b/core/src/test/kotlin/externalLocationProviders/ExternalLocationProviderTest.kt @@ -0,0 +1,25 @@ +package org.jetbrains.dokka.tests.externalLocationProviders + +import junit.framework.Assert.assertEquals +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.resolvers.ExternalLocationProvider +import org.junit.Test + + +class ExternalLocationProviderTest { + val stdlibLink = DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() + @Test fun kotlinString() { + val dri = DRI("kotlin", "String") + val link = ExternalLocationProvider.getLocation(dri, listOf(stdlibLink.packageListUrl)) + assertEquals("kotlin/-string/index.html", link) + } + + @Test fun kotlinCompareTo() { + val dri = DRI("kotlin", "String", "compareTo", "#Int#String") + val link = ExternalLocationProvider.getLocation(dri, listOf(stdlibLink.packageListUrl)) + assertEquals("kotlin/-string/compare-to.html", link) + } + +} + diff --git a/core/src/test/kotlin/linkResolvers/LinkResolverTest.kt b/core/src/test/kotlin/linkResolvers/LinkResolverTest.kt new file mode 100644 index 00000000..b2cccce2 --- /dev/null +++ b/core/src/test/kotlin/linkResolvers/LinkResolverTest.kt @@ -0,0 +1,92 @@ +package org.jetbrains.dokka.tests.linkResolvers +// +//import junit.framework.Assert.assertEquals +//import org.jetbrains.dokka.testApi.DokkaConfigurationImpl +//import org.jetbrains.dokka.Platform +//import org.jetbrains.dokka.links.DRI +//import org.jetbrains.dokka.pages.* +//import org.jetbrains.dokka.renderers.FileWriter +//import org.jetbrains.dokka.renderers.NewHtmlRenderer +//import org.jetbrains.dokka.resolvers.DefaultLocationProvider +//import org.junit.Test +// +// +//class LinkResolverTest { +// +// fun createModel(): ModulePageNode { +// val platform = listOf(PlatformData("jvm", Platform.jvm)) +// +// val moduleSymbol = ContentSymbol( +// listOf(ContentText("moduleName", platform)), +// platform) +// +// val packageDRI = DRI("packageName") +// +// val module = ModulePageNode("", +// listOf(moduleSymbol, ContentBlock( +// "packages", +// listOf(ContentGroup(listOf(ContentLink("packageName", packageDRI, platform)), platform)), +// platform) +// ), +// null) +// +// val packageSymbol = ContentSymbol( +// listOf(ContentText("package moduleName.packageName", platform)), +// platform) +// +// val packageNode = PackagePageNode("packageName", listOf(packageSymbol), module, DRI("packageName")) +// +// val classSymbol = ContentSymbol( +// listOf(ContentText("class ClassName()", platform)), +// platform) +// +// val classNode = ClassPageNode("className", listOf(classSymbol), packageNode, DRI("packageName", "className")) +// +// val memberSymbol = ContentSymbol( +// listOf(ContentText("fun funName(): String", platform)), +// platform) +// +// val memberText = ContentText("This is some docs for funName", platform) +// +// val memberNode = MemberPageNode("funName", +// listOf(memberSymbol, ContentComment(listOf(memberText), platform)), +// classNode, +// DRI("packageName", "className", "funName", "...")) +// +// module.appendChild(packageNode) +// packageNode.appendChild(classNode) +// classNode.appendChild(memberNode) +// return module +// } +// +// @Test fun memberLink() { +// val model = createModel() +// val linkResolver = DefaultLocationProvider(model, DokkaConfigurationImpl()) +// val link = linkResolver.resolve(model.children.first().children.first().children.first()) +// assertEquals("/--root--/package-name/class-name/fun-name", link) +// } +// +// @Test fun classLink() { +// val model = createModel() +// val linkResolver = DefaultLocationProvider(model, DokkaConfigurationImpl()) +// val link = linkResolver.resolve(model.children.first().children.first()) +// assertEquals("/--root--/package-name/class-name/index", link) +// } +// +// @Test fun moduleLink() { +// val model = createModel() +// val linkResolver = DefaultLocationProvider(model, DokkaConfigurationImpl()) +// val link = linkResolver.resolve(model) +// assertEquals("/--root--/index", link) +// } +// +// @Test fun writeToFile() { +// val model = createModel() +// val linkResolver = DefaultLocationProvider(model, DokkaConfigurationImpl()) +// val fileWriter = FileWriter("/Users/kamildoleglo/IdeaProjects/dokka/build/dokka", ".html") +// val renderer = NewHtmlRenderer("/Users/kamildoleglo/IdeaProjects/dokka/build/dokka", fileWriter, linkResolver) +// renderer.render(model) +// } +// +//} +// |