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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
package dotty.tools
package dottydoc
package model
import dotc.core.Symbols.Symbol
import dotc.core.Contexts.Context
import dotc.util.Positions.NoPosition
object parsers {
import comment._
import BodyParsers._
import model.internal._
import util.MemberLookup
import util.traversing._
import util.internal.setters._
class WikiParser extends CommentCleaner with CommentParser with CommentExpander {
private[this] var commentCache: Map[String, (Entity, Map[String, Package]) => Option[Comment]] = Map.empty
/** Parses comment and returns the path to the entity with an optional comment
*
* The idea here is to use this fact to create `Future[Seq[(String, Option[Comment]]]`
* which can then be awaited near the end of the run - before the pickling.
*/
def parseHtml(sym: Symbol, entity: Entity, packages: Map[String, Package])(implicit ctx: Context): (String, Option[Comment]) = {
val cmt = ctx.base.docstring(sym).map { d =>
val expanded = expand(sym)
val body = parse(entity, packages, clean(expanded), expanded, d.pos)
val summary = body.summary.map(_.toHtml(entity)).getOrElse("")
body.toHtml(entity) match {
case "" => None
case x => Some(Comment(x, summary))
}
}.flatten
(entity.path.mkString("."), cmt)
}
def add(entity: Entity, symbol: Symbol, ctx: Context): Unit = {
val commentParser = { (entity: Entity, packs: Map[String, Package]) =>
parseHtml(symbol, entity, packs)(ctx)._2
}
val path = entity.path.mkString(".")
if (!commentCache.contains(path) || ctx.base.docstring(symbol).isDefined)
commentCache = commentCache + (path -> commentParser)
}
def +=(entity: Entity, symbol: Symbol, ctx: Context) = add(entity, symbol, ctx)
def size: Int = commentCache.size
private def parse(entity: Entity, packs: Map[String, Package]): Option[Comment] =
commentCache(entity.path.mkString("."))(entity, packs)
def parse(packs: Map[String, Package]): Unit = {
def rootPackages: List[String] = {
var currentDepth = Int.MaxValue
var packages: List[String] = Nil
for (key <- packs.keys) {
val keyDepth = key.split("\\.").length
packages =
if (keyDepth < currentDepth) {
currentDepth = keyDepth
key :: Nil
} else if (keyDepth == currentDepth) {
key :: packages
} else packages
}
packages
}
for (pack <- rootPackages) {
mutateEntities(packs(pack)) { e =>
val comment = parse(e, packs)
setComment(e, to = comment)
}
}
}
def clear(): Unit = commentCache = Map.empty
}
sealed trait TypeLinker extends MemberLookup {
protected def linkReference(ent: Entity, rv: Reference, packs: Map[String, Package]): Reference =
rv match {
case rv @ TypeReference(_, UnsetLink(t, query), tps) =>
val inlineToHtml = InlineToHtml(ent)
val title = inlineToHtml(t)
def handleEntityLink(title: String, lt: LinkTo): MaterializableLink = lt match {
case Tooltip(str) => NoLink(title, str)
case LinkToExternal(_, url) => MaterializedLink(title, url)
case LinkToEntity(target) => MaterializedLink(title, util.traversing.relativePath(ent, target))
}
val target = handleEntityLink(title, makeEntityLink(ent, packs, t, NoPosition, query).link)
val tpTargets = tps.map {
case UnsetLink(t, query) =>
handleEntityLink(inlineToHtml(t), makeEntityLink(ent, packs, t, NoPosition, query).link)
case x => x
}
rv.copy(tpeLink = target, paramLinks = tpTargets)
case rv @ OrTypeReference(left, right) =>
rv.copy(left = linkReference(ent, left, packs), right = linkReference(ent, right, packs))
case rv @ AndTypeReference(left, right) =>
rv.copy(left = linkReference(ent, left, packs), right = linkReference(ent, right, packs))
case rv @ NamedReference(_, ref) => rv.copy(ref = linkReference(ent, ref, packs))
case _ => rv
}
def link(packs: Map[String, Package]): Unit
}
class ReturnTypeLinker extends TypeLinker {
def link(packs: Map[String, Package]): Unit =
for (pack <- packs.values) mutateEntities(pack) {
case ent: ReturnValue =>
setReturnValue(ent, linkReference(ent, ent.returnValue, packs))
case _ => ()
}
}
class ParamListLinker extends TypeLinker {
def link(packs: Map[String, Package]): Unit =
for (pack <- packs.values) mutateEntities(pack) {
case ent: Def =>
val newParamLists = for {
list <- ent.paramLists
newList = list.map(linkReference(ent, _, packs))
} yield newList.asInstanceOf[List[NamedReference]]
setParamLists(ent, newParamLists)
case _ => ()
}
}
}
|