aboutsummaryrefslogtreecommitdiff
path: root/doc-tool/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala
blob: 02f6ccb97915fef81ac85abd967d3b05d9e54ee9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package dotty.tools
package dottydoc
package core

import dotc.core.Contexts.Context
import dotc.util.Positions.NoPosition

import transform.DocMiniPhase
import model._
import model.internal._
import model.comment._
import model.references._
import HtmlParsers._
import util.MemberLookup
import util.traversing._
import util.internal.setters._
import util.syntax._

class LinkReturnTypes extends DocMiniPhase with TypeLinker {
  override def transformDef(implicit ctx: Context) = { case df: DefImpl =>
    val returnValue = linkReference(df, df.returnValue, ctx.docbase.packages)
    df.copy(returnValue = returnValue)
  }

  override def transformVal(implicit ctx: Context) = { case vl: ValImpl =>
    val returnValue = linkReference(vl, vl.returnValue, ctx.docbase.packages)
    vl.copy(returnValue = returnValue)
  }
}

class LinkParamListTypes extends DocMiniPhase with TypeLinker {
  override def transformDef(implicit ctx: Context) = { case df: DefImpl =>
    val newParamLists = for {
      ParamListImpl(list, isImplicit) <- df.paramLists
      newList = list.map(linkReference(df, _, ctx.docbase.packages))
    } yield ParamListImpl(newList.asInstanceOf[List[NamedReference]], isImplicit)

    df.copy(paramLists = newParamLists)
  }
}

class LinkSuperTypes extends DocMiniPhase with TypeLinker {
  def linkSuperTypes(ent: Entity with SuperTypes)(implicit ctx: Context): List[MaterializableLink] =
    ent.superTypes.collect {
      case UnsetLink(title, query) =>
        handleEntityLink(title, lookup(ent, ctx.docbase.packages, query), ent)
    }

  override def transformClass(implicit ctx: Context) = { case cls: ClassImpl =>
    cls.copy(superTypes = linkSuperTypes(cls))
  }

  override def transformCaseClass(implicit ctx: Context) = { case cc: CaseClassImpl =>
    cc.copy(superTypes = linkSuperTypes(cc))
  }

  override def transformTrait(implicit ctx: Context) = { case trt: TraitImpl =>
    trt.copy(superTypes = linkSuperTypes(trt))
  }

  override def transformObject(implicit ctx: Context) = { case obj: ObjectImpl =>
    obj.copy(superTypes = linkSuperTypes(obj))
  }
}

class LinkImplicitlyAddedTypes extends DocMiniPhase with TypeLinker {
  override def transformDef(implicit ctx: Context) = {
    case df: DefImpl if df.implicitlyAddedFrom.isDefined =>
      val implicitlyAddedFrom = linkReference(df, df.implicitlyAddedFrom.get, ctx.docbase.packages)
      df.copy(implicitlyAddedFrom = Some(implicitlyAddedFrom))
  }

  override def transformVal(implicit ctx: Context) = {
    case vl: ValImpl if vl.implicitlyAddedFrom.isDefined =>
      val implicitlyAddedFrom = linkReference(vl, vl.implicitlyAddedFrom.get, ctx.docbase.packages)
      vl.copy(implicitlyAddedFrom = Some(implicitlyAddedFrom))
  }
}

trait TypeLinker extends MemberLookup {
  def handleEntityLink(title: String, target: Option[Entity], ent: Entity, query: String = ""): MaterializableLink =
    target match {
      case Some(target: Package) =>
        MaterializedLink(title, target.path.mkString("/") + "/index.html")
      case Some(target: TypeAlias) =>
        MaterializedLink(title, target.parent.path.mkString("/") + ".html#" + target.signature)
      case Some(target: Def) =>
        MaterializedLink(title, target.parent.path.mkString("/") + ".html#" + target.signature)
      case Some(target: Val) =>
        MaterializedLink(title, target.parent.path.mkString("/") + ".html#" + target.signature)
      case Some(target) =>
        MaterializedLink(title, target.path.mkString("/") + ".html")
      case none =>
        NoLink(title, query)
    }

  def linkReference(ent: Entity, ref: Reference, packs: Map[String, Package]): Reference = {
    def linkRef(ref: Reference) = linkReference(ent, ref, packs)

    ref match {
      case ref @ TypeReference(_, UnsetLink(t, query), tps) =>
        val inlineToHtml = InlineToHtml(ent)
        val title = t

        val target = handleEntityLink(title, lookup(ent, packs, query), ent, query)
        val tpTargets = tps.map(linkReference(ent, _, packs))
        ref.copy(tpeLink = target, paramLinks = tpTargets)
      case ref @ OrTypeReference(left, right) =>
        ref.copy(left = linkReference(ent, left, packs), right = linkReference(ent, right, packs))
      case ref @ AndTypeReference(left, right) =>
        ref.copy(left = linkReference(ent, left, packs), right = linkReference(ent, right, packs))
      case ref @ NamedReference(_, rf, _, _) =>
        ref.copy(ref = linkRef(rf))
      case ref @ FunctionReference(args, rv) =>
        ref.copy(args = args.map(linkReference(ent, _, packs)), returnValue = linkReference(ent, rv, packs))
      case ref @ TupleReference(args) =>
        ref.copy(args = args.map(linkRef))
      case ref @ BoundsReference(low, high) =>
        ref.copy(low = linkRef(low), high = linkRef(high))
      case _ =>
        ref
    }
  }
}