Skip to content

Commit e34a01f

Browse files
committed
Fix scala#8020: Create dotty-tasty-consumer library
1 parent 5dc00b1 commit e34a01f

File tree

35 files changed

+192
-137
lines changed

35 files changed

+192
-137
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 ;dotty-staging/test ;dotty-tasty-consumer/test ;dotty-tastydoc/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-consumer` = Build.`dotty-tasty-consumer`
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.
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-consumer jar */
57+
def dottyTastyConsumer: String = sys.props("dotty.tests.classes.dottyTastyConsumer")
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-consumer", withTastyConsumerOptions),
131+
compileDir("tests/run-custom-args/tasty-interpreter", withTastyConsumerOptions),
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 withTastyConsumerClasspath =
43+
withCompilerClasspath + File.pathSeparator + mkClasspath(List(Properties.dottyTastyConsumer))
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 withTastyConsumerOptions =
61+
defaultOptions.withClasspath(withTastyConsumerClasspath).withRunClasspath(withTastyConsumerClasspath)
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: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ To inspect the TASTy Reflect trees of a TASTy file a consumer can be defined in
1616
the following way.
1717

1818
```scala
19+
import scala.tasty.Reflection
20+
import scala.tasty.file._
21+
1922
class Consumer extends TastyConsumer {
2023
final def apply(reflect: Reflection)(root: reflect.Tree): Unit = {
2124
import reflect._
@@ -33,4 +36,18 @@ object Test {
3336
ConsumeTasty("", List("foo.Bar"), new Consumer)
3437
}
3538
}
36-
```
39+
```
40+
41+
Note that if we need to run the main (in an object called `Test`) after
42+
compilation we need make available the compiler to the runtime:
43+
44+
```shell
45+
dotc -with-compiler -d out Test.scala
46+
dotr -with-compiler -classpath out Test
47+
```
48+
49+
Or, from SBT:
50+
51+
```scala
52+
libraryDependencies += "ch.epfl.lamp" %% "dotty-tasty-consumer" % scalaVersion.value
53+
```

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

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

project/Build.scala

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,10 @@ object Build {
595595
val asm = findArtifactPath(externalDeps, "scala-asm")
596596
val dottyCompiler = jars("dotty-compiler")
597597
val dottyStaging = jars("dotty-staging")
598+
val dottyTastyConsumer = jars("dotty-tasty-consumer")
598599
val dottyInterfaces = jars("dotty-interfaces")
599600
val tastyCore = jars("tasty-core")
600-
run(insertClasspathInArgs(args1, List(dottyCompiler, dottyInterfaces, asm, dottyStaging, tastyCore).mkString(File.pathSeparator)))
601+
run(insertClasspathInArgs(args1, List(dottyCompiler, dottyInterfaces, asm, dottyStaging, dottyTastyConsumer, tastyCore).mkString(File.pathSeparator)))
601602
} else run(args)
602603
},
603604

@@ -671,9 +672,10 @@ object Build {
671672
}
672673
val dottyInterfaces = jars("dotty-interfaces")
673674
val dottyStaging = jars("dotty-staging")
675+
val dottyTastyConsumer = jars("dotty-tasty-consumer")
674676
val tastyCore = jars("tasty-core")
675677
val asm = findArtifactPath(externalDeps, "scala-asm")
676-
extraClasspath ++= Seq(dottyCompiler, dottyInterfaces, asm, dottyStaging, tastyCore)
678+
extraClasspath ++= Seq(dottyCompiler, dottyInterfaces, asm, dottyStaging, dottyTastyConsumer, tastyCore)
677679
}
678680

679681
val fullArgs = main :: insertClasspathInArgs(args, extraClasspath.mkString(File.pathSeparator))
@@ -715,14 +717,18 @@ object Build {
715717
)
716718

