aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin
diff options
context:
space:
mode:
authorPaweł Marks <pmarks@virtuslab.com>2020-02-17 12:35:15 +0100
committerPaweł Marks <Kordyjan@users.noreply.github.com>2020-02-18 13:28:23 +0100
commita89d9a8c87cbe81bdba25b660d1b1fda1d0ce8ec (patch)
tree8e55f99386415fe644c6223a53825cf12022f8db /core/src/main/kotlin
parentba769f0695aaa9719b62ca32028fd3d24442f5ec (diff)
downloaddokka-a89d9a8c87cbe81bdba25b660d1b1fda1d0ce8ec.tar.gz
dokka-a89d9a8c87cbe81bdba25b660d1b1fda1d0ce8ec.tar.bz2
dokka-a89d9a8c87cbe81bdba25b660d1b1fda1d0ce8ec.zip
Moves location providers and output writers to base plugin
Diffstat (limited to 'core/src/main/kotlin')
-rw-r--r--core/src/main/kotlin/CoreExtensions.kt5
-rw-r--r--core/src/main/kotlin/plugability/DefaultExtensions.kt7
-rw-r--r--core/src/main/kotlin/renderers/FileWriter.kt78
-rw-r--r--core/src/main/kotlin/renderers/OutputWriter.kt7
-rw-r--r--core/src/main/kotlin/resolvers/DefaultLocationProvider.kt121
-rw-r--r--core/src/main/kotlin/resolvers/ExternalLocationProvider.kt99
-rw-r--r--core/src/main/kotlin/resolvers/LocationProvider.kt13
-rw-r--r--core/src/main/kotlin/resolvers/LocationProviderFactory.kt14
8 files changed, 0 insertions, 344 deletions
diff --git a/core/src/main/kotlin/CoreExtensions.kt b/core/src/main/kotlin/CoreExtensions.kt
index 859e850e..c8314f4d 100644
--- a/core/src/main/kotlin/CoreExtensions.kt
+++ b/core/src/main/kotlin/CoreExtensions.kt
@@ -2,8 +2,6 @@ package org.jetbrains.dokka
import org.jetbrains.dokka.plugability.ExtensionPoint
import org.jetbrains.dokka.renderers.Renderer
-import org.jetbrains.dokka.renderers.OutputWriter
-import org.jetbrains.dokka.resolvers.LocationProviderFactory
import org.jetbrains.dokka.transformers.descriptors.DescriptorToDocumentationTranslator
import org.jetbrains.dokka.transformers.documentation.DocumentableMerger
import org.jetbrains.dokka.transformers.documentation.DocumentationNodeTransformer
@@ -26,9 +24,6 @@ object CoreExtensions {
val pageTransformer by coreExtension<PageNodeTransformer>()
val renderer by coreExtension<Renderer>()
- val locationProviderFactory by coreExtension<LocationProviderFactory>()
- val outputWriter by coreExtension<OutputWriter>()
-
private fun <T: Any> coreExtension() = object {
operator fun provideDelegate(thisRef: CoreExtensions, property: KProperty<*>): Lazy<ExtensionPoint<T>> =
lazy { ExtensionPoint<T>(thisRef::class.qualifiedName!!, property.name) }
diff --git a/core/src/main/kotlin/plugability/DefaultExtensions.kt b/core/src/main/kotlin/plugability/DefaultExtensions.kt
index 242eb6b8..798e0f1a 100644
--- a/core/src/main/kotlin/plugability/DefaultExtensions.kt
+++ b/core/src/main/kotlin/plugability/DefaultExtensions.kt
@@ -1,20 +1,13 @@
package org.jetbrains.dokka.plugability
import org.jetbrains.dokka.CoreExtensions
-import org.jetbrains.dokka.renderers.FileWriter
-import org.jetbrains.dokka.renderers.OutputWriter
-import org.jetbrains.dokka.resolvers.DefaultLocationProviderFactory
internal object DefaultExtensions {
- private val providerFactory: LazyEvaluated<DefaultLocationProviderFactory> = LazyEvaluated.fromRecipe { DefaultLocationProviderFactory(it) }
- private val outputWriter: LazyEvaluated<OutputWriter> = LazyEvaluated.fromRecipe { FileWriter(it) }
@Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
internal fun <T : Any, E : ExtensionPoint<T>> get(point: E, fullContext: DokkaContext): List<T> =
when (point) {
- CoreExtensions.locationProviderFactory -> providerFactory.get(fullContext)
- CoreExtensions.outputWriter -> outputWriter.get(fullContext)
else -> null
}.let { listOfNotNull( it ) as List<T> }
} \ No newline at end of file
diff --git a/core/src/main/kotlin/renderers/FileWriter.kt b/core/src/main/kotlin/renderers/FileWriter.kt
deleted file mode 100644
index 727a8d21..00000000
--- a/core/src/main/kotlin/renderers/FileWriter.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.jetbrains.dokka.renderers
-
-import org.jetbrains.dokka.plugability.DokkaContext
-import java.io.File
-import java.io.IOException
-import java.net.URI
-import java.nio.file.*
-
-class FileWriter(val context: DokkaContext): OutputWriter {
- private val createdFiles: MutableSet<String> = mutableSetOf()
- private val jarUriPrefix = "jar:file:"
- private val root = context.configuration.outputDir
-
- override fun write(path: String, text: String, ext: String) {
- if (createdFiles.contains(path)) {
- context.logger.error("An attempt to write ${root}/$path several times!")
- return
- }
- createdFiles.add(path)
-
- try {
- val dir = Paths.get(root, path.dropLastWhile { it != '/' }).toFile()
- dir.mkdirsOrFail()
- Files.write(Paths.get(root, "$path$ext"), text.lines())
- } catch (e: Throwable) {
- context.logger.error("Failed to write $this. ${e.message}")
- e.printStackTrace()
- }
- }
-
- override fun writeResources(pathFrom: String, pathTo: String) =
- if (javaClass.getResource(pathFrom).toURI().toString().startsWith(jarUriPrefix)) {
- copyFromJar(pathFrom, pathTo)
- } else {
- copyFromDirectory(pathFrom, pathTo)
- }
-
-
- private fun copyFromDirectory(pathFrom: String, pathTo: String) {
- val dest = Paths.get(root, pathTo).toFile()
- val uri = javaClass.getResource(pathFrom).toURI()
- File(uri).copyRecursively(dest, true)
- }
-
- private fun copyFromJar(pathFrom: String, pathTo: String) {
- val rebase = fun(path: String) =
- "$pathTo/${path.removePrefix(pathFrom)}"
- val dest = Paths.get(root, pathTo).toFile()
- dest.mkdirsOrFail()
- val uri = javaClass.getResource(pathFrom).toURI()
- val fs = getFileSystemForURI(uri)
- val path = fs.getPath(pathFrom)
- for (file in Files.walk(path).iterator()) {
- if (Files.isDirectory(file)) {
- val dirPath = file.toAbsolutePath().toString()
- Paths.get(root, rebase(dirPath)).toFile().mkdirsOrFail()
- } else {
- val filePath = file.toAbsolutePath().toString()
- Paths.get(root, rebase(filePath)).toFile().writeBytes(
- javaClass.getResourceAsStream(filePath).readBytes()
- )
- }
- }
- }
-
- private fun File.mkdirsOrFail() {
- if (!mkdirs() && !exists()) {
- throw IOException("Failed to create directory $this")
- }
- }
-
- private fun getFileSystemForURI(uri: URI): FileSystem =
- try {
- FileSystems.newFileSystem(uri, emptyMap<String, Any>())
- } catch (e: FileSystemAlreadyExistsException) {
- FileSystems.getFileSystem(uri)
- }
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/renderers/OutputWriter.kt b/core/src/main/kotlin/renderers/OutputWriter.kt
deleted file mode 100644
index e317f8ef..00000000
--- a/core/src/main/kotlin/renderers/OutputWriter.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.jetbrains.dokka.renderers
-
-interface OutputWriter {
-
- fun write(path: String, text: String, ext: String)
- fun writeResources(pathFrom: String, pathTo: String)
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt b/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt
deleted file mode 100644
index 65d2f794..00000000
--- a/core/src/main/kotlin/resolvers/DefaultLocationProvider.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.jetbrains.dokka.resolvers
-
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.utilities.htmlEscape
-import java.util.*
-
-private const val PAGE_WITH_CHILDREN_SUFFIX = "index"
-
-open class DefaultLocationProvider(
- protected val pageGraphRoot: RootPageNode,
- protected val dokkaContext: DokkaContext
-) : LocationProvider {
- protected val extension = ".html"
-
- protected val pagesIndex: Map<DRI, ContentPage> = pageGraphRoot.asSequence().filterIsInstance<ContentPage>()
- .map { it.dri.map { dri -> dri to it } }.flatten()
- .groupingBy { it.first }
- .aggregate { dri, _, (_, page), first ->
- if (first) page else throw AssertionError("Multiple pages associated with dri: $dri")
- }
-
- protected val pathsIndex: Map<PageNode, List<String>> = IdentityHashMap<PageNode, List<String>>().apply {
- fun registerPath(page: PageNode, prefix: List<String>) {
- val newPrefix = prefix + page.pathName
- put(page, newPrefix)
- page.children.forEach { registerPath(it, newPrefix) }
- }
- put(pageGraphRoot, emptyList())
- pageGraphRoot.children.forEach { registerPath(it, emptyList()) }
- }
-
- override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean): String =
- pathTo(node, context) + if (!skipExtension) extension else ""
-
- override fun resolve(dri: DRI, platforms: List<PlatformData>, context: PageNode?): String =
- pagesIndex[dri]?.let { resolve(it, context) } ?:
- // Not found in PageGraph, that means it's an external link
- ExternalLocationProvider.getLocation(dri,
- this.dokkaContext.configuration.passesConfigurations
- .filter { passConfig ->
- platforms.toSet()
- .contains(PlatformData(passConfig.moduleName, passConfig.analysisPlatform, passConfig.targets))
- } // TODO: change targets to something better?
- .flatMap { it.externalDocumentationLinks }.distinct()
- )
-
- override fun resolveRoot(node: PageNode): String =
- pathTo(pageGraphRoot, node).removeSuffix(PAGE_WITH_CHILDREN_SUFFIX)
-
- override fun ancestors(node: PageNode): List<PageNode> =
- generateSequence(node) { it.parent() }.toList()
-
- protected open fun pathTo(node: PageNode, context: PageNode?): String {
- fun pathFor(page: PageNode) = pathsIndex[page] ?: throw AssertionError(
- "${page::class.simpleName}(${page.name}) does not belong to current page graph so it is impossible to compute its path"
- )
-
- val contextNode =
- if (context?.children?.isEmpty() == true && context.parent() != null) context.parent() else context
- val nodePath = pathFor(node)
- val contextPath = contextNode?.let { pathFor(it) }.orEmpty()
-
- val commonPathElements = nodePath.asSequence().zip(contextPath.asSequence())
- .takeWhile { (a, b) -> a == b }.count()
-
- return (List(contextPath.size - commonPathElements) { ".." } + nodePath.drop(commonPathElements) +
- if (node.children.isNotEmpty()) listOf(PAGE_WITH_CHILDREN_SUFFIX) else emptyList()).joinToString("/")
- }
-
- private fun PageNode.parent() = pageGraphRoot.parentMap[this]
-}
-
-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
-}
-
-private val PageNode.pathName: String
- get() = if (this is PackagePageNode) name else identifierToFilename(name)
diff --git a/core/src/main/kotlin/resolvers/ExternalLocationProvider.kt b/core/src/main/kotlin/resolvers/ExternalLocationProvider.kt
deleted file mode 100644
index d3d8fa0d..00000000
--- a/core/src/main/kotlin/resolvers/ExternalLocationProvider.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.jetbrains.dokka.resolvers
-
-import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
-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, externalDocumentationLinks: List<ExternalDocumentationLink>): String {
- val toResolve: MutableList<ExternalDocumentationLink> = mutableListOf()
- for(link in externalDocumentationLinks){
- val info = cache[link.packageListUrl]
- if(info == null) {
- toResolve.add(link)
- } else if(info.packages.contains(dri.packageName)) {
- return link.url.toExternalForm() + getLink(dri, info)
- }
- }
- // Not in cache, resolve packageLists
- while (toResolve.isNotEmpty()){
- val link = toResolve.first().also { toResolve.remove(it) }
- val locationInfo = loadPackageList(link.packageListUrl)
- if(locationInfo.packages.contains(dri.packageName)) {
- return link.url.toExternalForm() + 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
deleted file mode 100644
index 3bc9ab72..00000000
--- a/core/src/main/kotlin/resolvers/LocationProvider.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.jetbrains.dokka.resolvers
-
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.pages.ContentPage
-import org.jetbrains.dokka.pages.PageNode
-import org.jetbrains.dokka.pages.PlatformData
-
-interface LocationProvider {
- fun resolve(dri: DRI, platforms: List<PlatformData>, context: PageNode? = null): String
- fun resolve(node: PageNode, context: PageNode? = null, skipExtension: Boolean = false): String
- fun resolveRoot(node: PageNode): String
- fun ancestors(node: PageNode): List<PageNode>
-}
diff --git a/core/src/main/kotlin/resolvers/LocationProviderFactory.kt b/core/src/main/kotlin/resolvers/LocationProviderFactory.kt
deleted file mode 100644
index 782795de..00000000
--- a/core/src/main/kotlin/resolvers/LocationProviderFactory.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.jetbrains.dokka.resolvers
-
-import org.jetbrains.dokka.pages.ModulePageNode
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-
-interface LocationProviderFactory {
- fun getLocationProvider(pageNode: RootPageNode): LocationProvider
-}
-
-class DefaultLocationProviderFactory(val context: DokkaContext) : LocationProviderFactory {
-
- override fun getLocationProvider(pageNode: RootPageNode) = DefaultLocationProvider(pageNode, context)
-} \ No newline at end of file