@@ -14,12 +14,16 @@ import org.jetbrains.dokka.model.properties.PropertyContainer
14
14
import org .jetbrains .dokka .model .properties .PropertyContainerKt ._
15
15
import org .jetbrains .dokka .model .properties .{WithExtraProperties }
16
16
17
- import quoted .Quotes
17
+ import java .util .regex .Pattern
18
+
19
+ import scala .util .{Try , Success , Failure }
18
20
import scala .tasty .inspector .DocTastyInspector
19
- import dotty .dokka .model .api .withNewMembers
21
+ import scala .quoted .Quotes
22
+
23
+ import dotty .tools .dotc
24
+
20
25
import dotty .dokka .tasty .comments .MemberLookup
21
26
import dotty .dokka .tasty .comments .QueryParser
22
- import scala .util .Try
23
27
import dotty .dokka .model .api ._
24
28
25
29
/** Responsible for collectively inspecting all the Tasty files we're interested in.
@@ -30,23 +34,71 @@ case class DokkaTastyInspector(parser: Parser)(using ctx: DocContext) extends Do
30
34
31
35
private val topLevels = Seq .newBuilder[(String , Member )]
32
36
33
- def processCompilationUnit (using q : Quotes )(root : q.reflect.Tree ): Unit =
34
- // NOTE we avoid documenting definitions in the magical stdLibPatches directory;
35
- // the symbols there are "patched" through dark Dotty magic onto other stdlib
36
- // definitions, so if we documented their origin, we'd get defs with duplicate DRIs
37
- if ! root.symbol.fullName.startsWith(" scala.runtime.stdLibPatches" ) then
38
- val parser = new TastyParser (q, this )
39
-
40
- def driFor (link : String ): Option [DRI ] =
41
- val symOps = new SymOps [q.type ](q)
42
- import symOps ._
43
- Try (QueryParser (link).readQuery()).toOption.flatMap(q =>
44
- MemberLookup .lookupOpt(q, None ).map{ case (sym, _) => sym.dri}
45
- )
37
+ def processCompilationUnit (using quotes : Quotes )(root : quotes.reflect.Tree ): Unit = ()
38
+
39
+ override def postProcess (using q : Quotes ): Unit =
40
+ // hack into the compiler to get a list of all top-level trees
41
+ // in principle, to do this, one would collect trees in processCompilationUnit
42
+ // however, path-dependent types disallow doing so w/o using casts
43
+ inline def hackForeachTree (thunk : q.reflect.Tree => Unit ): Unit =
44
+ given dctx : dotc.core.Contexts .Context = q.asInstanceOf [scala.quoted.runtime.impl.QuotesImpl ].ctx
45
+ dctx.run.units.foreach { compilationUnit =>
46
+ // mirrors code from TastyInspector
47
+ thunk(compilationUnit.tpdTree.asInstanceOf [q.reflect.Tree ])
48
+ }
49
+
50
+ val symbolsToSkip : Set [q.reflect.Symbol ] =
51
+ ctx.args.identifiersToSkip.flatMap { ref =>
52
+ val qrSymbol = q.reflect.Symbol
53
+ Try (qrSymbol.requiredPackage(ref)).orElse(Try (qrSymbol.requiredClass(ref))) match {
54
+ case Success (sym) => Some (sym)
55
+ case Failure (err) =>
56
+ report.warning(
57
+ s " Failed to resolve identifier to skip - $ref - because: ${throwableToString(err)}" ,
58
+ dotc.util.NoSourcePosition ,
59
+ )
60
+ None
61
+ }
62
+ }.toSet
63
+
64
+ val patternsToSkip : List [Pattern ] =
65
+ ctx.args.regexesToSkip.flatMap { regexString =>
66
+ Try (Pattern .compile(regexString)) match
67
+ case Success (pat) => Some (pat)
68
+ case Failure (err) =>
69
+ report.warning(
70
+ s " Failed to compile regex to skip - $regexString - because: ${throwableToString(err)}" ,
71
+ dotc.util.NoSourcePosition ,
72
+ )
73
+ None
74
+ }
75
+
76
+ def isSkipped (sym : q.reflect.Symbol ): Boolean =
77
+ def isSkippedById (sym : q.reflect.Symbol ): Boolean =
78
+ if ! sym.exists then false else
79
+ symbolsToSkip.contains(sym) || isSkipped(sym.owner)
80
+
81
+ def isSkippedByRx (sym : q.reflect.Symbol ): Boolean =
82
+ val symStr = sym.fullName
83
+ patternsToSkip.exists(p => p.matcher(symStr).matches())
84
+
85
+ isSkippedById(sym) || isSkippedByRx(sym)
86
+
87
+ hackForeachTree { root =>
88
+ if ! isSkipped(root.symbol) then
89
+ val parser = new TastyParser (q, this )(isSkipped)
90
+
91
+ def driFor (link : String ): Option [DRI ] =
92
+ val symOps = new SymOps [q.type ](q)
93
+ import symOps ._
94
+ Try (QueryParser (link).readQuery()).toOption.flatMap(q =>
95
+ MemberLookup .lookupOpt(q, None ).map{ case (sym, _) => sym.dri}
96
+ )
97
+
98
+ ctx.staticSiteContext.foreach(_.memberLinkResolver = driFor)
99
+ topLevels ++= parser.parseRootTree(root.asInstanceOf [parser.qctx.reflect.Tree ])
100
+ }
46
101
47
- ctx.staticSiteContext.foreach(_.memberLinkResolver = driFor)
48
- topLevels ++= parser.parseRootTree(root.asInstanceOf [parser.qctx.reflect.Tree ])
49
- end processCompilationUnit
50
102
51
103
def result (): List [Member ] =
52
104
topLevels.clear()
@@ -65,8 +117,14 @@ case class DokkaTastyInspector(parser: Parser)(using ctx: DocContext) extends Do
65
117
}.toList
66
118
67
119
/** Parses a single Tasty compilation unit. */
68
- case class TastyParser (qctx : Quotes , inspector : DokkaTastyInspector )(using val ctx : DocContext )
69
- extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport with NameNormalizer :
120
+ case class TastyParser (
121
+ qctx : Quotes ,
122
+ inspector : DokkaTastyInspector ,
123
+ )(
124
+ isSkipped : qctx.reflect.Symbol => Boolean
125
+ )(
126
+ using val ctx : DocContext
127
+ ) extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport with NameNormalizer :
70
128
import qctx .reflect ._
71
129
72
130
def processTree [T ](tree : Tree )(op : => T ): Option [T ] = try Option (op) catch
@@ -92,7 +150,7 @@ case class TastyParser(qctx: Quotes, inspector: DokkaTastyInspector)(using val c
92
150
93
151
override def traverseTree (tree : Tree )(owner : Symbol ): Unit =
94
152
seen = tree :: seen
95
- tree match {
153
+ if ! isSkipped(tree.symbol) then tree match {
96
154
case pck : PackageClause =>
97
155
docs += parsePackage(pck)
98
156
super .traverseTree(tree)(owner)
0 commit comments