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
|
package dotty.tools
package dotc
package core
import dotc.ast.{ untpd, tpd }
import Decorators._
import Symbols._
import Contexts.Context
import Flags.EmptyFlags
import dotc.util.SourceFile
import dotc.util.Positions._
import dotc.parsing.Parsers.Parser
import dotty.tools.dottydoc.model.comment.CommentUtils._
object Comments {
case class Comment(pos: Position, raw: String)(implicit ctx: Context) {
val isDocComment = raw.startsWith("/**")
private[this] lazy val sections = tagIndex(raw)
private def fold[A](z: A)(op: => A) = if (!isDocComment) z else op
lazy val usecases = fold(List.empty[UseCase]) {
sections
.filter { startsWithTag(raw, _, "@usecase") }
.map { case (start, end) => decomposeUseCase(start, end) }
}
/** Turns a usecase section into a UseCase, with code changed to:
* {{{
* // From:
* def foo: A
* // To:
* def foo: A = ???
* }}}
*/
private def decomposeUseCase(start: Int, end: Int): UseCase = {
val codeStart = skipWhitespace(raw, start + "@usecase".length)
val codeEnd = skipToEol(raw, codeStart)
val code = raw.substring(codeStart, codeEnd) + " = ???"
val codePos = subPos(codeStart, codeEnd)
val commentStart = skipLineLead(raw, codeEnd + 1) min end
val commentStr = "/** " + raw.substring(commentStart, end) + "*/"
val commentPos = subPos(commentStart, end)
UseCase(Comment(commentPos, commentStr), code, codePos)
}
private def subPos(start: Int, end: Int) =
if (pos == NoPosition) NoPosition
else {
val start1 = pos.start + start
val end1 = pos.end + end
pos withStart start1 withPoint start1 withEnd end1
}
}
case class UseCase(comment: Comment, code: String, codePos: Position)(implicit ctx: Context) {
/** Set by typer */
var tpdCode: tpd.DefDef = _
lazy val untpdCode: untpd.Tree = {
val tree = new Parser(new SourceFile("<usecase>", code)).localDef(codePos.start, EmptyFlags)
tree match {
case tree: untpd.DefDef =>
val newName = (tree.name.show + "$" + codePos + "$doc").toTermName
untpd.DefDef(newName, tree.tparams, tree.vparamss, tree.tpt, tree.rhs)
case _ =>
ctx.error("proper definition was not found in `@usecase`", codePos)
tree
}
}
}
}
|