diff options
Diffstat (limited to 'plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt')
| -rw-r--r-- | plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt | 64 | 
1 files changed, 44 insertions, 20 deletions
| diff --git a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt index fe8c8f84..3ef8bcce 100644 --- a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt +++ b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt @@ -5,17 +5,17 @@ import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint  import org.jetbrains.dokka.links.DRI  import org.jetbrains.dokka.links.PointingToDeclaration  import org.jetbrains.dokka.model.DisplaySourceSet +import org.jetbrains.dokka.model.toDisplaySourceSet  import org.jetbrains.dokka.model.withDescendants  import org.jetbrains.dokka.pages.*  import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.utilities.urlEncoded  import java.util.*  open class DokkaLocationProvider(      pageGraphRoot: RootPageNode,      dokkaContext: DokkaContext,      extension: String = ".html" -) : DefaultLocationProvider(pageGraphRoot, dokkaContext, extension) { +) : DokkaBaseLocationProvider(pageGraphRoot, dokkaContext, extension) {      protected open val PAGE_WITH_CHILDREN_SUFFIX = "index"      protected open val pathsIndex: Map<PageNode, List<String>> = IdentityHashMap<PageNode, List<String>>().apply { @@ -28,28 +28,33 @@ open class DokkaLocationProvider(          pageGraphRoot.children.forEach { registerPath(it, emptyList()) }      } -    protected val pagesIndex: Map<Pair<DRI, DisplaySourceSet?>, ContentPage> = +    protected val pagesIndex: Map<DRIWithSourceSet, ContentPage> =          pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()              .flatMap { page ->                  page.dri.flatMap { dri -> -                    page.sourceSets().ifEmpty { setOf(null) }.map { sourceSet -> (dri to sourceSet) to page } +                    page.sourceSets().ifEmpty { setOf(null) }.map { sourceSet -> DRIWithSourceSet(dri,sourceSet) to page }                  }              }              .groupingBy { it.first }              .aggregate { key, _, (_, page), first -> -                if (first) page else throw AssertionError("Multiple pages associated with key: ${key.first}/${key.second}") +                if (first) page else throw AssertionError("Multiple pages associated with key: ${key.dri}/${key.sourceSet}")              } -    protected val anchorsIndex: Map<Pair<DRI, DisplaySourceSet?>, ContentPage> = +    protected val anchorsIndex: Map<DRIWithSourceSet, PageWithKind> =          pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()              .flatMap { page ->                  page.content.withDescendants() -                    .filter { it.extra[SymbolAnchorHint] != null } -                    .mapNotNull { it.dci.dri.singleOrNull() } +                    .filter { it.extra[SymbolAnchorHint] != null && it.dci.dri.any() } +                    .flatMap { content -> +                        content.dci.dri.map { dri -> +                            (dri to content.sourceSets) to content.extra[SymbolAnchorHint]?.contentKind!! +                        } +                    }                      .distinct() -                    .flatMap { dri -> -                        page.sourceSets().ifEmpty { setOf(null) }.map { sourceSet -> -                            (dri to sourceSet) to page +                    .flatMap { (pair, kind) -> +                        val (dri, sourceSets) = pair +                        sourceSets.ifEmpty { setOf(null) }.map { sourceSet -> +                            DRIWithSourceSet(dri, sourceSet) to PageWithKind(page, kind)                          }                      }              }.toMap() @@ -59,18 +64,33 @@ open class DokkaLocationProvider(      override fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode?): String? =          sourceSets.ifEmpty { setOf(null) }.mapNotNull { sourceSet -> -            val driWithSourceSet = Pair(dri, sourceSet) +            val driWithSourceSet = DRIWithSourceSet(dri, sourceSet)              getLocalLocation(driWithSourceSet, context) -                ?: getLocalLocation(driWithSourceSet.copy(first = dri.copy(target = PointingToDeclaration)), context) +                ?: getLocalLocation(driWithSourceSet.copy(dri = dri.copy(target = PointingToDeclaration)), context)                  // Not found in PageGraph, that means it's an external link                  ?: getExternalLocation(dri, sourceSets)                  ?: getExternalLocation(dri.copy(target = PointingToDeclaration), sourceSets)          }.distinct().singleOrNull() -    private fun getLocalLocation(dri: Pair<DRI, DisplaySourceSet?>, context: PageNode?): String? = -        pagesIndex[dri]?.let { resolve(it, context) } -            ?: anchorsIndex[dri]?.let { resolve(it, context) + "#${dri.first.toString().urlEncoded()}" } +    private fun getLocalLocation(driWithSourceSet: DRIWithSourceSet, context: PageNode?): String? { +        val (dri, originalSourceSet) = driWithSourceSet +        val allSourceSets = +            listOf(originalSourceSet) + originalSourceSet?.let { oss -> +                dokkaContext.configuration.sourceSets.filter { it.sourceSetID in oss.sourceSetIDs } +                    .flatMap { it.dependentSourceSets } +                    .mapNotNull { ssid -> +                        dokkaContext.configuration.sourceSets.find { it.sourceSetID == ssid }?.toDisplaySourceSet() +                    } +            }.orEmpty() +        return allSourceSets.asSequence().mapNotNull { displaySourceSet -> +            pagesIndex[DRIWithSourceSet(dri, displaySourceSet)]?.let { page -> resolve(page, context) } +                ?: anchorsIndex[driWithSourceSet]?.let { (page, kind) -> +                    val dci = DCI(setOf(dri), kind) +                    resolve(page, context) + "#" + anchorForDCI(dci, setOfNotNull(displaySourceSet)) +                } +        }.firstOrNull() +    }      override fun pathToRoot(from: PageNode): String =          pathTo(pageGraphRoot, from).removeSuffix(PAGE_WITH_CHILDREN_SUFFIX) @@ -104,8 +124,13 @@ open class DokkaLocationProvider(      private val PageNode.pathName: String          get() = if (this is PackagePageNode) name else identifierToFilename(name) +    protected data class DRIWithSourceSet(val dri: DRI, val sourceSet: DisplaySourceSet?) + +    protected data class PageWithKind(val page: ContentPage, val kind: Kind) +      companion object {          internal val reservedFilenames = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out") +          //Taken from: https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names          internal val reservedCharacters = setOf('|', '>', '<', '*', ':', '"', '?', '%') @@ -119,10 +144,9 @@ open class DokkaLocationProvider(  internal fun sanitizeFileName(name: String, reservedFileNames: Set<String>, reservedCharacters: Set<Char>): String {      val lowercase = name.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() }      val withoutReservedFileNames = if (lowercase in reservedFileNames) "--$lowercase--" else lowercase -    return reservedCharacters.fold(withoutReservedFileNames){ -        acc, character -> -            if(character in acc) acc.replace(character.toString(), "[${character.toInt()}]") -            else acc +    return reservedCharacters.fold(withoutReservedFileNames) { acc, character -> +        if (character in acc) acc.replace(character.toString(), "[${character.toInt()}]") +        else acc      }  } | 