717719
lazy val bootstrapedDottyCompilerSettings = commonDottyCompilerSettings ++ Seq(
718-
javaOptions += {
720+
javaOptions ++= {
719721
val jars = packageAll.value
720-
"-Ddotty.tests.classes.dottyStaging=" + jars("dotty-staging")
722+
Seq(
723+
"-Ddotty.tests.classes.dottyStaging=" + jars("dotty-staging"),
724+
"-Ddotty.tests.classes.dottyTastyConsumer=" + jars("dotty-tasty-consumer"),
725+
)
721726
},
722727
packageAll := {
723728
packageAll.in(`dotty-compiler`).value ++ Seq(
724729
"dotty-compiler" -> packageBin.in(Compile).value.getAbsolutePath,
725730
"dotty-staging" -> packageBin.in(LocalProject("dotty-staging"), Compile).value.getAbsolutePath,
731+
"dotty-tasty-consumer" -> packageBin.in(LocalProject("dotty-tasty-consumer"), Compile).value.getAbsolutePath,
726732
"tasty-core" -> packageBin.in(LocalProject("tasty-core-bootstrapped"), Compile).value.getAbsolutePath,
727733
)
728734
}
@@ -803,6 +809,19 @@ object Build {
803809
javaOptions := (javaOptions in `dotty-compiler-bootstrapped`).value
804810
)
805811

812+
lazy val `dotty-tasty-consumer` = project.in(file("tasty-consumer")).
813+
withCommonSettings(Bootstrapped).
814+
// We want the compiler to be present in the compiler classpath when compiling this project but not
815+
// when compiling a project that depends on dotty-staging (see sbt-dotty/sbt-test/sbt-dotty/tasty-consumer-example-project),
816+
// but we always need it to be present on the JVM classpath at runtime.
817+
dependsOn(dottyCompiler(Bootstrapped) % "provided").
818+
dependsOn(dottyCompiler(Bootstrapped) % "compile->runtime").
819+
dependsOn(dottyCompiler(Bootstrapped) % "test->test").
820+
settings(commonBootstrappedSettings).
821+
settings(
822+
javaOptions := (javaOptions in `dotty-compiler-bootstrapped`).value
823+
)
824+
806825
lazy val `dotty-sbt-bridge` = project.in(file("sbt-bridge/src")).
807826
// We cannot depend on any bootstrapped project to compile the bridge, since the
808827
// bridge is needed to compile these projects.
@@ -1106,6 +1125,7 @@ object Build {
11061125
publishLocal in `dotty-library-bootstrapped`,
11071126
publishLocal in `tasty-core-bootstrapped`,
11081127
publishLocal in `dotty-staging`,
1128+
publishLocal in `dotty-tasty-consumer`,
11091129
publishLocal in `scala-library`,
11101130
publishLocal in `scala-reflect`,
11111131
publishLocal in `dotty-doc-bootstrapped`,
@@ -1315,7 +1335,7 @@ object Build {
13151335
// FIXME: we do not aggregate `bin` because its tests delete jars, thus breaking other tests
13161336
def asDottyRoot(implicit mode: Mode): Project = project.withCommonSettings.
13171337
aggregate(`dotty-interfaces`, dottyLibrary, dottyCompiler, tastyCore, dottyDoc, `dotty-sbt-bridge`).
1318-
bootstrappedAggregate(`scala-library`, `scala-compiler`, `scala-reflect`, scalap, `dotty-language-server`, `dotty-staging`).
1338+
bootstrappedAggregate(`scala-library`, `scala-compiler`, `scala-reflect`, scalap, `dotty-language-server`, `dotty-staging`, `dotty-tasty-consumer`).
13191339
dependsOn(tastyCore).
13201340
dependsOn(dottyCompiler).
13211341
dependsOn(dottyLibrary).
@@ -1354,6 +1374,7 @@ object Build {
13541374
def asDottyTastydoc(implicit mode: Mode): Project = project.withCommonSettings.
13551375
aggregate(`dotty-tastydoc-input`).
13561376
dependsOn(dottyCompiler).
1377+
dependsOn(`dotty-tasty-consumer`).
13571378
settings(commonDocSettings)
13581379

13591380
def asDottyTastydocInput(implicit mode: Mode): Project = project.withCommonSettings.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package hello
2+
3+
import scala.tasty.Reflection
4+
import scala.tasty.file._
5+
6+
object Main extends App {
7+
8+
9+
class Consumer extends TastyConsumer {
10+
final def apply(reflect: Reflection)(root: reflect.Tree): Unit = {
11+
import reflect._
12+
val tastyStr = root.show
13+
println(tastyStr)
14+
}
15+
}
16+
17+
ConsumeTasty("", List("lib.Foo"), new Consumer)
18+
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
lazy val dottyVersion = sys.props("plugin.scalaVersion")
2+
3+
lazy val lib = project
4+
.in(file("lib"))
5+
.settings(
6+
scalaVersion := dottyVersion
7+
)
8+
9+
lazy val app = project
10+
.in(file("app"))
11+
.settings(
12+
scalaVersion := dottyVersion,
13+
libraryDependencies += "ch.epfl.lamp" %% "dotty-tasty-consumer" % scalaVersion.value,
14+
)
15+
.dependsOn(lib)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package lib
2+
3+
class Foo {
4+
def foo(x: Int) = x
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version"))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
> app/run

0 commit comments

Comments
 (0)