@@ -14,12 +14,16 @@ import org.jetbrains.dokka.model.properties.PropertyContainer
1414import org .jetbrains .dokka .model .properties .PropertyContainerKt ._
1515import org .jetbrains .dokka .model .properties .{WithExtraProperties }
1616
17- import quoted .Quotes
17+ import java .util .regex .Pattern
18+
19+ import scala .util .{Try , Success , Failure }
1820import scala .tasty .inspector .DocTastyInspector
19- import dotty .dokka .model .api .withNewMembers
21+ import scala .quoted .Quotes
22+
23+ import dotty .tools .dotc
24+
2025import dotty .dokka .tasty .comments .MemberLookup
2126import dotty .dokka .tasty .comments .QueryParser
22- import scala .util .Try
2327import dotty .dokka .model .api ._
2428
2529/** 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
3034
3135 private val topLevels = Seq .newBuilder[(String , Member )]
3236
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+ }
46101
47- ctx.staticSiteContext.foreach(_.memberLinkResolver = driFor)
48- topLevels ++= parser.parseRootTree(root.asInstanceOf [parser.qctx.reflect.Tree ])
49- end processCompilationUnit
50102
51103 def result (): List [Member ] =
52104 topLevels.clear()
@@ -65,8 +117,14 @@ case class DokkaTastyInspector(parser: Parser)(using ctx: DocContext) extends Do
65117 }.toList
66118
67119/** 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 :
70128 import qctx .reflect ._
71129
72130 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
92150
93151 override def traverseTree (tree : Tree )(owner : Symbol ): Unit =
94152 seen = tree :: seen
95- tree match {
153+ if ! isSkipped(tree.symbol) then tree match {
96154 case pck : PackageClause =>
97155 docs += parsePackage(pck)
98156 super .traverseTree(tree)(owner)
0 commit comments