Skip to content

Commit 2ae6901

Browse files
nicolasstuckisjrd
authored andcommitted
Remove OldTastyInspector from scaladoc
1 parent d83aa49 commit 2ae6901

File tree

8 files changed

+134
-99
lines changed

8 files changed

+134
-99
lines changed

Diff for: scaladoc/src/dotty/tools/scaladoc/ScalaModuleProvider.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ case class Module(rootPackage: Member, members: Map[DRI, Member])
88

99
object ScalaModuleProvider:
1010
def mkModule()(using ctx: DocContext): Module =
11-
val (result, rootDoc) = ScaladocTastyInspector().result()
11+
val (result, rootDoc) = ScaladocTastyInspector.loadDocs()
1212
val (rootPck, rest) = result.partition(_.name == "API")
1313
val (emptyPackages, nonemptyPackages) = (rest ++ rootPck.flatMap(_.members))
1414
.filter(p => p.members.nonEmpty || p.docs.nonEmpty).sortBy(_.name)

Diff for: scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala

+35-32
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package tasty
55
import java.util.regex.Pattern
66

77
import scala.util.{Try, Success, Failure}
8-
import scala.tasty.inspector.DocTastyInspector
8+
import scala.tasty.inspector.{TastyInspector, Inspector, Tasty}
99
import scala.quoted._
1010

1111
import dotty.tools.dotc
@@ -24,24 +24,12 @@ import ScaladocSupport._
2424
*
2525
* Delegates most of the work to [[TastyParser]] [[dotty.tools.scaladoc.tasty.TastyParser]].
2626
*/
27-
case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspector:
27+
case class ScaladocTastyInspector()(using ctx: DocContext) extends Inspector:
2828

2929
private val topLevels = Seq.newBuilder[(String, Member)]
3030
private var rootDoc: Option[Comment] = None
3131

32-
def processCompilationUnit(using Quotes)(root: reflect.Tree): Unit = ()
33-
34-
override def postProcess(using Quotes): Unit =
35-
// hack into the compiler to get a list of all top-level trees
36-
// in principle, to do this, one would collect trees in processCompilationUnit
37-
// however, path-dependent types disallow doing so w/o using casts
38-
inline def hackForeachTree(thunk: reflect.Tree => Unit): Unit =
39-
given dctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx
40-
dctx.run.nn.units.foreach { compilationUnit =>
41-
// mirrors code from TastyInspector
42-
thunk(compilationUnit.tpdTree.asInstanceOf[reflect.Tree])
43-
}
44-
32+
def inspect(using Quotes)(tastys: List[scala.tasty.inspector.Tasty[quotes.type]]): Unit =
4533
val symbolsToSkip: Set[reflect.Symbol] =
4634
ctx.args.identifiersToSkip.flatMap { ref =>
4735
val qrSymbol = reflect.Symbol
@@ -116,7 +104,8 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe
116104
rootDoc = Some(parseCommentString(using parser.qctx, summon[DocContext])(content, topLevelPck, None))
117105
}
118106

