diff options
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 |