Skip to content

Commit 0b90ec1

Browse files
Merge pull request #8021 from dotty-staging/fix-#8020
Fix #8020: Create dotty-tasty-inspector library
2 parents 2ebbeb7 + 83fc85a commit 0b90ec1

File tree

38 files changed

+250
-226
lines changed

38 files changed

+250
-226
lines changed

.drone.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ steps:
4040
depends_on: [ clone ]
4141
commands:
4242
- cp -R . /tmp/2/ && cd /tmp/2/
43-
- ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test ;dotty-staging/test ;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test ;configureIDE"
43+
- ./project/scripts/sbt ";dotty-bootstrapped/compile ;dotty-bootstrapped/test;sjsSandbox/run;sjsSandbox/test;sjsJUnitTests/test ;configureIDE"
4444
- ./project/scripts/bootstrapCmdTests
4545

4646
- name: community_build

build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ val `dotty-library-bootstrappedJS` = Build.`dotty-library-bootstrappedJS`
1111
val `dotty-sbt-bridge` = Build.`dotty-sbt-bridge`
1212
val `dotty-sbt-bridge-tests` = Build.`dotty-sbt-bridge-tests`
1313
val `dotty-staging` = Build.`dotty-staging`
14+
val `dotty-tasty-inspector` = Build.`dotty-tasty-inspector`
1415
val `dotty-language-server` = Build.`dotty-language-server`
1516
val `dotty-bench` = Build.`dotty-bench`
1617
val `dotty-bench-bootstrapped` = Build.`dotty-bench-bootstrapped`

compiler/src/dotty/tools/dotc/consumetasty/ConsumeTasty.scala

Lines changed: 0 additions & 55 deletions
This file was deleted.

compiler/src/dotty/tools/dotc/consumetasty/TastyConsumerPhase.scala

Lines changed: 0 additions & 18 deletions
This file was deleted.

compiler/src/dotty/tools/dotc/consumetasty/TastyFromClass.scala

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package dotty.tools.dotc.util
2+
3+
import java.net.URLClassLoader
4+
import java.nio.file.Paths
5+
6+
import dotty.tools.repl.AbstractFileClassLoader
7+
8+
object ClasspathFromClassloader {
9+
10+
/** Attempt to recreate a classpath from a classloader.
11+
*
12+
* BEWARE: with exotic enough classloaders, this may not work at all or do
13+
* the wrong thing.
14+
*/
15+
def apply(cl: ClassLoader): String = {
16+
val classpathBuff = List.newBuilder[String]
17+
def collectClassLoaderPaths(cl: ClassLoader): Unit = {
18+
if (cl != null) {
19+
cl match {
20+
case cl: URLClassLoader =>
21+
// This is wrong if we're in a subclass of URLClassLoader
22+
// that filters loading classes from its parent ¯\_(ツ)_/¯
23+
collectClassLoaderPaths(cl.getParent)
24+
// Parent classloaders are searched before their child, so the part of
25+
// the classpath coming from the child is added at the _end_ of the
26+
// classpath.
27+
classpathBuff ++=
28+
cl.getURLs.iterator.map(url => Paths.get(url.toURI).toAbsolutePath.toString)
29+
case _ =>
30+
// HACK: We can't just collect the classpath from arbitrary parent
31+
// classloaders since the current classloader might intentionally
32+
// filter loading classes from its parent (for example
33+
// BootFilteredLoader in the sbt launcher does this and we really
34+
// don't want to include the scala-library that sbt depends on
35+
// here), but we do need to look at the parent of the REPL
36+
// classloader, so we special case it. We can't do this using a type
37+
// test since the REPL classloader class itself is normally loaded
38+
// with a different classloader.
39+
if (cl.getClass.getName == classOf[AbstractFileClassLoader].getName)
40+
collectClassLoaderPaths(cl.getParent)
41+
}
42+
}
43+
}
44+
collectClassLoaderPaths(cl)
45+
classpathBuff.result().mkString(java.io.File.pathSeparator)
46+
}
47+
}