119-
hackForeachTree { root =>
107+
for tasty <- tastys do {
108+
val root = tasty.ast
120109
if !isSkipped(root.symbol) then
121110
val treeRoot = root.asInstanceOf[parser.qctx.reflect.Tree]
122111
processRootDocIfNeeded(treeRoot)
@@ -141,23 +130,7 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe
141130
topLevels += "scala" -> Member(scalaPckg.fullName, "", scalaPckg.dri, Kind.Package)
142131
topLevels += mergeAnyRefAliasAndObject(parser)
143132

144-
def result(): (List[Member], Option[Comment]) =
145-
topLevels.clear()
146-
rootDoc = None
147-
val filePaths = ctx.args.tastyFiles.map(_.getAbsolutePath).toList
148-
val classpath = ctx.args.classpath.split(java.io.File.pathSeparator).toList
149133

150-
if filePaths.nonEmpty then inspectFilesInContext(classpath, filePaths)
151-
152-
val all = topLevels.result()
153-
all.groupBy(_._1).map { case (pckName, members) =>
154-
val (pcks, rest) = members.map(_._2).partition(_.kind == Kind.Package)
155-
val basePck = pcks.reduce( (p1, p2) =>
156-
val withNewMembers = p1.withNewMembers(p2.members)
157-
if withNewMembers.docs.isEmpty then withNewMembers.withDocs(p2.docs) else withNewMembers
158-
)
159-
basePck.withMembers((basePck.members ++ rest).sortBy(_.name))
160-
}.toList -> rootDoc
161134

162135
def mergeAnyRefAliasAndObject(parser: TastyParser) =
163136
import parser.qctx.reflect._
@@ -171,6 +144,36 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe
171144
kind = Kind.Class(Nil, Nil),
172145
members = objectMembers
173146
)
147+
148+
object ScaladocTastyInspector:
149+
150+
def loadDocs()(using ctx: DocContext): (List[Member], Option[Comment]) =
151+
val filePaths = ctx.args.tastyFiles.map(_.getAbsolutePath).toList
152+
val classpath = ctx.args.classpath.split(java.io.File.pathSeparator).toList
153+
154+
val inspector = new ScaladocTastyInspector
155+
156+
val (tastyPaths, nonTastyPaths) = filePaths.partition(_.endsWith(".tasty"))
157+
val (jarPaths, invalidPaths) = nonTastyPaths.partition(_.endsWith(".jar"))
158+
159+
for invalidPath <- invalidPaths do
160+
report.error("File extension is not `tasty` or `jar`: " + invalidPath)
161+
162+
if tastyPaths.nonEmpty then
163+
TastyInspector.inspectAllTastyFiles(tastyPaths, jarPaths, classpath)(inspector)
164+
165+
val all = inspector.topLevels.result()
166+
all.groupBy(_._1).map { case (pckName, members) =>
167+
val (pcks, rest) = members.map(_._2).partition(_.kind == Kind.Package)
168+
val basePck = pcks.reduce( (p1, p2) =>
169+
val withNewMembers = p1.withNewMembers(p2.members)
170+
if withNewMembers.docs.isEmpty then withNewMembers.withDocs(p2.docs) else withNewMembers
171+
)
172+
basePck.withMembers((basePck.members ++ rest).sortBy(_.name))
173+
}.toList -> inspector.rootDoc
174+
175+
end ScaladocTastyInspector
176+
174177
/** Parses a single Tasty compilation unit. */
175178
case class TastyParser(
176179
qctx: Quotes,

Diff for: scaladoc/src/scala/tasty/inspector/DocTastyInspector.scala

-9
This file was deleted.

Diff for: scaladoc/src/scala/tasty/inspector/Inspector.scala

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copy of tasty-inspector/src/scala/tasty/inspector/Inspector.scala
2+
// FIXME remove this copy of the file
3+
4+
package scala.tasty.inspector
5+
6+
import scala.quoted._
7+
import scala.quoted.runtime.impl.QuotesImpl
8+
9+
import dotty.tools.dotc.Compiler
10+
import dotty.tools.dotc.Driver
11+
import dotty.tools.dotc.Run
12+
import dotty.tools.dotc.core.Contexts.Context
13+
import dotty.tools.dotc.core.Mode
14+
import dotty.tools.dotc.core.Phases.Phase
15+
import dotty.tools.dotc.fromtasty._
16+
import dotty.tools.dotc.util.ClasspathFromClassloader
17+
import dotty.tools.dotc.CompilationUnit
18+
import dotty.tools.unsupported
19+
import dotty.tools.dotc.report
20+
21+
import java.io.File.pathSeparator
22+
23+
trait Inspector:
24+
25+
/** Inspect all TASTy files using `Quotes` reflect API.
26+
*
27+
* Note: Within this method `quotes.reflect.SourceFile.current` will not work, hence the explicit source paths.
28+
*
29+
* @param tastys List of `Tasty` containing `.tasty`file path and AST
30+
*/
31+
def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit
32+
33+
end Inspector

Diff for: scaladoc/src/scala/tasty/inspector/Tasty.scala

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copy of tasty-inspector/src/scala/tasty/inspector/Tasty.scala
2+
// FIXME remove this copy of the file
3+
4+
package scala.tasty.inspector
5+
6+
import scala.quoted._
7+
8+
/** `.tasty` file representation containing file path and the AST */
9+
trait Tasty[Q <: Quotes & Singleton]:
10+
11+
/** Instance of `Quotes` used to load the AST */
12+
val quotes: Q
13+
14+
/** Path to the `.tasty` file */
15+
def path: String
16+
17+
/** Abstract Syntax Tree contained in the `.tasty` file */
18+
def ast: quotes.reflect.Tree
19+
20+
end Tasty
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copy of tasty-inspector/src/scala/tasty/inspector/TastyInspector.scala
2+
// FIXME remove this copy of the file
3+
14
package scala.tasty.inspector
25

36
import scala.quoted._
@@ -10,45 +13,43 @@ import dotty.tools.dotc.core.Contexts.Context
1013
import dotty.tools.dotc.core.Mode
1114
import dotty.tools.dotc.core.Phases.Phase
1215
import dotty.tools.dotc.fromtasty._
16+
import dotty.tools.dotc.quoted.QuotesCache
1317
import dotty.tools.dotc.util.ClasspathFromClassloader
1418
import dotty.tools.dotc.CompilationUnit
1519
import dotty.tools.unsupported
1620
import dotty.tools.dotc.report
1721

1822
import java.io.File.pathSeparator
1923

20-
// COPY OF OLD IMPLEMENTATION
21-
// TODO: update to new implementation
22-
trait OldTastyInspector:
23-
self =>
24-
25-
/** Process a TASTy file using TASTy reflect */
26-
protected def processCompilationUnit(using Quotes)(root: quotes.reflect.Tree): Unit
27-
28-
/** Called after all compilation units are processed */
29-
protected def postProcess(using Quotes): Unit = ()
24+
object TastyInspector:
3025

3126
/** Load and process TASTy files using TASTy reflect
3227
*
3328
* @param tastyFiles List of paths of `.tasty` files
29+
*
30+
* @return boolean value indicating whether the process succeeded
3431
*/
35-
def inspectTastyFiles(tastyFiles: List[String]): Boolean =
36-
inspectAllTastyFiles(tastyFiles, Nil, Nil)
32+
def inspectTastyFiles(tastyFiles: List[String])(inspector: Inspector): Boolean =
33+
inspectAllTastyFiles(tastyFiles, Nil, Nil)(inspector)
3734

3835
/** Load and process TASTy files in a `jar` file using TASTy reflect
3936
*
4037
* @param jars Path of `.jar` file
38+
*
39+
* @return boolean value indicating whether the process succeeded
4140
*/
42-
def inspectTastyFilesInJar(jar: String): Boolean =
43-
inspectAllTastyFiles(Nil, List(jar), Nil)
41+
def inspectTastyFilesInJar(jar: String)(inspector: Inspector): Boolean =
42+
inspectAllTastyFiles(Nil, List(jar), Nil)(inspector)
4443

4544
/** Load and process TASTy files using TASTy reflect
4645
*
4746
* @param tastyFiles List of paths of `.tasty` files
4847
* @param jars List of path of `.jar` files
4948
* @param dependenciesClasspath Classpath with extra dependencies needed to load class in the `.tasty` files
49+
*
50+
* @return boolean value indicating whether the process succeeded
5051
*/
51-
def inspectAllTastyFiles(tastyFiles: List[String], jars: List[String], dependenciesClasspath: List[String]): Boolean =
52+
def inspectAllTastyFiles(tastyFiles: List[String], jars: List[String], dependenciesClasspath: List[String])(inspector: Inspector): Boolean =
5253
def checkFile(fileName: String, ext: String): Unit =
5354
val file = dotty.tools.io.Path(fileName)
5455
if file.extension != ext then
@@ -58,40 +59,30 @@ trait OldTastyInspector:
5859
tastyFiles.foreach(checkFile(_, "tasty"))
5960
jars.foreach(checkFile(_, "jar"))
6061
val files = tastyFiles ::: jars
61-
files.nonEmpty && inspectFiles(dependenciesClasspath, files)
62-
63-
/** Load and process TASTy files using TASTy reflect and provided context
64-
*
65-
* Used in doctool to reuse reporter and setup provided by sbt
66-
*
67-
* @param classes List of paths of `.tasty` and `.jar` files (no validation is performed)
68-
* @param classpath Classpath with extra dependencies needed to load class in the `.tasty` files
69-
*/
70-
protected[inspector] def inspectFilesInContext(classpath: List[String], classes: List[String])(using Context): Unit =
71-
if (classes.isEmpty) report.error("Parameter classes should no be empty")
72-
inspectorDriver().process(inspectorArgs(classpath, classes), summon[Context])
73-
62+
inspectFiles(dependenciesClasspath, files)(inspector)
7463

75-
private def inspectorDriver() =
64+
private def inspectorDriver(inspector: Inspector) =
7665
class InspectorDriver extends Driver:
7766
override protected def newCompiler(implicit ctx: Context): Compiler = new TastyFromClass
7867

7968
class TastyInspectorPhase extends Phase:
8069
override def phaseName: String = "tastyInspector"
8170

82-
override def run(implicit ctx: Context): Unit =
83-
val qctx = QuotesImpl()
84-
self.processCompilationUnit(using qctx)(ctx.compilationUnit.tpdTree.asInstanceOf[qctx.reflect.Tree])
85-
86-
class TastyInspectorFinishPhase extends Phase:
87-
override def phaseName: String = "tastyInspectorFinish"
88-
89-
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] =
90-
val qctx = QuotesImpl()
91-
self.postProcess(using qctx)
71+
override def runOn(units: List[CompilationUnit])(using ctx0: Context): List[CompilationUnit] =
72+
val ctx = QuotesCache.init(ctx0.fresh)
73+
runOnImpl(units)(using ctx)
74+
75+
private def runOnImpl(units: List[CompilationUnit])(using Context): List[CompilationUnit] =
76+
val quotesImpl = QuotesImpl()
77+
class TastyImpl(val path: String, val ast: quotesImpl.reflect.Tree) extends Tasty[quotesImpl.type] {
78+
val quotes = quotesImpl
79+
}
80+
val tastys = units.map(unit => new TastyImpl(unit.source.path , unit.tpdTree.asInstanceOf[quotesImpl.reflect.Tree]))
81+
inspector.inspect(using quotesImpl)(tastys)
9282
units
9383

9484
override def run(implicit ctx: Context): Unit = unsupported("run")
85+
end TastyInspectorPhase
9586

9687
class TastyFromClass extends TASTYCompiler:
9788

@@ -105,7 +96,6 @@ trait OldTastyInspector:
10596

10697
override protected def backendPhases: List[List[Phase]] =
10798
List(new TastyInspectorPhase) :: // Perform a callback for each compilation unit
108-
List(new TastyInspectorFinishPhase) :: // Perform a final callback
10999
Nil
110100

111101
override def newRun(implicit ctx: Context): Run =
@@ -123,14 +113,14 @@ trait OldTastyInspector:
123113
("-from-tasty" :: "-Yretain-trees" :: "-classpath" :: fullClasspath :: classes).toArray
124114

125115

126-
private def inspectFiles(classpath: List[String], classes: List[String]): Boolean =
127-
if (classes.isEmpty)
128-
throw new IllegalArgumentException("Parameter classes should no be empty")
129-
130-
val reporter = inspectorDriver().process(inspectorArgs(classpath, classes))
131-
reporter.hasErrors
116+
private def inspectFiles(classpath: List[String], classes: List[String])(inspector: Inspector): Boolean =
117+
classes match
118+
case Nil => true
119+
case _ =>
120+
val reporter = inspectorDriver(inspector).process(inspectorArgs(classpath, classes))
121+
!reporter.hasErrors
132122

133123
end inspectFiles
134124

135125

136-
end OldTastyInspector
126+
end TastyInspector

Diff for: scaladoc/test/dotty/tools/scaladoc/ExternalLocationProviderIntegrationTest.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ class Scaladoc3ExternalLocationProviderIntegrationTest extends ExternalLocationP
5757

5858
def getScalaLibraryPath: String = {
5959
val classpath: List[String] = System.getProperty("java.class.path").split(java.io.File.pathSeparatorChar).toList
60-
classpath.find(_.contains("scala-library-2")).getOrElse("foobarbazz") // If we don't find the scala 2 library, the test will fail
60+
val stdlib = classpath.find(_.contains("scala-library-2")).getOrElse("foobarbazz") // If we don't find the scala 2 library, the test will fail
61+
new java.io.File(stdlib).getCanonicalPath() // canonicalize for case-insensitive file systems
6162
}
6263

6364
class Scaladoc2LegacyExternalLocationProviderIntegrationTest extends LegacyExternalLocationProviderIntegrationTest(

Diff for: scaladoc/test/dotty/tools/scaladoc/tasty/comments/MemberLookupTests.scala

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package dotty.tools.scaladoc
22
package tasty.comments
33

4-
import scala.quoted.Quotes
4+
import scala.quoted.*
55

66
import org.junit.{Test, Rule}
77
import org.junit.Assert.{assertSame, assertTrue}
@@ -198,14 +198,11 @@ class MemberLookupTests {
198198

199199
@Test
200200
def test(): Unit = {
201-
import scala.tasty.inspector.OldTastyInspector
202-
class Inspector extends OldTastyInspector:
203-
var alreadyRan: Boolean = false
201+
import scala.tasty.inspector.*
202+
class MyInspector extends Inspector:
204203

205-
override def processCompilationUnit(using ctx: quoted.Quotes)(root: ctx.reflect.Tree): Unit =
206-
if !alreadyRan then
207-
this.test()
208-
alreadyRan = true
204+
def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit =
205+
this.test()
209206

210207
def test()(using q: Quotes): Unit = {
211208
import dotty.tools.scaladoc.tasty.comments.MemberLookup
@@ -215,6 +212,6 @@ class MemberLookupTests {
215212
cases.testAll()
216213
}
217214

218-
Inspector().inspectTastyFiles(TestUtils.listOurClasses())
215+
TastyInspector.inspectTastyFiles(TestUtils.listOurClasses())(new MyInspector)
219216
}
220217
}

0 commit comments

Comments
 (0)