All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dotty.tools.scaladoc.renderers.Locations.scala Maven / Gradle / Ivy

There is a newer version: 3.6.0-RC1-bin-20240903-21a3d39-NIGHTLY
Show newest version
package dotty.tools.scaladoc
package renderers

import scala.jdk.CollectionConverters._
import java.net.URI
import dotty.tools.scaladoc.site._
import java.nio.file.Paths
import dotty.tools.scaladoc.util.Escape._

val UnresolvedLocationLink = "#"

trait Locations(using ctx: DocContext):
  def effectiveMembers: Map[DRI, Member]

  // We generate this collection only if there may be a conflict with resources.
  // Potentially can be quite big.
  lazy val apiPaths = effectiveMembers.keySet.filterNot(_.isStaticFile).map(absolutePath(_))

  var cache = new JHashMap[DRI, Seq[String]]()

  private[renderers] def pathsConflictResoultionMsg =
    "Using `-Yapi-subdirectory` flag will move all API documentation into `api` subdirectory and will fix this conflict."

  // TODO verify if location exisits
  def rawLocation(dri: DRI): Seq[String] =
    cache.get(dri) match
      case null =>
        val path = dri match
          case `apiPageDRI` =>
            if ctx.args.apiSubdirectory && ctx.staticSiteContext.nonEmpty
              then List("api", "index")
              else List("index")
          case dri if dri.isStaticFile =>
            Paths.get(dri.location).iterator.asScala.map(_.toString).toList
          case dri =>
            val loc = dri.location
            val fqn = loc.split(Array('.')).toList match
              case "" :: Nil  => "_empty_" :: Nil
              case "" :: tail => "_empty_" :: tail
              case other => other
            if ctx.args.apiSubdirectory then "api" :: fqn else fqn
        ctx.checkPathCompat(path)
        cache.put(dri, path)
        path
      case cached => cached

  private def unknownPage(dri: DRI): String =
    // TODO we should switch that to warning probably or has dedicated setting
    report.inform(s"Unrecognized page for ${dri.location} ($dri)")
    UnresolvedLocationLink

  def pathToPage(from: DRI, to: DRI): String =
    if to.isStaticFile || effectiveMembers.contains(to) then
      val anchor = if to.anchor.isEmpty then "" else "#" + to.anchor
      pathToRaw(rawLocation(from), rawLocation(to)) +".html" + anchor
    else
      to.externalLink.fold(unknownPage(to))(l => l)

  def pathToRaw(from: Seq[String], to: Seq[String]): String =
    import dotty.tools.scaladoc.util.Escape._
    val fromDir = from.dropRight(1)
    val commonPaths = to.zip(fromDir).takeWhile{ case (a, b) => a == b }.size

    val contextPath = fromDir.drop(commonPaths).map(_ => "..")
    val nodePath = to.drop(commonPaths) match
        case Nil if contextPath.isEmpty && to.nonEmpty=> Seq("..", to.last)
        case Nil => to.lastOption.fold(Seq("index"))(".." :: _ :: Nil)
        case l => l

    escapeUrl((contextPath ++ nodePath).mkString("/"))

  def resolveRoot(from: Seq[String], to: String): String =
    pathToRaw(from, to.split("/").toList)

  def resolveRoot(dri: DRI, path: String): String = resolveRoot(rawLocation(dri), path)
  def absolutePath(dri: DRI, extension: String = "html"): String = rawLocation(dri).mkString("", "/", s".$extension")

  def escapedAbsolutePathWithAnchor(dri: DRI, extension: String = "html"): String =
    s"${escapeUrl(absolutePath(dri, extension))}#${dri.anchor}"

  def relativeInternalOrAbsoluteExternalPath(dri: DRI): String =
    dri.externalLink.getOrElse(escapedAbsolutePathWithAnchor(dri))

  def resolveLink(dri: DRI, url: String): String =
    if URI(url).isAbsolute then url else resolveRoot(dri, url)

  def pathToRoot(dri: DRI): String = rawLocation(dri).drop(1).map(_ => "..") match
    case Nil => ""
    case seq => seq.mkString("", "/" , "/")

  def driExists(dri: DRI) = effectiveMembers.get(dri).isDefined || dri.isStaticFile




© 2015 - 2024 Weber Informatics LLC | Privacy Policy