Skip to content

Commit

Permalink
Scala 3 without Scala 2.13 toolchain (#1383)
Browse files Browse the repository at this point in the history
## Motivation

Until now Ammonite for Scala 3 was compiled using a mix of the Scala
2.13 and the Scala 3 compiler.
This was great since it allowed us to have Ammonite on Scala 3 before
`fastparse`, `mainargs` and other libraries were even supported on Scala
3, or they were not on par with their Scala 2.13 counterpart.
Now that the ecosystem has caught up with Scala 3, we can avoid using
Scala 2.13 and do everything with Scala 3.
This has the benefit that now all the classpath contains only Scala 3
libraries and we can finally invoke Scala 3 macros in the included
libraries like `upickle`.
Also, the build gets much simpler since we don't have to do tricks to
swap dependencies at runtime and manually remove transitive
dependencies.
The only dependency that still is on Scala 2.13 is scalameta `common`,
for which we still force the Scala 3 version of its `sourcecode`
dependency to avoid double dependencies at runtime.

## uPickle macros on Scala 3

<img width="867" alt="upickle"
src="https://github.com/com-lihaoyi/Ammonite/assets/5793054/05817a4a-58f7-4e33-9fb5-f829590911df">

## Breaking changes

- Drop support for Scala 3.1
- Drop support for Scala 2.13.0
- Scala 3 artifacts don't have the `-cross` naming convention anymore
but are just like Scala 2 artifacts except for the `_3` or `_3.x.y`
suffix
- `ammonite.util.Bind` now depends on
[typename](https://github.com/tpolecat/typename) instead of
scala-reflect (which doesn't have a Scala 3 counterpart
- `scala-java8-compat` updated to `1.0.2`
- `mainargs` updated to `0.5.4`
- `requests` updated to `0.8.0`
- `interp.api.APIHolder.value` is now `final`
- `typeOf` removed from Scala 3 API (was not supported already)
- Vararg command line arguments now use `mainargs.Leftover`
  • Loading branch information
lolgab authored Nov 16, 2023
1 parent 1bcbe7f commit cf9a7b8
Show file tree
Hide file tree
Showing 70 changed files with 422 additions and 696 deletions.
20 changes: 17 additions & 3 deletions .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
java-version: [8, 11]
scala-version: [2.12.18, 2.13.12, 3.3.1]
scala-binary-version: [2.12, 2.13, 3]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -23,13 +23,13 @@ jobs:
- uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java-version }}
- run: ./mill -i unitTest "${{ matrix.scala-version }}"
- run: ./mill -i unitTest "${{ matrix.scala-binary-version }}"
itest:
strategy:
fail-fast: false
matrix:
java-version: [8, 11]
scala-version: [2.12.18, 2.13.12, 3.3.1]
scala-version: [2.12.18, 2.13.12, 3.2.2, 3.3.1]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -39,3 +39,17 @@ jobs:
with:
java-version: ${{ matrix.java-version }}
- run: ./mill -i integrationTest ${{ matrix.scala-version }}
publishLocal:
strategy:
fail-fast: false
matrix:
scala-version: [2.12.18, 2.13.12, 3.2.2]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-java@v1
with:
java-version: 8
- run: ./mill -i __[${{ matrix.scala-version }}].__.publishLocal
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ out
.bloop
.vscode
.metals
.bsp
2 changes: 1 addition & 1 deletion .mill-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.10.11
0.10.13

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package ammonite.interp.api

class APIHolder[T >: Null <: AnyRef] {
var value0: T = null
implicit lazy val value = value0
implicit final lazy val value: T = value0
}
7 changes: 1 addition & 6 deletions amm/interp/src/main/scala/ammonite/interp/Interpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class Interpreter(val compilerBuilder: CompilerBuilder,
def watch(p: os.Path) = watchedValues.append(
(Watchable.Path(p), Watchable.pathSignature(p))
)
def watchValue[T](v: => T) = watchedValues.append((() => v.hashCode, v.hashCode()))
def watchValue[T](v: => T) = watchedValues.append((new Watchable { def poll() = v.hashCode.toLong }, v.hashCode().toLong))

def resolveSingleImportHook(
source: CodeSource,
Expand Down Expand Up @@ -214,11 +214,6 @@ class Interpreter(val compilerBuilder: CompilerBuilder,
source: CodeSource,
wrapperPath: Seq[Name]): Res[ImportHookInfo] = synchronized{

// Fake an update to the classpath to force re-creation of the compiler
// Workaround for https://github.com/scala/bug/issues/11564#issuecomment-501834821,
// which I caused in 2.13.0 and should be fixed in 2.13.1
if (scala.util.Properties.versionNumberString == "2.13.0") headFrame.addClasspath(Nil)

for (hookImports <- Res.map(importTrees)(resolveSingleImportHook(source, _, wrapperPath)))
yield ImportHookInfo(
Imports(hookImports.flatten.flatMap(_.value)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object SemanticdbProcessor {

val mapRange = {
val adjust0 = adjust(module.blocks.length)
range: scala.meta.internal.semanticdb.Range =>
(range: scala.meta.internal.semanticdb.Range) =>
for {
(startLine, startChar) <- adjust0(range.startLine, range.startCharacter)
(endLine, endChar) <- adjust0(range.endLine, range.endCharacter)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ammonite.repl

import scala.reflect.runtime.universe._

trait FullReplAPIScalaVersionSpecific {

def typeOf[T: WeakTypeTag] = scala.reflect.runtime.universe.weakTypeOf[T]
def typeOf[T: WeakTypeTag](t: => T) = scala.reflect.runtime.universe.weakTypeOf[T]

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ammonite.repl.api

import scala.reflect.runtime.universe._

trait ReplAPIScalaVersionSpecific {

/**
* Get the `Type` object of [[T]]. Useful for finding
* what its methods are and what you can do with it
*/
def typeOf[T: WeakTypeTag]: Type

/**
* Get the `Type` object representing the type of `t`. Useful
* for finding what its methods are and what you can do with it
*
*/
def typeOf[T: WeakTypeTag](t: => T): Type

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package ammonite.repl

trait FullReplAPIScalaVersionSpecific
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package ammonite.repl.api

trait ReplAPIScalaVersionSpecific
7 changes: 1 addition & 6 deletions amm/repl/api/src/main/scala/ammonite/repl/FullReplAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@ import ammonite.repl.api.ReplAPI
import ammonite.util.{Bind, _}
import ammonite.util.Util.newLine

import scala.reflect.runtime.universe._

import scala.collection.mutable
import scala.reflect.ClassTag
import scala.reflect.classTag

trait FullReplAPI extends ReplAPI{ replApi =>

def typeOf[T: WeakTypeTag] = scala.reflect.runtime.universe.weakTypeOf[T]
def typeOf[T: WeakTypeTag](t: => T) = scala.reflect.runtime.universe.weakTypeOf[T]
trait FullReplAPI extends ReplAPI with FullReplAPIScalaVersionSpecific { replApi =>

protected val colors: Ref[Colors]

Expand Down
20 changes: 1 addition & 19 deletions amm/repl/api/src/main/scala/ammonite/repl/api/ReplAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ package ammonite.repl.api

import ammonite.util._

import scala.reflect.runtime.universe._




trait ReplAPI {
trait ReplAPI extends ReplAPIScalaVersionSpecific {

/**
* Read/writable prompt for the shell. Use this to change the
Expand Down Expand Up @@ -47,19 +42,6 @@ trait ReplAPI {
*/
def history: History

/**
* Get the `Type` object of [[T]]. Useful for finding
* what its methods are and what you can do with it
*/
def typeOf[T: WeakTypeTag]: Type

/**
* Get the `Type` object representing the type of `t`. Useful
* for finding what its methods are and what you can do with it
*
*/
def typeOf[T: WeakTypeTag](t: => T): Type

/**
* Throw away the current scala.tools.nsc.Global and get a new one
*/
Expand Down
6 changes: 4 additions & 2 deletions amm/repl/api/src/main/scala/ammonite/repl/tools/Util.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ object Util {
/**
* Additional [[mainargs.TokensReader]] instance to teach it how to read Ammonite paths
*/
implicit object PathRead
extends mainargs.TokensReader[os.Path]("path", strs => Right(os.Path(strs.last, os.pwd)))
implicit object PathRead extends mainargs.TokensReader.Simple[os.Path] {
def shortName = "path"
def read(strs: Seq[String]) = Right(os.Path(strs.last, os.pwd))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ case class GrepResult(spans: Seq[(Int, Int)], text: fansi.Str)
object GrepResult{
case class Color(highlight: fansi.Attrs, dotDotDotColor: fansi.Attrs)
object Color{
implicit val defaultColor = Color(
implicit val defaultColor: Color = Color(
fansi.Back.Yellow ++ fansi.Color.Blue,
fansi.Attrs.Empty
)
Expand Down Expand Up @@ -211,8 +211,8 @@ object time {
object browse{
case class Strings(values: Seq[String])
object Strings{
implicit def stringPrefix(s: String) = Strings(Seq(s))
implicit def stringSeqPrefix(s: Seq[String]) = Strings(s)
implicit def stringPrefix(s: String): Strings = Strings(Seq(s))
implicit def stringSeqPrefix(s: Seq[String]): Strings = Strings(s)
}
// R -> show ansi-colors as colors, M -> show current-browse-% bar
val lessViewer = Seq("less", "-RM")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ammonite.main

import ammonite.util.{ImportData, Imports}

private[main] trait DefaultsScalaVersionSpecific {
val replImports = Imports(
ImportData("""ammonite.repl.ReplBridge.value.{
codeColorsImplicit,
tprintColorsImplicit,
show,
typeOf
}""")
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ammonite.main

import ammonite.util.{ImportData, Imports}

private[main] trait DefaultsScalaVersionSpecific {
val replImports = Imports(
ImportData("""ammonite.repl.ReplBridge.value.{
codeColorsImplicit,
tprintColorsImplicit,
show
}""")
)
}
Loading

0 comments on commit cf9a7b8

Please sign in to comment.