compiler/test/dotty/Properties.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ object Properties {
5353
/** dotty-staging jar */
5454
def dottyStaging: String = sys.props("dotty.tests.classes.dottyStaging")
5555

56+
/** dotty-tasty-inspector jar */
57+
def dottyTastyInspector: String = sys.props("dotty.tests.classes.dottyTastyInspector")
58+
5659
/** tasty-core jar */
5760
def tastyCore: String = sys.props("dotty.tests.classes.tastyCore")
5861

compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting {
127127
aggregateTests(
128128
compileFilesInDir("tests/run-with-compiler", withCompilerOptions),
129129
compileFilesInDir("tests/run-staging", withStagingOptions),
130-
compileDir("tests/run-with-compiler-custom-args/tasty-interpreter", withCompilerOptions)
130+
compileFilesInDir("tests/run-custom-args/tasty-inspector", withTastyInspectorOptions),
131+
compileDir("tests/run-custom-args/tasty-interpreter", withTastyInspectorOptions),
131132
).checkRuns()
132133
}
133134

compiler/test/dotty/tools/vulpix/TestConfiguration.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ object TestConfiguration {
3939
lazy val withStagingClasspath =
4040
withCompilerClasspath + File.pathSeparator + mkClasspath(List(Properties.dottyStaging))
4141

42+
lazy val withTastyInspectorClasspath =
43+
withCompilerClasspath + File.pathSeparator + mkClasspath(List(Properties.dottyTastyInspector))
44+
4245
def mkClasspath(classpaths: List[String]): String =
4346
classpaths.map({ p =>
4447
val file = new java.io.File(p)
@@ -54,6 +57,8 @@ object TestConfiguration {
5457
defaultOptions.withClasspath(withCompilerClasspath).withRunClasspath(withCompilerClasspath)
5558
lazy val withStagingOptions =
5659
defaultOptions.withClasspath(withStagingClasspath).withRunClasspath(withStagingClasspath)
60+
lazy val withTastyInspectorOptions =
61+
defaultOptions.withClasspath(withTastyInspectorClasspath).withRunClasspath(withTastyInspectorClasspath)
5762
val allowDeepSubtypes = defaultOptions without "-Yno-deep-subtypes"
5863
val allowDoubleBindings = defaultOptions without "-Yno-double-bindings"
5964
val picklingOptions = defaultOptions and (

dist/bin/common

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ DOTTY_COMP=$(find_lib "*dotty-compiler*")
108108
DOTTY_INTF=$(find_lib "*dotty-interfaces*")
109109
DOTTY_LIB=$(find_lib "*dotty-library*")
110110
DOTTY_STAGING=$(find_lib "*dotty-staging*")
111+
DOTTY_CONSUME_TASTY=$(find_lib "*dotty-consume-tasty*")
111112
TASTY_CORE=$(find_lib "*tasty-core*")
112113
SCALA_ASM=$(find_lib "*scala-asm*")
113114
SCALA_LIB=$(find_lib "*scala-library*")

dist/bin/dotr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then
102102
echo "warning: multiple classpaths are found, dotr only use the last one."
103103
fi
104104
if [ $with_compiler == true ]; then
105-
cp_arg+="$PSEP$DOTTY_COMP$PSEP$TASTY_CORE$PSEP$DOTTY_INTF$PSEP$SCALA_ASM$PSEP$DOTTY_STAGING"
105+
cp_arg+="$PSEP$DOTTY_COMP$PSEP$TASTY_CORE$PSEP$DOTTY_INTF$PSEP$SCALA_ASM$PSEP$DOTTY_STAGING$PSEP$DOTTY_CONSUME_TASTY"
106106
fi
107107
eval exec "\"$JAVACMD\"" "$DEBUG" "-classpath \"$cp_arg\"" "${jvm_options[@]}" "${residual_args[@]}"
108108
else

docs/docs/reference/metaprogramming/tasty-inspect.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ layout: doc-page
33
title: "TASTy Inspection"
44
---
55

6+
```scala
7+
libraryDependencies += "ch.epfl.lamp" %% "dotty-tasty-inspector" % scalaVersion.value
8+
```
9+
610
TASTy files contain the full typed tree of a class including source positions
711
and documentation. This is ideal for tools that analyze or extract semantic
812
information of the code. To avoid the hassle of working directly with the TASTy
9-
file we provide the `TastyConsumer` which loads the contents and exposes it
13+
file we provide the `TastyInspector` which loads the contents and exposes it
1014
through the TASTy reflect API.
1115

1216

@@ -16,7 +20,10 @@ To inspect the TASTy Reflect trees of a TASTy file a consumer can be defined in
1620
the following way.
1721

1822
```scala
19-
class Consumer extends TastyConsumer {
23+
import scala.tasty.Reflection
24+
import scala.tasty.file._
25+
26+
class Consumer extends TastyInspector {
2027
final def apply(reflect: Reflection)(root: reflect.Tree): Unit = {
2128
import reflect._
2229
// Do something with the tree
@@ -30,7 +37,15 @@ the class `foo.Bar` for a foo in the classpath.
3037
```scala
3138
object Test {
3239
def main(args: Array[String]): Unit = {
33-
ConsumeTasty("", List("foo.Bar"), new Consumer)
40+
InspectTasty("", List("foo.Bar"), new Consumer)
3441
}
3542
}
36-
```
43+
```
44+
45+
Note that if we need to run the main (in an object called `Test`) after
46+
compilation we need make available the compiler to the runtime:
47+
48+
```shell
49+
dotc -with-compiler -d out Test.scala
50+
dotr -with-compiler -classpath out Test
51+
```

library/src/scala/tasty/file/ConsumeTasty.scala

Lines changed: 0 additions & 26 deletions
This file was deleted.

library/src/scala/tasty/file/TastyConsumer.scala

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)