aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/kotlin/pages/ContentNodes.kt13
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt5
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt89
3 files changed, 99 insertions, 8 deletions
diff --git a/core/src/main/kotlin/pages/ContentNodes.kt b/core/src/main/kotlin/pages/ContentNodes.kt
index 61bc3dfc..cbb5b656 100644
--- a/core/src/main/kotlin/pages/ContentNodes.kt
+++ b/core/src/main/kotlin/pages/ContentNodes.kt
@@ -30,7 +30,7 @@ data class ContentBreakLine(
override val dci: DCI = DCI(emptySet(), ContentKind.Empty),
override val style: Set<Style> = emptySet(),
override val extra: PropertyContainer<ContentNode> = PropertyContainer.empty()
-): ContentNode {
+) : ContentNode {
override fun withNewExtras(newExtras: PropertyContainer<ContentNode>): ContentNode = copy(extra = newExtras)
}
@@ -163,17 +163,20 @@ data class PlatformHintedContent(
/** All extras */
interface Extra
+
interface Style
interface Kind
enum class ContentKind : Kind {
+
Comment, Constructors, Functions, Parameters, Properties, Classlikes, Packages, Symbol, Sample, Main, BriefComment,
- Empty, TypeAliases;
+ Empty, Source, TypeAliases;
- companion object{
- private val platformTagged = setOf(Constructors, Functions, Properties, Classlikes, Packages, TypeAliases)
+ companion object {
+ private val platformTagged =
+ setOf(Constructors, Functions, Properties, Classlikes, Packages, Source, TypeAliases)
- fun shouldBePlatformTagged(kind: Kind) : Boolean = kind in platformTagged
+ fun shouldBePlatformTagged(kind: Kind): Boolean = kind in platformTagged
}
}
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
index 934bb3df..1376cd8e 100644
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -22,6 +22,7 @@ import org.jetbrains.dokka.base.transformers.pages.merger.FallbackPageMergerStra
import org.jetbrains.dokka.base.transformers.pages.merger.PageMerger
import org.jetbrains.dokka.base.transformers.pages.merger.PageMergerStrategy
import org.jetbrains.dokka.base.transformers.pages.merger.SameMethodNamePageMergerStrategy
+import org.jetbrains.dokka.base.transformers.pages.sourcelinks.SourceLinksTransformer
import org.jetbrains.dokka.base.translators.descriptors.DefaultDescriptorToDocumentableTranslator
import org.jetbrains.dokka.base.translators.documentables.DefaultDocumentableToPageTranslator
import org.jetbrains.dokka.base.translators.psi.DefaultPsiToDocumentableTranslator
@@ -127,6 +128,10 @@ class DokkaBase : DokkaPlugin() {
htmlPreprocessors with RootCreator
}
+ val sourceLinksTransformer by extending {
+ htmlPreprocessors providing ::SourceLinksTransformer order { after(rootCreator) }
+ }
+
val navigationPageInstaller by extending {
htmlPreprocessors with NavigationPageInstaller order { after(rootCreator) }
}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
index e6ab7b5e..b19f83d3 100644
--- a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
@@ -1,10 +1,93 @@
package org.jetbrains.dokka.base.transformers.pages.sourcelinks
-import org.jetbrains.dokka.pages.RootPageNode
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiDocumentManager
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.DescriptorDocumentableSource
+import org.jetbrains.dokka.model.WithExpectActual
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.pages.PageTransformer
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
+import org.jetbrains.kotlin.resolve.source.getPsi
+import org.jetbrains.kotlin.utils.addToStdlib.cast
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+
+class SourceLinksTransformer(val context: DokkaContext) : PageTransformer {
+
+ private lateinit var sourceLinks: List<SourceLink>
-object SourceLinksTransformer : PageTransformer {
override fun invoke(input: RootPageNode): RootPageNode {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+
+ sourceLinks = context.configuration.passesConfigurations
+ .flatMap { it.sourceLinks.map { sl -> SourceLink(sl, it.platformData) } }
+
+ return input.transformContentPagesTree { node ->
+ node.documentable.safeAs<WithExpectActual>()?.sources?.map?.entries?.fold(node) { acc, entry ->
+ sourceLinks.find { entry.value.path.contains(it.path) && it.platformData == entry.key }?.run {
+ acc.modified(
+ content = acc.content.addSource(
+ entry.key,
+ entry.value.cast<DescriptorDocumentableSource>().toLink(this)
+ )
+ )
+ } ?: acc
+ } ?: node
+ }
+ }
+
+ private fun DescriptorDocumentableSource.toLink(sourceLink: SourceLink): String =
+ sourceLink.url +
+ this.path.split(sourceLink.path)[1] +
+ sourceLink.lineSuffix +
+ "${this.descriptor.cast<DeclarationDescriptorWithSource>().source.getPsi()?.lineNumber() ?: 1}"
+
+ private fun ContentNode.addSource(platformData: PlatformData, address: String?): ContentNode =
+ if (address != null) when (this) {
+ is ContentGroup -> copy(
+ children = children + listOf(platformHintedContentResolvedLink(platformData, dci.dri, address))
+ )
+ else -> ContentGroup(
+ children = listOf(this, platformHintedContentResolvedLink(platformData, dci.dri, address)),
+ extra = this.extra,
+ platforms = this.platforms,
+ dci = this.dci,
+ style = this.style
+ )
+ } else this
+
+ private fun platformHintedContentResolvedLink(platformData: PlatformData, dri: Set<DRI>, address: String) =
+ PlatformHintedContent(
+ inner = ContentResolvedLink(
+ children = listOf(
+ ContentText(
+ text = "(source)",
+ dci = DCI(dri, ContentKind.BriefComment),
+ platforms = setOf(platformData),
+ style = emptySet(),
+ extra = PropertyContainer.empty()
+ )
+ ),
+ address = address,
+ extra = PropertyContainer.empty(),
+ dci = DCI(dri, ContentKind.Source),
+ platforms = setOf(platformData),
+ style = emptySet()
+ ),
+ platforms = setOf(platformData)
+ )
+
+ private fun PsiElement.lineNumber(): Int? {
+ val doc = PsiDocumentManager.getInstance(project).getDocument(containingFile)
+ // IJ uses 0-based line-numbers; external source browsers use 1-based
+ return doc?.getLineNumber(textRange.startOffset)?.plus(1)
}
+}
+
+data class SourceLink(val path: String, val url: String, val lineSuffix: String?, val platformData: PlatformData) {
+ constructor(sourceLinkDefinition: DokkaConfiguration.SourceLinkDefinition, platformData: PlatformData) : this(
+ sourceLinkDefinition.path, sourceLinkDefinition.url, sourceLinkDefinition.lineSuffix, platformData
+ )
} \ No newline at end of file