From f625cef495d625d81ee22e950083f57cc4fab875 Mon Sep 17 00:00:00 2001 From: Paweł Marks Date: Mon, 17 Feb 2020 09:32:35 +0100 Subject: Moves PsiToDocumentablesTranslator to the base plugin --- .../main/kotlin/renderers/html/NavigationPage.kt | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt (limited to 'plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt') diff --git a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt new file mode 100644 index 00000000..4a2fb40d --- /dev/null +++ b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt @@ -0,0 +1,50 @@ +package org.jetbrains.dokka.renderers.html + +import kotlinx.html.* +import kotlinx.html.stream.createHTML +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.pages.PageNode +import org.jetbrains.dokka.pages.PlatformData +import org.jetbrains.dokka.pages.RendererSpecificPage +import org.jetbrains.dokka.pages.RenderingStrategy + +class NavigationPage(val root: NavigationNode) : RendererSpecificPage { + override val name = "navigation" + + override val children = emptyList() + + override fun modified(name: String, children: List) = this + + override val strategy = RenderingStrategy { + createHTML().visit(root, "nav-submenu", this) + } + + private fun TagConsumer.visit(node: NavigationNode, navId: String, renderer: HtmlRenderer): R = + with(renderer) { + div("sideMenuPart") { + id = navId + div("overview") { + buildLink(node.dri, node.platforms) { +node.name } + if (node.children.isNotEmpty()) { + span("navButton") { + onClick = """document.getElementById("$navId").classList.toggle("hidden");""" + span("navButtonContent") + } + } + } + node.children.withIndex().forEach { (n, p) -> visit(p, "$navId-$n", renderer) } + } + } +} + +class NavigationNode( + val name: String, + val dri: DRI, + val platforms: List, + val children: List +) + +fun NavigationPage.transform(block: (NavigationNode) -> NavigationNode) = NavigationPage(root.transform(block)) + +fun NavigationNode.transform(block: (NavigationNode) -> NavigationNode) = + run(block).let { NavigationNode(it.name, it.dri, it.platforms, it.children.map(block)) } -- cgit From a89d9a8c87cbe81bdba25b660d1b1fda1d0ce8ec Mon Sep 17 00:00:00 2001 From: Paweł Marks Date: Mon, 17 Feb 2020 12:35:15 +0100 Subject: Moves location providers and output writers to base plugin --- core/src/main/kotlin/CoreExtensions.kt | 5 - .../main/kotlin/plugability/DefaultExtensions.kt | 7 -- core/src/main/kotlin/renderers/FileWriter.kt | 78 ------------- core/src/main/kotlin/renderers/OutputWriter.kt | 7 -- .../kotlin/resolvers/DefaultLocationProvider.kt | 121 --------------------- .../kotlin/resolvers/ExternalLocationProvider.kt | 99 ----------------- core/src/main/kotlin/resolvers/LocationProvider.kt | 13 --- .../kotlin/resolvers/LocationProviderFactory.kt | 14 --- plugins/base/src/main/kotlin/DokkaBase.kt | 16 ++- .../src/main/kotlin/renderers/DefaultRenderer.kt | 11 +- .../base/src/main/kotlin/renderers/FileWriter.kt | 79 ++++++++++++++ .../base/src/main/kotlin/renderers/OutputWriter.kt | 7 ++ .../src/main/kotlin/renderers/html/HtmlRenderer.kt | 3 +- .../main/kotlin/renderers/html/NavigationPage.kt | 2 +- .../kotlin/renderers/html/htmlPreprocessors.kt | 2 +- .../kotlin/resolvers/DefaultLocationProvider.kt | 116 ++++++++++++++++++++ .../resolvers/DefaultLocationProviderFactory.kt | 9 ++ .../kotlin/resolvers/ExternalLocationProvider.kt | 99 +++++++++++++++++ .../src/main/kotlin/resolvers/LocationProvider.kt | 19 ++++ 19 files changed, 353 insertions(+), 354 deletions(-) delete mode 100644 core/src/main/kotlin/renderers/FileWriter.kt delete mode 100644 core/src/main/kotlin/renderers/OutputWriter.kt delete mode 100644 core/src/main/kotlin/resolvers/DefaultLocationProvider.kt delete mode 100644 core/src/main/kotlin/resolvers/ExternalLocationProvider.kt delete mode 100644 core/src/main/kotlin/resolvers/LocationProvider.kt delete mode 100644 core/src/main/kotlin/resolvers/LocationProviderFactory.kt create mode 100644 plugins/base/src/main/kotlin/renderers/FileWriter.kt create mode 100644 plugins/base/src/main/kotlin/renderers/OutputWriter.kt create mode 100644 plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt create mode 100644 plugins/base/src/main/kotlin/resolvers/DefaultLocationProviderFactory.kt create mode 100644 plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt create mode 100644 plugins/base/src/main/kotlin/resolvers/LocationProvider.kt (limited to 'plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt') 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() val renderer by coreExtension() - val locationProviderFactory by coreExtension() - val outputWriter by coreExtension() - private fun coreExtension() = object { operator fun provideDelegate(thisRef: CoreExtensions, property: KProperty<*>): Lazy> = lazy { ExtensionPoint(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 = LazyEvaluated.fromRecipe { DefaultLocationProviderFactory(it) } - private val outputWriter: LazyEvaluated = LazyEvaluated.fromRecipe { FileWriter(it) } @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST") internal fun > get(point: E, fullContext: DokkaContext): List = when (point) { - CoreExtensions.locationProviderFactory -> providerFactory.get(fullContext) - CoreExtensions.outputWriter -> outputWriter.get(fullContext) else -> null }.let { listOfNotNull( it ) as List } } \ 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 = 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()) - } 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 = pageGraphRoot.asSequence().filterIsInstance() - .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> = IdentityHashMap>().apply { - fun registerPath(page: PageNode, prefix: List) { - 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, 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 = - 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 = mutableMapOf() - - fun getLocation(dri: DRI, externalDocumentationLinks: List): String { - val toResolve: MutableList = 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, val locations: Map) - -} 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, 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 -} 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 diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt index 9b6e9b1a..fd842dc0 100644 --- a/plugins/base/src/main/kotlin/DokkaBase.kt +++ b/plugins/base/src/main/kotlin/DokkaBase.kt @@ -1,6 +1,11 @@ package org.jetbrains.dokka.base import org.jetbrains.dokka.CoreExtensions +import org.jetbrains.dokka.base.renderers.FileWriter +import org.jetbrains.dokka.base.renderers.OutputWriter +import org.jetbrains.dokka.base.renderers.html.HtmlRenderer +import org.jetbrains.dokka.base.resolvers.DefaultLocationProviderFactory +import org.jetbrains.dokka.base.resolvers.LocationProviderFactory import org.jetbrains.dokka.base.transformers.descriptors.DefaultDescriptorToDocumentationTranslator import org.jetbrains.dokka.base.transformers.documentables.DefaultDocumentableMerger import org.jetbrains.dokka.base.transformers.documentables.DefaultDocumentablesToPageTranslator @@ -12,11 +17,12 @@ import org.jetbrains.dokka.base.transformers.pages.merger.PageNodeMerger import org.jetbrains.dokka.base.transformers.pages.merger.SameMethodNamePageMergerStrategy import org.jetbrains.dokka.base.transformers.psi.DefaultPsiToDocumentationTranslator import org.jetbrains.dokka.plugability.DokkaPlugin -import org.jetbrains.dokka.renderers.html.HtmlRenderer class DokkaBase : DokkaPlugin() { val pageMergerStrategy by extensionPoint() val commentsToContentConverter by extensionPoint() + val locationproviderFactory by extensionPoint() + val outputWriter by extensionPoint() val descriptorToDocumentationTranslator by extending(isFallback = true) { CoreExtensions.descriptorToDocumentationTranslator providing ::DefaultDescriptorToDocumentationTranslator @@ -57,4 +63,12 @@ class DokkaBase : DokkaPlugin() { val htmlRenderer by extending { CoreExtensions.renderer providing ::HtmlRenderer applyIf { format == "html" } } + + val locationProvider by extending(isFallback = true) { + locationproviderFactory providing ::DefaultLocationProviderFactory + } + + val fileWriter by extending(isFallback = true) { + outputWriter providing ::FileWriter + } } \ No newline at end of file diff --git a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt index c6183cf3..951545d2 100644 --- a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt @@ -1,18 +1,19 @@ package org.jetbrains.dokka.base.renderers -import org.jetbrains.dokka.CoreExtensions +import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.base.resolvers.LocationProvider import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.renderers.OutputWriter +import org.jetbrains.dokka.plugability.plugin +import org.jetbrains.dokka.plugability.querySingle import org.jetbrains.dokka.renderers.Renderer -import org.jetbrains.dokka.resolvers.LocationProvider import org.jetbrains.dokka.transformers.pages.PageNodeTransformer abstract class DefaultRenderer( protected val context: DokkaContext ) : Renderer { - protected val outputWriter = context.single(CoreExtensions.outputWriter) + protected val outputWriter = context.plugin().querySingle { outputWriter } protected lateinit var locationProvider: LocationProvider private set @@ -116,7 +117,7 @@ abstract class DefaultRenderer( val newRoot = preprocessors.fold(root) { acc, t -> t(acc) } locationProvider = - context.single(CoreExtensions.locationProviderFactory).getLocationProvider(newRoot) + context.plugin().querySingle { locationproviderFactory }.getLocationProvider(newRoot) root.children().forEach { renderPackageList(it) } diff --git a/plugins/base/src/main/kotlin/renderers/FileWriter.kt b/plugins/base/src/main/kotlin/renderers/FileWriter.kt new file mode 100644 index 00000000..5d3067fc --- /dev/null +++ b/plugins/base/src/main/kotlin/renderers/FileWriter.kt @@ -0,0 +1,79 @@ +package org.jetbrains.dokka.base.renderers + +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.renderers.OutputWriter +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 = 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()) + } catch (e: FileSystemAlreadyExistsException) { + FileSystems.getFileSystem(uri) + } +} \ No newline at end of file diff --git a/plugins/base/src/main/kotlin/renderers/OutputWriter.kt b/plugins/base/src/main/kotlin/renderers/OutputWriter.kt new file mode 100644 index 00000000..a6fda51a --- /dev/null +++ b/plugins/base/src/main/kotlin/renderers/OutputWriter.kt @@ -0,0 +1,7 @@ +package org.jetbrains.dokka.base.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/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt index c9270681..8bf00043 100644 --- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt @@ -1,4 +1,4 @@ -package org.jetbrains.dokka.renderers.html +package org.jetbrains.dokka.base.renderers.html import kotlinx.html.* import kotlinx.html.stream.createHTML @@ -7,7 +7,6 @@ import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.Function import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.renderers.OutputWriter import java.io.File open class HtmlRenderer( diff --git a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt index 4a2fb40d..ad574769 100644 --- a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt +++ b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt @@ -1,4 +1,4 @@ -package org.jetbrains.dokka.renderers.html +package org.jetbrains.dokka.base.renderers.html import kotlinx.html.* import kotlinx.html.stream.createHTML diff --git a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt index 09164d97..ecd2e89a 100644 --- a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt +++ b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt @@ -1,4 +1,4 @@ -package org.jetbrains.dokka.renderers.html +package org.jetbrains.dokka.base.renderers.html import kotlinx.html.h1 import kotlinx.html.id diff --git a/plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt new file mode 100644 index 00000000..2238b0c3 --- /dev/null +++ b/plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt @@ -0,0 +1,116 @@ +package org.jetbrains.dokka.base.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 = pageGraphRoot.asSequence().filterIsInstance() + .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> = IdentityHashMap>().apply { + fun registerPath(page: PageNode, prefix: List) { + 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, 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 = + 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" + val callableChecked = callable ?: return classLink.htmlEscape() + + val callableLink = "$classLink#${callableChecked.name}" + when { + jdkVersion < 8 -> "(${callableChecked.params.joinToString(", ")})" + jdkVersion < 10 -> "-${callableChecked.params.joinToString("-")}-" + else -> "(${callableChecked.params.joinToString(",")})" + } + + return callableLink.htmlEscape() +} + +fun DRI.toDokkaLocation(extension: String): String { // TODO: classes without packages? + val classNamesChecked = classNames ?: return "$packageName/index$extension" + + val classLink = if (packageName == null) { + "" + } else { + "$packageName/" + } + classNamesChecked.split('.').joinToString("/", transform = ::identifierToFilename) + + val callableChecked = callable ?: return "$classLink/index$extension" + + return "$classLink/${identifierToFilename(callableChecked.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/plugins/base/src/main/kotlin/resolvers/DefaultLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/DefaultLocationProviderFactory.kt new file mode 100644 index 00000000..c649e22b --- /dev/null +++ b/plugins/base/src/main/kotlin/resolvers/DefaultLocationProviderFactory.kt @@ -0,0 +1,9 @@ +package org.jetbrains.dokka.base.resolvers + +import org.jetbrains.dokka.pages.RootPageNode +import org.jetbrains.dokka.plugability.DokkaContext + +class DefaultLocationProviderFactory(private val context: DokkaContext) : LocationProviderFactory { + + override fun getLocationProvider(pageNode: RootPageNode) = DefaultLocationProvider(pageNode, context) +} \ No newline at end of file diff --git a/plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt new file mode 100644 index 00000000..7c0e9952 --- /dev/null +++ b/plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt @@ -0,0 +1,99 @@ +package org.jetbrains.dokka.base.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 = mutableMapOf() + + fun getLocation(dri: DRI, externalDocumentationLinks: List): String { + val toResolve: MutableList = 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, val locations: Map) + +} diff --git a/plugins/base/src/main/kotlin/resolvers/LocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/LocationProvider.kt new file mode 100644 index 00000000..13f4563c --- /dev/null +++ b/plugins/base/src/main/kotlin/resolvers/LocationProvider.kt @@ -0,0 +1,19 @@ +package org.jetbrains.dokka.base.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 +import org.jetbrains.dokka.pages.RootPageNode + +interface LocationProvider { + fun resolve(dri: DRI, platforms: List, 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 +} + +interface LocationProviderFactory { + fun getLocationProvider(pageNode: RootPageNode): LocationProvider +} + -- cgit From 39759708d2329f81008e66ff57c11898cd739246 Mon Sep 17 00:00:00 2001 From: Filip Zybała Date: Tue, 10 Mar 2020 17:07:53 +0100 Subject: Add DRIs to navigation elements, tag each ContentPage with DRI, add JS for collapsing navigation --- .../resources/dokka/scripts/navigationLoader.js | 41 ++++++++++++++++++---- .../src/main/kotlin/renderers/html/HtmlRenderer.kt | 5 ++- .../main/kotlin/renderers/html/NavigationPage.kt | 1 + 3 files changed, 40 insertions(+), 7 deletions(-) (limited to 'plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt') diff --git a/core/src/main/resources/dokka/scripts/navigationLoader.js b/core/src/main/resources/dokka/scripts/navigationLoader.js index 99a885a9..5fe52ade 100644 --- a/core/src/main/resources/dokka/scripts/navigationLoader.js +++ b/core/src/main/resources/dokka/scripts/navigationLoader.js @@ -1,12 +1,41 @@ onload = () => { fetch(pathToRoot + "navigation.html") - .then(response => response.text()) - .then(data => { - document.getElementById("sideMenu").innerHTML = data; - }).then(() => { + .then(response => response.text()) + .then(data => { + document.getElementById("sideMenu").innerHTML = data; + }).then(() => { document.querySelectorAll(".overview > a").forEach(link => { - link.setAttribute("href", pathToRoot + link.getAttribute("href")) + link.setAttribute("href", pathToRoot + link.getAttribute("href")); console.log(link.attributes["href"]) }) + }).then(() => { + document.querySelectorAll(".sideMenuPart").forEach(nav => { + if (!nav.classList.contains("hidden")) nav.classList.add("hidden") + }) + }).then(() => { + revealNavigationForCurrentPage() }) -} \ No newline at end of file +}; + +revealNavigationForCurrentPage = () => { + let pageId = document.getElementById("content").attributes["pageIds"].value.toString(); + let parts = document.querySelectorAll(".sideMenuPart"); + let found = 0; + do { + parts.forEach(part => { + if (part.attributes['pageId'].value.indexOf(pageId) !== -1 && found === 0) { + found = 1; + if (part.classList.contains("hidden")) part.classList.remove("hidden"); + revealParents(part) + } + }); + pageId = pageId.substring(0, pageId.lastIndexOf("/")) + } while (pageId.indexOf("/") !== -1 && found === 0) +}; + +revealParents = (part) => { + if (part.classList.contains("sideMenuPart")) { + if (part.classList.contains("hidden")) part.classList.remove("hidden"); + revealParents(part.parentNode) + } +}; \ No newline at end of file diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt index 74bc6fea..aaa9c0a4 100644 --- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt @@ -202,7 +202,10 @@ open class HtmlRenderer( private fun PageNode.root(path: String) = locationProvider.resolveRoot(this) + path override fun buildPage(page: ContentPage, content: (FlowContent, ContentPage) -> Unit): String = - buildHtml(page, page.embeddedResources) { content(this, page) } + buildHtml(page, page.embeddedResources) { + attributes["pageIds"] = page.dri.toList()[0].toString() + content(this, page) + } open fun buildHtml(page: PageNode, resources: List, content: FlowContent.() -> Unit) = createHTML().html { diff --git a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt index ad574769..4b90cc8a 100644 --- a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt +++ b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt @@ -23,6 +23,7 @@ class NavigationPage(val root: NavigationNode) : RendererSpecificPage { with(renderer) { div("sideMenuPart") { id = navId + attributes["pageId"] = node.dri.toString() div("overview") { buildLink(node.dri, node.platforms) { +node.name } if (node.children.isNotEmpty()) { -- cgit From 3f2a790190da4f40ea6d8a976aa1929b2a1b002b Mon Sep 17 00:00:00 2001 From: Błażej Kardyś Date: Tue, 5 May 2020 17:45:12 +0200 Subject: Changing approach from platform-driven to source-set-driven --- .idea/compiler.xml | 36 +++ core/src/main/kotlin/DokkaGenerator.kt | 36 +-- core/src/main/kotlin/configuration.kt | 6 +- core/src/main/kotlin/defaultConfiguration.kt | 2 + core/src/main/kotlin/model/Documentable.kt | 168 ++++++-------- core/src/main/kotlin/model/SourceSetData.kt | 23 ++ core/src/main/kotlin/model/aditionalExtras.kt | 4 +- core/src/main/kotlin/model/documentableUtils.kt | 15 +- core/src/main/kotlin/pages/ContentNodes.kt | 29 +-- core/src/main/kotlin/pages/PageNodes.kt | 5 +- core/src/main/kotlin/plugability/DokkaContext.kt | 14 +- .../PreMergeDocumentableTransformer.kt | 2 +- .../sources/SourceToDocumentableTranslator.kt | 4 +- plugins/base/src/main/kotlin/DokkaBase.kt | 6 +- .../src/main/kotlin/renderers/DefaultRenderer.kt | 21 +- .../src/main/kotlin/renderers/html/HtmlRenderer.kt | 58 ++--- .../main/kotlin/renderers/html/NavigationPage.kt | 4 +- .../resolvers/local/DefaultLocationProvider.kt | 9 +- .../kotlin/resolvers/local/LocationProvider.kt | 4 +- .../kotlin/signatures/KotlinSignatureProvider.kt | 35 ++- .../documentables/ActualTypealiasAdder.kt | 8 +- .../documentables/DefaultDocumentableMerger.kt | 233 ++++++++----------- .../documentables/DocumentableVisibilityFilter.kt | 55 +++-- .../InheritorsExtractorTransformer.kt | 23 +- .../ModuleAndPackageDocumentationTransformer.kt | 42 ++-- .../pages/comments/CommentsToContentConverter.kt | 3 +- .../pages/comments/DocTagToContentConverter.kt | 33 +-- .../merger/SameMethodNamePageMergerStrategy.kt | 2 +- .../pages/samples/SamplesTransformer.kt | 25 +- .../pages/sourcelinks/SourceLinksTransformer.kt | 23 +- .../DefaultDescriptorToDocumentableTranslator.kt | 252 ++++++++++----------- .../documentables/DefaultPageCreator.kt | 111 +++++---- .../documentables/PageContentBuilder.kt | 98 ++++---- .../psi/DefaultPsiToDocumentableTranslator.kt | 57 +++-- .../src/test/kotlin/expect/AbstractExpectTest.kt | 2 +- .../kotlin/linkableContent/LinkableContentTest.kt | 6 + plugins/base/src/test/kotlin/model/ClassesTest.kt | 20 +- .../base/src/test/kotlin/model/InheritorsTest.kt | 10 +- plugins/base/src/test/kotlin/model/JavaTest.kt | 4 +- plugins/base/src/test/kotlin/model/PackagesTest.kt | 4 +- .../test/kotlin/renderers/RenderingOnlyTestBase.kt | 7 +- .../renderers/html/PlatformDependentHintTest.kt | 120 ---------- .../renderers/html/SourceSetDependentHintTest.kt | 121 ++++++++++ .../annotatedFunction/out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../annotatedFunction/out/html/root/index.html | 4 +- .../annotatedFunction/out/html/root/package-list | 4 +- .../annotatedFunction/out/html/scripts/pages.js | 0 .../out/html/navigation.html | 10 +- .../out/html/root/[jvm root]/-fancy/-init-.html | 32 --- .../out/html/root/[jvm root]/-fancy/equals.html | 32 --- .../out/html/root/[jvm root]/-fancy/hash-code.html | 32 --- .../out/html/root/[jvm root]/-fancy/index.html | 102 --------- .../out/html/root/[jvm root]/-fancy/to-string.html | 32 --- .../out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 69 ------ .../out/html/root/[main root]/-fancy/-init-.html | 32 +++ .../out/html/root/[main root]/-fancy/equals.html | 32 +++ .../html/root/[main root]/-fancy/hash-code.html | 32 +++ .../out/html/root/[main root]/-fancy/index.html | 102 +++++++++ .../html/root/[main root]/-fancy/to-string.html | 32 +++ .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 69 ++++++ .../out/html/root/index.html | 4 +- .../out/html/root/package-list | 10 +- .../expect/function/out/html/navigation.html | 6 +- .../function/out/html/root/[jvm root]/fn.html | 34 --- .../function/out/html/root/[jvm root]/index.html | 50 ---- .../function/out/html/root/[main root]/fn.html | 34 +++ .../function/out/html/root/[main root]/index.html | 50 ++++ .../expect/function/out/html/root/index.html | 4 +- .../expect/function/out/html/root/package-list | 4 +- .../out/html/navigation.html | 10 +- .../out/html/root/[jvm root]/-fancy/-init-.html | 32 --- .../out/html/root/[jvm root]/-fancy/equals.html | 32 --- .../out/html/root/[jvm root]/-fancy/hash-code.html | 32 --- .../out/html/root/[jvm root]/-fancy/index.html | 83 ------- .../out/html/root/[jvm root]/-fancy/to-string.html | 32 --- .../out/html/root/[jvm root]/function.html | 32 --- .../out/html/root/[jvm root]/index.html | 69 ------ .../out/html/root/[main root]/-fancy/-init-.html | 32 +++ .../out/html/root/[main root]/-fancy/equals.html | 32 +++ .../html/root/[main root]/-fancy/hash-code.html | 32 +++ .../out/html/root/[main root]/-fancy/index.html | 83 +++++++ .../html/root/[main root]/-fancy/to-string.html | 32 +++ .../out/html/root/[main root]/function.html | 32 +++ .../out/html/root/[main root]/index.html | 69 ++++++ .../out/html/root/index.html | 4 +- .../out/html/root/package-list | 10 +- .../out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../out/html/root/index.html | 4 +- .../out/html/root/package-list | 4 +- .../out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/function.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/function.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../out/html/root/index.html | 4 +- .../out/html/root/package-list | 4 +- .../out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../out/html/root/index.html | 4 +- .../out/html/root/package-list | 4 +- .../functionWithParams/out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/function.html | 34 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/function.html | 34 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../functionWithParams/out/html/root/index.html | 4 +- .../functionWithParams/out/html/root/package-list | 4 +- .../functionWithReceiver/out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/fn.html | 40 ---- .../out/html/root/[jvm root]/index.html | 66 ------ .../out/html/root/[main root]/fn.html | 40 ++++ .../out/html/root/[main root]/index.html | 66 ++++++ .../functionWithReceiver/out/html/root/index.html | 4 +- .../out/html/root/package-list | 6 +- .../genericFunction/out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/generic.html | 34 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/generic.html | 34 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../genericFunction/out/html/root/index.html | 4 +- .../genericFunction/out/html/root/package-list | 4 +- .../out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/generic.html | 34 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/generic.html | 34 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../out/html/root/index.html | 4 +- .../out/html/root/package-list | 4 +- .../expect/inlineFunction/out/html/navigation.html | 6 +- .../inlineFunction/out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../expect/inlineFunction/out/html/root/index.html | 4 +- .../inlineFunction/out/html/root/package-list | 4 +- .../inlineSuspendFunction/out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../inlineSuspendFunction/out/html/root/index.html | 4 +- .../out/html/root/package-list | 4 +- .../expect/signatureTest/out/html/root/index.html | 2 +- .../out/html/root/signatureTest/index.html | 8 +- .../out/html/root/signatureTest/test.html | 2 +- .../out/html/root/signatureTest/test2.html | 2 +- .../expect/sinceKotlin/out/html/navigation.html | 6 +- .../html/root/[jvm root]/available-since1.1.html | 34 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../html/root/[main root]/available-since1.1.html | 34 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../expect/sinceKotlin/out/html/root/index.html | 4 +- .../expect/sinceKotlin/out/html/root/package-list | 4 +- .../suspendFunction/out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../suspendFunction/out/html/root/index.html | 4 +- .../suspendFunction/out/html/root/package-list | 4 +- .../suspendInlineFunction/out/html/navigation.html | 6 +- .../out/html/root/[jvm root]/f.html | 32 --- .../out/html/root/[jvm root]/index.html | 50 ---- .../out/html/root/[main root]/f.html | 32 +++ .../out/html/root/[main root]/index.html | 50 ++++ .../suspendInlineFunction/out/html/root/index.html | 4 +- .../out/html/root/package-list | 4 +- plugins/gfm/src/main/kotlin/GfmPlugin.kt | 11 +- .../kotlin/converters/KotlinToJavaConverter.kt | 86 +++---- .../kotlin/signatures/JavaSignatureProvider.kt | 4 +- runners/cli/src/main/kotlin/cli/main.kt | 11 + .../dokka/gradle/ConfigurationExtractor.kt | 144 ++++++------ .../kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt | 47 ++-- .../dokka/gradle/configurationImplementations.kt | 2 + .../main/kotlin/org/jetbrains/dokka/gradle/main.kt | 4 +- .../kotlin/org/jetbrains/dokka/gradle/utils.kt | 14 +- runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 7 +- .../src/main/kotlin/testApi/context/MockContext.kt | 12 +- .../testApi/testRunner/DokkaTestGenerator.kt | 11 +- .../main/kotlin/testApi/testRunner/TestRunner.kt | 10 +- 193 files changed, 3010 insertions(+), 3003 deletions(-) create mode 100644 core/src/main/kotlin/model/SourceSetData.kt delete mode 100644 plugins/base/src/test/kotlin/renderers/html/PlatformDependentHintTest.kt create mode 100644 plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunction/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunction/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunction/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunction/out/html/root/[main root]/index.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunction/out/html/scripts/pages.js delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[jvm root]/-fancy/-init-.html delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[jvm root]/-fancy/equals.html delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[jvm root]/-fancy/hash-code.html delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[jvm root]/-fancy/index.html delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[jvm root]/-fancy/to-string.html delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[main root]/-fancy/-init-.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[main root]/-fancy/equals.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[main root]/-fancy/hash-code.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[main root]/-fancy/index.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[main root]/-fancy/to-string.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/annotatedFunctionWithAnnotationParameters/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/function/out/html/root/[jvm root]/fn.html delete mode 100644 plugins/base/src/test/resources/expect/function/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/function/out/html/root/[main root]/fn.html create mode 100644 plugins/base/src/test/resources/expect/function/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[jvm root]/-fancy/-init-.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[jvm root]/-fancy/equals.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[jvm root]/-fancy/hash-code.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[jvm root]/-fancy/index.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[jvm root]/-fancy/to-string.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[jvm root]/function.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[main root]/-fancy/-init-.html create mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[main root]/-fancy/equals.html create mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[main root]/-fancy/hash-code.html create mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[main root]/-fancy/index.html create mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[main root]/-fancy/to-string.html create mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[main root]/function.html create mode 100644 plugins/base/src/test/resources/expect/functionWithAnnotatedParam/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithDefaultParameter/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithDefaultParameter/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/functionWithDefaultParameter/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/functionWithDefaultParameter/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithNoinlineParam/out/html/root/[jvm root]/function.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithNoinlineParam/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/functionWithNoinlineParam/out/html/root/[main root]/function.html create mode 100644 plugins/base/src/test/resources/expect/functionWithNoinlineParam/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithNotDocumentedAnnotation/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithNotDocumentedAnnotation/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/functionWithNotDocumentedAnnotation/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/functionWithNotDocumentedAnnotation/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithParams/out/html/root/[jvm root]/function.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithParams/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/functionWithParams/out/html/root/[main root]/function.html create mode 100644 plugins/base/src/test/resources/expect/functionWithParams/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithReceiver/out/html/root/[jvm root]/fn.html delete mode 100644 plugins/base/src/test/resources/expect/functionWithReceiver/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/functionWithReceiver/out/html/root/[main root]/fn.html create mode 100644 plugins/base/src/test/resources/expect/functionWithReceiver/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/genericFunction/out/html/root/[jvm root]/generic.html delete mode 100644 plugins/base/src/test/resources/expect/genericFunction/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/genericFunction/out/html/root/[main root]/generic.html create mode 100644 plugins/base/src/test/resources/expect/genericFunction/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/genericFunctionWithConstraints/out/html/root/[jvm root]/generic.html delete mode 100644 plugins/base/src/test/resources/expect/genericFunctionWithConstraints/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/genericFunctionWithConstraints/out/html/root/[main root]/generic.html create mode 100644 plugins/base/src/test/resources/expect/genericFunctionWithConstraints/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/inlineFunction/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/inlineFunction/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/inlineFunction/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/inlineFunction/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/inlineSuspendFunction/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/inlineSuspendFunction/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/inlineSuspendFunction/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/inlineSuspendFunction/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/sinceKotlin/out/html/root/[jvm root]/available-since1.1.html delete mode 100644 plugins/base/src/test/resources/expect/sinceKotlin/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/sinceKotlin/out/html/root/[main root]/available-since1.1.html create mode 100644 plugins/base/src/test/resources/expect/sinceKotlin/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/suspendFunction/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/suspendFunction/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/suspendFunction/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/suspendFunction/out/html/root/[main root]/index.html delete mode 100644 plugins/base/src/test/resources/expect/suspendInlineFunction/out/html/root/[jvm root]/f.html delete mode 100644 plugins/base/src/test/resources/expect/suspendInlineFunction/out/html/root/[jvm root]/index.html create mode 100644 plugins/base/src/test/resources/expect/suspendInlineFunction/out/html/root/[main root]/f.html create mode 100644 plugins/base/src/test/resources/expect/suspendInlineFunction/out/html/root/[main root]/index.html (limited to 'plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt') diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 7ee14d19..a7e03ba2 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -16,8 +16,14 @@ + + + + + + @@ -78,14 +84,24 @@ + + + + + + + + + + @@ -101,6 +117,8 @@ + + @@ -110,6 +128,10 @@ + + + + @@ -126,6 +148,8 @@ + + @@ -150,6 +174,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt index 053b4cb6..6e62c033 100644 --- a/core/src/main/kotlin/DokkaGenerator.kt +++ b/core/src/main/kotlin/DokkaGenerator.kt @@ -1,23 +1,20 @@ package org.jetbrains.dokka -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.psi.PsiJavaFile -import com.intellij.psi.PsiManager import org.jetbrains.dokka.analysis.AnalysisEnvironment import org.jetbrains.dokka.analysis.DokkaResolutionFacade import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.pages.PlatformData +import org.jetbrains.dokka.model.SourceSetCache +import org.jetbrains.dokka.model.SourceSetData +import org.jetbrains.dokka.model.sourceSet import org.jetbrains.dokka.pages.RootPageNode import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.DokkaPlugin import org.jetbrains.dokka.utilities.DokkaLogger -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.utils.PathUtil import java.io.File @@ -31,13 +28,14 @@ class DokkaGenerator( ) { fun generate() = timed { report("Setting up analysis environments") - val platforms: Map = setUpAnalysis(configuration) + val sourceSetsCache = SourceSetCache() + val sourceSets: Map = setUpAnalysis(configuration, sourceSetsCache) report("Initializing plugins") - val context = initializePlugins(configuration, logger, platforms) + val context = initializePlugins(configuration, logger, sourceSets, sourceSetsCache) report("Creating documentation models") - val modulesFromPlatforms = createDocumentationModels(platforms, context) + val modulesFromPlatforms = createDocumentationModels(sourceSets, context) report("Transforming documentation model before merging") val transformedDocumentationBeforeMerge = transformDocumentationModelBeforeMerge(modulesFromPlatforms, context) @@ -62,27 +60,31 @@ class DokkaGenerator( logger.report() }.dump("\n\n === TIME MEASUREMENT ===\n") - fun setUpAnalysis(configuration: DokkaConfiguration): Map = + fun setUpAnalysis( + configuration: DokkaConfiguration, + sourceSetsCache: SourceSetCache + ): Map = configuration.passesConfigurations.map { - it.platformData to createEnvironmentAndFacade(it) + sourceSetsCache.getSourceSet(it) to createEnvironmentAndFacade(it) }.toMap() fun initializePlugins( configuration: DokkaConfiguration, logger: DokkaLogger, - platforms: Map, + sourceSets: Map, + sourceSetsCache: SourceSetCache, pluginOverrides: List = emptyList() - ) = DokkaContext.create(configuration, logger, platforms, pluginOverrides) + ) = DokkaContext.create(configuration, logger, sourceSets, sourceSetsCache, pluginOverrides) fun createDocumentationModels( - platforms: Map, + platforms: Map, context: DokkaContext ) = platforms.flatMap { (pdata, _) -> translateSources(pdata, context) } fun transformDocumentationModelBeforeMerge( modulesFromPlatforms: List, context: DokkaContext - ) = context[CoreExtensions.preMergeDocumentableTransformer].fold(modulesFromPlatforms) { acc, t -> t(acc, context) } + ) = context[CoreExtensions.preMergeDocumentableTransformer].fold(modulesFromPlatforms) { acc, t -> t(acc) } fun mergeDocumentationModels( modulesFromPlatforms: List, @@ -119,7 +121,7 @@ class DokkaGenerator( } pass.classpath.forEach { addClasspath(File(it)) } - addSources(pass.sourceRoots.map { it.path }) + addSources((pass.sourceRoots + pass.dependentSourceRoots).map { it.path }) loadLanguageVersionSettings(pass.languageVersion, pass.apiVersion) @@ -128,7 +130,7 @@ class DokkaGenerator( EnvironmentAndFacade(environment, facade) } - private fun translateSources(platformData: PlatformData, context: DokkaContext) = + private fun translateSources(platformData: SourceSetData, context: DokkaContext) = context[CoreExtensions.sourceToDocumentableTranslator].map { it.invoke(platformData, context) } diff --git a/core/src/main/kotlin/configuration.kt b/core/src/main/kotlin/configuration.kt index 34671c4e..88924924 100644 --- a/core/src/main/kotlin/configuration.kt +++ b/core/src/main/kotlin/configuration.kt @@ -1,6 +1,5 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.pages.PlatformData import java.io.File import java.net.URL @@ -37,8 +36,10 @@ interface DokkaConfiguration { interface PassConfiguration { val moduleName: String + val sourceSetName: String val classpath: List val sourceRoots: List + val dependentSourceRoots: List val samples: List val includes: List val includeNonPublic: Boolean @@ -59,9 +60,6 @@ interface DokkaConfiguration { val analysisPlatform: Platform val targets: List val sinceKotlin: String? - - val platformData: PlatformData - get() = PlatformData(moduleName, analysisPlatform, targets) } interface SourceRoot { diff --git a/core/src/main/kotlin/defaultConfiguration.kt b/core/src/main/kotlin/defaultConfiguration.kt index ae674ea1..08f70b45 100644 --- a/core/src/main/kotlin/defaultConfiguration.kt +++ b/core/src/main/kotlin/defaultConfiguration.kt @@ -16,8 +16,10 @@ data class DokkaConfigurationImpl( data class PassConfigurationImpl ( override val moduleName: String, + override val sourceSetName: String, override val classpath: List, override val sourceRoots: List, + override val dependentSourceRoots: List, override val samples: List, override val includes: List, override val includeNonPublic: Boolean, diff --git a/core/src/main/kotlin/model/Documentable.kt b/core/src/main/kotlin/model/Documentable.kt index 313f4cd4..85487725 100644 --- a/core/src/main/kotlin/model/Documentable.kt +++ b/core/src/main/kotlin/model/Documentable.kt @@ -1,11 +1,12 @@ package org.jetbrains.dokka.model import com.intellij.psi.PsiNamedElement +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.Platform import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.doc.DocumentationNode import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.model.properties.WithExtraProperties -import org.jetbrains.dokka.pages.PlatformData import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.load.kotlin.toSourceElement @@ -13,8 +14,9 @@ abstract class Documentable { abstract val name: String? abstract val dri: DRI abstract val children: List - abstract val documentation: PlatformDependent - abstract val platformData: List + abstract val documentation: SourceSetDependent + abstract val sourceSets: List + abstract val expectPresentInSet: SourceSetData? override fun toString(): String = "${javaClass.simpleName}($dri)" @@ -25,45 +27,10 @@ abstract class Documentable { override fun hashCode() = dri.hashCode() } -data class PlatformDependent( - val map: Map, - val expect: T? = null -) : Map by map { - val prevalentValue: T? - get() = map.values.distinct().singleOrNull() - - val allValues: Sequence = sequence { - expect?.also { yield(it) } - yieldAll(map.values) - } - - val allEntries: Sequence> = sequence { - expect?.also { yield(null to it) } - map.forEach { (k, v) -> yield(k to v) } - } - - fun getOrExpect(platform: PlatformData): T? = map[platform] ?: expect - - companion object { - fun empty(): PlatformDependent = PlatformDependent(emptyMap()) - - fun from(platformData: PlatformData, element: T) = PlatformDependent(mapOf(platformData to element)) - - @Suppress("UNCHECKED_CAST") - fun from(pairs: Iterable>) = - PlatformDependent( - pairs.filter { it.first != null }.toMap() as Map, - pairs.firstOrNull { it.first == null }?.second - ) - - fun from(vararg pairs: Pair) = from(pairs.asIterable()) - - fun expectFrom(element: T) = PlatformDependent(map = emptyMap(), expect = element) - } -} +typealias SourceSetDependent = Map interface WithExpectActual { - val sources: PlatformDependent + val sources: SourceSetDependent } interface WithScope { @@ -73,7 +40,7 @@ interface WithScope { } interface WithVisibility { - val visibility: PlatformDependent + val visibility: SourceSetDependent } interface WithType { @@ -81,7 +48,7 @@ interface WithType { } interface WithAbstraction { - val modifier: PlatformDependent + val modifier: SourceSetDependent } sealed class Modifier(val name: String) @@ -112,7 +79,7 @@ interface WithGenerics { } interface WithSupertypes { - val supertypes: PlatformDependent> + val supertypes: SourceSetDependent> } interface Callable : WithVisibility, WithType, WithAbstraction, WithExpectActual { @@ -124,8 +91,9 @@ sealed class DClasslike : Documentable(), WithScope, WithVisibility, WithExpectA data class DModule( override val name: String, val packages: List, - override val documentation: PlatformDependent, - override val platformData: List, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData? = null, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), WithExtraProperties { override val dri: DRI = DRI.topLevel @@ -141,8 +109,9 @@ data class DPackage( override val properties: List, override val classlikes: List, val typealiases: List, - override val documentation: PlatformDependent, - override val platformData: List, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData? = null, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), WithScope, WithExtraProperties { override val name = dri.packageName.orEmpty() @@ -159,14 +128,15 @@ data class DClass( override val functions: List, override val properties: List, override val classlikes: List, - override val sources: PlatformDependent, - override val visibility: PlatformDependent, + override val sources: SourceSetDependent, + override val visibility: SourceSetDependent, override val companion: DObject?, override val generics: List, - override val supertypes: PlatformDependent>, - override val documentation: PlatformDependent, - override val modifier: PlatformDependent, - override val platformData: List, + override val supertypes: SourceSetDependent>, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val modifier: SourceSetDependent, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : DClasslike(), WithAbstraction, WithCompanion, WithConstructors, WithGenerics, WithSupertypes, WithExtraProperties { @@ -181,16 +151,17 @@ data class DEnum( override val dri: DRI, override val name: String, val entries: List, - override val documentation: PlatformDependent, - override val sources: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val sources: SourceSetDependent, override val functions: List, override val properties: List, override val classlikes: List, - override val visibility: PlatformDependent, + override val visibility: SourceSetDependent, override val companion: DObject?, override val constructors: List, - override val supertypes: PlatformDependent>, - override val platformData: List, + override val supertypes: SourceSetDependent>, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : DClasslike(), WithCompanion, WithConstructors, WithSupertypes, WithExtraProperties { override val children: List @@ -202,11 +173,12 @@ data class DEnum( data class DEnumEntry( override val dri: DRI, override val name: String, - override val documentation: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, override val functions: List, override val properties: List, override val classlikes: List, - override val platformData: List, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), WithScope, WithExtraProperties { override val children: List @@ -220,14 +192,15 @@ data class DFunction( override val name: String, val isConstructor: Boolean, val parameters: List, - override val documentation: PlatformDependent, - override val sources: PlatformDependent, - override val visibility: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val sources: SourceSetDependent, + override val visibility: SourceSetDependent, override val type: Bound, override val generics: List, override val receiver: DParameter?, - override val modifier: PlatformDependent, - override val platformData: List, + override val modifier: SourceSetDependent, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), Callable, WithGenerics, WithExtraProperties { override val children: List @@ -239,16 +212,17 @@ data class DFunction( data class DInterface( override val dri: DRI, override val name: String, - override val documentation: PlatformDependent, - override val sources: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val sources: SourceSetDependent, override val functions: List, override val properties: List, override val classlikes: List, - override val visibility: PlatformDependent, + override val visibility: SourceSetDependent, override val companion: DObject?, override val generics: List, - override val supertypes: PlatformDependent>, - override val platformData: List, + override val supertypes: SourceSetDependent>, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : DClasslike(), WithCompanion, WithGenerics, WithSupertypes, WithExtraProperties { override val children: List @@ -260,14 +234,15 @@ data class DInterface( data class DObject( override val name: String?, override val dri: DRI, - override val documentation: PlatformDependent, - override val sources: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val sources: SourceSetDependent, override val functions: List, override val properties: List, override val classlikes: List, - override val visibility: PlatformDependent, - override val supertypes: PlatformDependent>, - override val platformData: List, + override val visibility: SourceSetDependent, + override val supertypes: SourceSetDependent>, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : DClasslike(), WithSupertypes, WithExtraProperties { override val children: List @@ -279,15 +254,16 @@ data class DObject( data class DAnnotation( override val name: String, override val dri: DRI, - override val documentation: PlatformDependent, - override val sources: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val sources: SourceSetDependent, override val functions: List, override val properties: List, override val classlikes: List, - override val visibility: PlatformDependent, + override val visibility: SourceSetDependent, override val companion: DObject?, override val constructors: List, - override val platformData: List, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : DClasslike(), WithCompanion, WithConstructors, WithExtraProperties { override val children: List @@ -299,15 +275,16 @@ data class DAnnotation( data class DProperty( override val dri: DRI, override val name: String, - override val documentation: PlatformDependent, - override val sources: PlatformDependent, - override val visibility: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val sources: SourceSetDependent, + override val visibility: SourceSetDependent, override val type: Bound, override val receiver: DParameter?, val setter: DFunction?, val getter: DFunction?, - override val modifier: PlatformDependent, - override val platformData: List, + override val modifier: SourceSetDependent, + override val sourceSets: List, override val generics: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), Callable, WithExtraProperties, WithGenerics { @@ -321,9 +298,10 @@ data class DProperty( data class DParameter( override val dri: DRI, override val name: String?, - override val documentation: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, val type: Bound, - override val platformData: List, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), WithExtraProperties { override val children: List @@ -335,9 +313,10 @@ data class DParameter( data class DTypeParameter( override val dri: DRI, override val name: String, - override val documentation: PlatformDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, val bounds: List, - override val platformData: List, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), WithExtraProperties { override val children: List @@ -350,10 +329,11 @@ data class DTypeAlias( override val dri: DRI, override val name: String, override val type: Bound, - val underlyingType: PlatformDependent, - override val visibility: PlatformDependent, - override val documentation: PlatformDependent, - override val platformData: List, + val underlyingType: SourceSetDependent, + override val visibility: SourceSetDependent, + override val documentation: SourceSetDependent, + override val expectPresentInSet: SourceSetData?, + override val sourceSets: List, override val extra: PropertyContainer = PropertyContainer.empty() ) : Documentable(), WithType, WithVisibility, WithExtraProperties { override val children: List @@ -417,7 +397,7 @@ sealed class JavaVisibility(name: String) : Visibility(name) { object Default : JavaVisibility("") } -fun PlatformDependent?.orEmpty(): PlatformDependent = this ?: PlatformDependent.empty() +fun SourceSetDependent?.orEmpty(): SourceSetDependent = this ?: emptyMap() interface DocumentableSource { val path: String @@ -429,4 +409,4 @@ class DescriptorDocumentableSource(val descriptor: DeclarationDescriptor) : Docu class PsiDocumentableSource(val psi: PsiNamedElement) : DocumentableSource { override val path = psi.containingFile.virtualFile.path -} +} \ No newline at end of file diff --git a/core/src/main/kotlin/model/SourceSetData.kt b/core/src/main/kotlin/model/SourceSetData.kt new file mode 100644 index 00000000..8f67f272 --- /dev/null +++ b/core/src/main/kotlin/model/SourceSetData.kt @@ -0,0 +1,23 @@ +package org.jetbrains.dokka.model + +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.plugability.DokkaContext + +data class SourceSetData( + val moduleName: String, + val sourceSetName: String, + val platform: Platform, + val sourceRoots: List = emptyList() +) + +class SourceSetCache { + private val sourceSets = HashMap() + + fun getSourceSet(pass: DokkaConfiguration.PassConfiguration) = + sourceSets.getOrPut("${pass.moduleName}/${pass.sourceSetName}", + { SourceSetData(pass.moduleName, pass.sourceSetName, pass.analysisPlatform, pass.sourceRoots) } + ) +} + +fun DokkaContext.sourceSet(pass: DokkaConfiguration.PassConfiguration) : SourceSetData = sourceSetCache.getSourceSet(pass) \ No newline at end of file diff --git a/core/src/main/kotlin/model/aditionalExtras.kt b/core/src/main/kotlin/model/aditionalExtras.kt index 58209939..27ad8a55 100644 --- a/core/src/main/kotlin/model/aditionalExtras.kt +++ b/core/src/main/kotlin/model/aditionalExtras.kt @@ -41,13 +41,13 @@ object PrimaryConstructorExtra : ExtraProperty, ExtraProperty.Key = this } -data class ActualTypealias(val underlyingType: PlatformDependent) : ExtraProperty { +data class ActualTypealias(val underlyingType: SourceSetDependent) : ExtraProperty { companion object : ExtraProperty.Key { override fun mergeStrategyFor( left: ActualTypealias, right: ActualTypealias ) = - MergeStrategy.Replace(ActualTypealias(PlatformDependent(left.underlyingType + right.underlyingType))) + MergeStrategy.Replace(ActualTypealias(left.underlyingType + right.underlyingType)) } override val key: ExtraProperty.Key = ActualTypealias diff --git a/core/src/main/kotlin/model/documentableUtils.kt b/core/src/main/kotlin/model/documentableUtils.kt index 7f946344..b09260ee 100644 --- a/core/src/main/kotlin/model/documentableUtils.kt +++ b/core/src/main/kotlin/model/documentableUtils.kt @@ -1,21 +1,18 @@ package org.jetbrains.dokka.model -import org.jetbrains.dokka.pages.PlatformData +fun SourceSetDependent.filtered(platformDataList: List) = filter { it.key in platformDataList } +fun SourceSetData?.filtered(platformDataList: List) = takeIf { this in platformDataList } -fun PlatformDependent.filtered(platformDataList: List) = PlatformDependent( - map.filter { it.key in platformDataList }, - expect -) - -fun DTypeParameter.filter(filteredData: List) = - if (filteredData.containsAll(platformData)) this +fun DTypeParameter.filter(filteredData: List) = + if (filteredData.containsAll(sourceSets)) this else { - val intersection = filteredData.intersect(platformData).toList() + val intersection = filteredData.intersect(sourceSets).toList() if (intersection.isEmpty()) null else DTypeParameter( dri, name, documentation.filtered(intersection), + expectPresentInSet?.takeIf { intersection.contains(expectPresentInSet) }, bounds, intersection, extra diff --git a/core/src/main/kotlin/pages/ContentNodes.kt b/core/src/main/kotlin/pages/ContentNodes.kt index 26bcdf77..bb669199 100644 --- a/core/src/main/kotlin/pages/ContentNodes.kt +++ b/core/src/main/kotlin/pages/ContentNodes.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka.pages import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.model.SourceSetData import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.model.properties.WithExtraProperties @@ -10,7 +11,7 @@ data class DCI(val dri: Set, val kind: Kind) { interface ContentNode : WithExtraProperties { val dci: DCI - val platforms: Set + val sourceSets: Set val style: Set