diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/base/src/main/kotlin/DokkaBase.kt | 5 | ||||
-rw-r--r-- | plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt | 89 |
2 files changed, 91 insertions, 3 deletions
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 |