Git Product home page Git Product logo

virtuslab / scala-cli Goto Github PK

View Code? Open in Web Editor NEW
527.0 22.0 123.0 77.43 MB

Scala CLI is a command-line tool to interact with the Scala language. It lets you compile, run, test, and package your Scala code (and more!)

Home Page: https://scala-cli.virtuslab.org

License: Apache License 2.0

Shell 1.21% Scala 95.09% Java 0.67% Batchfile 0.19% JavaScript 1.08% CSS 0.08% Dockerfile 0.04% SCSS 0.91% MDX 0.72%
scala cli

scala-cli's Introduction

scala-cli

Build status Maven Central Discord

Scala CLI is a command-line tool to interact with the Scala language. It lets you compile, run, test, and package your Scala code. (and more!) It shares some similarities with build tools, but it doesn't aim at supporting multi-module projects, nor to be extended via a task system.

As of SIP-46, Scala CLI has been accepted as the new scala command and is currently in the experimental phase. If you want to try it out, check for more details here.

Docs

scala-cli's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scala-cli's Issues

Add `new` command?

To create sources with skeletons of simple apps for cats-effect, zio, various testing frameworks, etc.

Add fmt command

Using scalafmt either:

  • purely dynamically, downloading it upon launch and running it by spawning a JVM
  • purely statically, by depending on it and including it in our native binaries
  • a mix of both: default to a static embedded version, but allow for other version dynamically (although formatting would be slower)

Generate BSP discovery file

The BSP discovery file .bsp/scala-cli.json would enable any BSP server to connect to scala-cli. More concretely it would enable IntelliJ to import a scala-cli project.

It should contain something like:

{"name":"scala-cli","version":"0.0.0+274-gb0d66b5-SNAPSHOT","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["scala-cli","bsp"]}

This file could be generated systematically or by a dedicated command: scala-cli bsp-config.

Better overall CLI UX

For now, individual commands use case-app to parse arguments, and picking commands is manual.

Ideally, we'd like to have:

  • comprehensive and colorful usage and help messages, both for listing commands and for individual commands
  • completions for option names and option values

case-app lacks support for completions, his usage and help messages are poorly formatted and have no colors, and its commands API is complex.

moped could have been a candidate for that, but for a few cons:

  • it has many dependencies (JSON stuff, …)
  • no colors in help messages

We also don't have a need for many of its features (testkit, conversion to / from JSON / HOCON / …)

Execution of Scala.js fails and hangs in release mode

I'm on Apple M1, java version is:

❯ java -version
openjdk version "17" 2021-09-14
OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode)
❯ cat js.scala
object Hello extends App {
  var i = 0
  while (i < 5) {
    println(i)
    i += 1
  }
}

❯ scala-cli clean js.scala && scala-cli js.scala --js --js-mode dev
Compiling project (Scala 3.0.2, Scala.JS)
Compiled project (Scala 3.0.2, Scala.JS)
0
1
2
3
4

❯ scala-cli clean js.scala && scala-cli js.scala --js --js-mode release
Compiling project (Scala 3.0.2, Scala.JS)
Compiled project (Scala 3.0.2, Scala.JS)
java.lang.ExceptionInInitializerError
	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:315)
	at com.google.javascript.jscomp.DiagnosticGroups.<clinit>(DiagnosticGroups.java:233)
	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:375)
	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:295)
	at com.google.javascript.jscomp.CompilationLevel.applyFullCompilationOptions(CompilationLevel.java:179)
	at com.google.javascript.jscomp.CompilationLevel.setOptionsForCompilationLevel(CompilationLevel.java:86)
	at org.scalajs.linker.backend.closure.ClosureLinkerBackend.closureOptions(ClosureLinkerBackend.scala:219)
	at org.scalajs.linker.backend.closure.ClosureLinkerBackend.$anonfun$emit$5(ClosureLinkerBackend.scala:96)
	at org.scalajs.logging.Logger.time(Logger.scala:42)
	at org.scalajs.logging.Logger.time$(Logger.scala:40)
	at org.scalajs.logging.ScalaConsoleLogger.time(ScalaConsoleLogger.scala:15)
	at org.scalajs.linker.backend.closure.ClosureLinkerBackend.$anonfun$emit$3(ClosureLinkerBackend.scala:95)
	at scala.Option.map(Option.scala:230)
	at org.scalajs.linker.backend.closure.ClosureLinkerBackend.emit(ClosureLinkerBackend.scala:89)
	at org.scalajs.linker.standard.StandardLinkerImpl.$anonfun$link$2(StandardLinkerImpl.scala:47)
	at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:307)
	at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:41)
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
	at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
	at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
	at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192)
Caused by: java.util.MissingResourceException: Can't find bundle for base name com.google.javascript.rhino.Messages, locale en_US
	at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:2055)
	at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1689)
	at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1593)
	at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1556)
	at java.util.ResourceBundle.getBundle(ResourceBundle.java:932)
	at com.google.javascript.rhino.ErrorFormat.format(ErrorFormat.java:54)
	at com.google.javascript.rhino.SimpleErrorReporter.getMessage(SimpleErrorReporter.java:103)
	at com.google.javascript.rhino.SimpleErrorReporter.getMessage0(SimpleErrorReporter.java:95)
	at com.google.javascript.jscomp.RhinoErrorReporter.<clinit>(RhinoErrorReporter.java:136)
	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:375)
	at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:295)
	... 25 more

P.S.: having tons of fun with this tool, absolute incredible addition to Scala tooling!

Packaging should require configuration

Currently scala-cli package --deb create a valid deb package that adds app command to PATH.

We should have it configurable and also have interactive way to configure it

Consistent --help and --version flag or commands

It would be nice if all combination of help/-help/--help and version/-version/--version were supported. Currently, some of the combinations return error messages.

❯ scala-cli version
0.0.7
❯ scala-cli help
help: not found
❯ scala-cli --version
Unrecognized argument: --version
❯ scala-cli --help
Usage: scala-cli <COMMAND> [options]
Compile, run, package Scala code.

Help options:
  --usage                   Print usage and exit
  -h, -help, --help         Print help message and exit
  --help-full, --full-help  Print help message, including hidden options, and exit

Scala options:
  --js                                           Enable Scala.JS
...

sbt task system integration

We now have a build module, that can be used as a library to build projects. Don't know how do-able / usable it would be to define a set of keys / tasks using our library to build scala projects. This keys / tasks set would probably be rather different than the current one in sbt, which would be incompatible with most of its plugins.

Ammonite-style imports can trigger unused import warnings even when used

$ touch Main.scala

$ scala-cli compile Main.scala --scala 2.13.6 --scalac-option -Ywarn-unused:imports
Compiling project (Scala 2.13.6, JVM)
Compiled project (Scala 2.13.6, JVM)

$ echo 'import $ivy.`org.typelevel::cats-kernel:2.6.1`;  object Main { println(cats.kernel.Semigroup) }' > Main.scala

$ scala-cli compile Main.scala --scala 2.13.6 --scalac-option -Ywarn-unused:imports 
Compiling project (Scala 2.13.6, JVM)
[warn] ./Main.scala:1:1: Unused import
[warn] ^^^^^^^^^^^^^^
Compiled project (Scala 2.13.6, JVM)

$ scala-cli compile Main.scala --scala 2.13.6 --scalac-option -Ywarn-unused:imports --scalac-option -Xfatal-warnings
Compiling project (Scala 2.13.6, JVM)
[error] ./Main.scala:1:1: Unused import
[error] ^^^^^^^^^^^^^^
Error compiling project (Scala 2.13.6, JVM)

launcher version: https://github.com/VirtuslabRnD/scala-cli/releases/download/nightly/scala-cli-x86_64-apple-darwin.gz (downloaded at the time nightly pointed to c4852a7)

system: macOS catalina

Scope of scala-cli

It hasn't been a month, and there are already more issues about "features" than I think scala-cli should ever have. At the last meeting we already had some (inconclusive) discussions about what should or should not go in. It is not sustainable to have a debate about every individual feature.

We need to define one clear criteria against which we can weigh potential features, in order to determine whether they are in the scope of scala-cli or not.

We will probably have to discuss this in a live meeting, but it should also be put in a written form that we can refer to, hence this issue.

Too many hyphens in some prompted options (zsh)

Repro:

  1. scala-cli install completions --rc-file ./zsh --shell zsh
  2. source ./zsh
  3. Type scala-cli compile -[TAB]

Expected:
A lot of options, including --language

Acual:
A lot of options, including ---language (one extra hyphen)

Add publishing to Maven repositories capabilities

coursier has nascent publishing capabilities. These could be used for that, but these need some clean-up / updates before. In particular, it doesn't support "bundle uploads" to Sonatype repositories, that makes publishing there more reliable and that sbt-sonatype uses by default.

Running with Scala Native 0.4.1 fails

I know, I know... it's just been released :D

❯ cat native.scala
object E extends App {
  println("hello!")
}

❯ scala-cli version
0.0.7

❯ scala-cli clean native.scala && scala-cli run native.scala -S 2.13 --native --native-version 0.4.1
Compiling project (Scala 2.13.6, Scala Native)
Compiled project (Scala 2.13.6, Scala Native)
Exception in thread "main" scala.MatchError: 170 (of class java.lang.Integer)
	at scala.scalanative.nir.serialization.BinaryDeserializer.getInst(BinaryDeserializer.scala:106)
	at scala.scalanative.nir.serialization.BinaryDeserializer.$anonfun$getInsts$1(BinaryDeserializer.scala:103)
	at scala.scalanative.nir.serialization.BinaryDeserializer.$anonfun$getSeq$1(BinaryDeserializer.scala:41)
	at scala.scalanative.nir.serialization.BinaryDeserializer.$anonfun$getSeq$1$adapted(BinaryDeserializer.scala:41)
	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:286)
	at scala.collection.immutable.Range.foreach(Range.scala:158)
	at scala.collection.TraversableLike.map(TraversableLike.scala:286)
	at scala.collection.TraversableLike.map$(TraversableLike.scala:279)
	at scala.collection.AbstractTraversable.map(Traversable.scala:108)
	at scala.scalanative.nir.serialization.BinaryDeserializer.getSeq(BinaryDeserializer.scala:41)
	at scala.scalanative.nir.serialization.BinaryDeserializer.getInsts(BinaryDeserializer.scala:103)
	at scala.scalanative.nir.serialization.BinaryDeserializer.getDefn(BinaryDeserializer.scala:168)
	at scala.scalanative.nir.serialization.BinaryDeserializer.$anonfun$deserialize$1(BinaryDeserializer.scala:35)

Expectation

Works as with 0.4.0:

❯ scala-cli clean native.scala && scala-cli run native.scala -S 2.13 --native --native-version 0.4.0
Compiling project (Scala 2.13.6, Scala Native)
Compiled project (Scala 2.13.6, Scala Native)
Linking (1772 ms)
Discovered 974 classes and 7887 methods
Generating intermediate code (1416 ms)
Produced 16 files
Compiling to native code (2167 ms)
Linking native code (immix gc, none lto) (193 ms)
Total (6075 ms)
hello!

Use Scalafmt native-image binaries from the scalameta/scalafmt repository?

I just noticed that scala-cli is using native-image binaries from https://github.com/alexarchambault/scalafmt-native-image/releases

Would scala-cli be interested in using native-image binaries from the scalameta/scalafmt repository? We can add the necessary GH Action workflows to the main repo. The Scalafmt repo already builds some native-imagine binaries but we could sunset those binaries since they don't follow the standard naming conventions and are missing some platforms lik Windows.

Improve error message when user makes an error in ivy import

It would be nice to display something more meaningful when user makes an error in ivy imports.

To reproduce take a file and run scala-cli test on it:

import $ivy"com.novocode:junit-interface:0.11"
import org.junit.Test
import org.junit.Assert.*

class Test1:
  @Test def t1(): Unit = 
    assertEquals("I was compiled by Scala 3. :)", msg)

Error will be more or less:

maman@Marcins-MacBook-Pro ~/Documents/scala-cli (setup-ide-before-all) [1]> ./mill -i scala test ../example/scala3 -S 3.0.1                      (base) 
[132/506] de.tobiasroeser.mill.vcs.version.VcsVersion.vcsState 
[246/506] stubs.publishLocalNoFluff 
Publishing Artifact(org.virtuslab.scala-cli,stubs,0.0.4-SNAPSHOT) to ivy repo /Users/maman/Documents/scala-cli/out/repo/0.0.4-SNAPSHOT
[294/506] runner[2.13.6].publishLocalNoFluff 
Publishing Artifact(org.virtuslab.scala-cli,runner_2.13,0.0.4-SNAPSHOT) to ivy repo /Users/maman/Documents/scala-cli/out/repo/0.0.4-SNAPSHOT
[342/506] test-runner[2.13.6].publishLocalNoFluff 
Publishing Artifact(org.virtuslab.scala-cli,test-runner_2.13,0.0.4-SNAPSHOT) to ivy repo /Users/maman/Documents/scala-cli/out/repo/0.0.4-SNAPSHOT
[386/506] runner[2.12.15].publishLocalNoFluff 
Publishing Artifact(org.virtuslab.scala-cli,runner_2.12,0.0.4-SNAPSHOT) to ivy repo /Users/maman/Documents/scala-cli/out/repo/0.0.4-SNAPSHOT
[399/506] test-runner[2.12.15].publishLocalNoFluff 
Publishing Artifact(org.virtuslab.scala-cli,test-runner_2.12,0.0.4-SNAPSHOT) to ivy repo /Users/maman/Documents/scala-cli/out/repo/0.0.4-SNAPSHOT
[447/506] runner[3.0.2].publishLocalNoFluff 
Publishing Artifact(org.virtuslab.scala-cli,runner_3,0.0.4-SNAPSHOT) to ivy repo /Users/maman/Documents/scala-cli/out/repo/0.0.4-SNAPSHOT
[495/506] test-runner[3.0.2].publishLocalNoFluff 
Publishing Artifact(org.virtuslab.scala-cli,test-runner_3,0.0.4-SNAPSHOT) to ivy repo /Users/maman/Documents/scala-cli/out/repo/0.0.4-SNAPSHOT
[505/506] cli.run 
Exception in thread "main" java.lang.AssertionError: assertion failed
	at scala.Predef$.assert(Predef.scala:208)
	at scala.build.preprocessing.ScalaPreprocessor$.$anonfun$processSpecialImports$15(ScalaPreprocessor.scala:301)
	at scala.build.preprocessing.ScalaPreprocessor$.$anonfun$processSpecialImports$15$adapted(ScalaPreprocessor.scala:299)
	at scala.collection.Iterator.foreach(Iterator.scala:943)
	at scala.collection.Iterator.foreach$(Iterator.scala:943)
	at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
	at scala.collection.IterableLike.foreach(IterableLike.scala:74)
	at scala.collection.IterableLike.foreach$(IterableLike.scala:73)
	at scala.collection.AbstractIterable.foreach(Iterable.scala:56)
	at scala.build.preprocessing.ScalaPreprocessor$.scala$build$preprocessing$ScalaPreprocessor$$processSpecialImports(ScalaPreprocessor.scala:299)
	at scala.build.preprocessing.ScalaPreprocessor$stateMachine$async$3.apply(ScalaPreprocessor.scala:124)
	at scala.build.EitherStateMachine.start(EitherCps.scala:59)
	at scala.build.preprocessing.ScalaPreprocessor$.process(ScalaPreprocessor.scala:117)
	at scala.build.preprocessing.ScalaPreprocessor$stateMachine$async$1.apply(ScalaPreprocessor.scala:55)
	at scala.build.EitherStateMachine.start(EitherCps.scala:59)
	at scala.build.preprocessing.ScalaPreprocessor$.preprocess(ScalaPreprocessor.scala:49)
	at scala.build.CrossSources$stateMachine$async$1.$anonfun$forInputs$5(CrossSources.scala:76)
	at scala.collection.Iterator$$anon$11.nextCur(Iterator.scala:486)
	at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:492)
	at scala.collection.Iterator.toStream(Iterator.scala:1417)
	at scala.collection.Iterator.toStream$(Iterator.scala:1416)
	at scala.collection.AbstractIterator.toStream(Iterator.scala:1431)
	at scala.build.CrossSources$stateMachine$async$1.$anonfun$forInputs$4(CrossSources.scala:76)
	at scala.collection.immutable.List.map(List.scala:293)
	at scala.build.CrossSources$stateMachine$async$1.apply(CrossSources.scala:75)
	at scala.build.EitherStateMachine.start(EitherCps.scala:59)
	at scala.build.CrossSources$.forInputs(CrossSources.scala:71)
	at scala.build.Build$stateMachine$async$1.apply(Build.scala:118)
	at scala.build.EitherStateMachine.start(EitherCps.scala:59)
	at scala.build.Build$.scala$build$Build$$build(Build.scala:113)
	at scala.build.Build$.$anonfun$build$4(Build.scala:236)
	at scala.build.bloop.BloopServer$.withBuildServer(BloopServer.scala:200)
	at scala.build.Build$.build(Build.scala:229)
	at scala.build.Build$.build(Build.scala:248)
	at scala.cli.commands.Test$.run(Test.scala:55)
	at scala.cli.commands.Test$.run(Test.scala:8)
	at caseapp.core.app.CaseApp.main(CaseApp.scala:150)
	at caseapp.core.app.CommandsEntryPoint.main(CommandsEntryPoint.scala:112)
	at scala.cli.ScalaCli$.main(ScalaCli.scala:96)
	at scala.cli.ScalaCli.main(ScalaCli.scala)
1 targets failed
cli.run subprocess failed

There are 2 problems with it:

  • i don't see a position where user made an error which makes it super difficult to fix
  • error is not related to the reason why it was thrown

Source line not printed with compiler messages

➜ cat A.scala
object Main {
  def main(args: Array[String]): Unit = {
    typo()
  }
}

➜ scalac A.scala
A.scala:3: error: not found: value typo
    typo()
    ^
1 error

➜ scala-cli --scala-version 2.13.6 A.scala
Compiling project (Scala 2.13.6, JVM)
[error] ./A.scala:3:5: not found: value typo
[error]     ^^^^^
Error compiling project (Scala 2.13.6, JVM)
Compilation failed

Import scala-cli scripts directory as bsp module into Intellij sbt project

I'd like to try to accommodate following use case with scala-cli: keep some scripts alongside my main project and still be able to browse/navigate them in IntelliJ.
I wasn't able to achieve it with ammonite, so I have huge hopes for scala-cli.

I tried to accomplish it by importing a script dir as bsp module into my project. Detailed steps below:

  1. Create simple script under scripts dir
mkdir -p scripts
cat <<'EOT' > scripts/script.sc
import $ivy.`com.lihaoyi::upickle:1.4.0`
import ujson._
EOT
  1. run it with scala-cli scripts/script.sc
  2. prepare ide support with scala-cli setup-ide scripts
  3. Import the directory in Intellij with File -> New -> Module from existing sources -> select scripts dir -> select BSP import

Unfortunately, this doesn't add the upickle to the classpath and so ujson is not recognized.

I'm not familiar with BSP that much but the generated .bsp/scala-cli.json file doesn't seem to mention external dependencies in any way.

Ammonite imports don't work in REPL

$ cat abc.sc 
import $ivy.`org.scalaz::scalaz-core:7.3.5`, scalaz._, Scalaz._
val x = (Option(1) |@| Option(2))(_ + _)
println(x)
$ scala-cli -S 2.12 abc.sc 
Some(3)
$ scala-cli repl -S 2.12
Welcome to Scala 2.12.14 (OpenJDK 64-Bit Server VM, Java 11.0.11).
Type in expressions for evaluation. Or try :help.

scala> import $ivy.`org.scalaz::scalaz-core:7.3.5`
<console>:11: error: not found: value $ivy
       import $ivy.`org.scalaz::scalaz-core:7.3.5`
$ scala-cli about
Scala CLI version 0.0.1 (v0.0.1)

Proper packaging for Linux and Mac OS

In order to install Scala CLI, the web site suggests downloading a shell script and piping it into a shell interpreter. This is a shame.

Here's one reason why this practice, though popular, should be considered harmful:
https://www.idontplaydarts.com/2016/04/detecting-curl-pipe-bash-server-side/

I believe we should use package management tools wherever possible. Let's make installation great again!

Here's a list of package systems that are in my opinion worth supporting, in order of decreasing importance:

Split core and test sources

For now, the exact same sources are used by all commands ( compile, run, test, …). We may not want to put the tests in the output of package, or of the upcoming publish command.

For that, we need to decide on a way to mark some sources as test-specific.

There could be several ways of doing that:

  • assuming sources with the .test.scala extensions are tests,
  • using a top-level directive, like
package something

tests

class MyTests extends munit.FunSuite {
  …
}

or

test package something

class MyTests extends munit.FunSuite {
  …
}
  • with with the upcoming using syntax

Scripting: access to command line arguments

the docs say that a hello world script is desugared to:

object hello {
  val message = "Hello from Scala script"
  println(message)

  def main(args: Array[String]): Unit = ()
}

this leaves me unable to reference args

I don't see any information about this on the doc page I linked above

(context: I was hoping I could replace the combination of https://github.com/scala/community-build/blob/2.13.x/advance and https://github.com/scala/community-build/blob/2.13.x/scripts/Advance.scala with a single .sc file, but this is blocking me)

automatic scala 3 compiler library does not match compiler version

scala-cli version

v0.0.7

minimal example

import dotty.tools.dotc.config.Properties.versionString

println(s"Scala $versionString")

if I run this in scala-cli with -S 3.1 then it prints Scala version 3.0.0, I have to explicitly add using lib org.scala-lang::scala3-compiler:3.1.0 to get the library that matches the compiler version

Support running Scala 2 nightlies (and PR validation snapshots)

I had hoped this might work:

scala-cli repl --scala 2.13.7-bin-072e68e

and I also thought it might work if I used --repository:

scala-cli repl --scala 2.13.7-bin-072e68e \
  --repository https://scala-ci.typesafe.com/artifactory/scala-integration/

but it seems that --repository isn't used when resolving Scala itself:

Exception in thread "main" java.lang.Exception: coursier.error.ResolutionError$Several: Error downloading org.scala-lang:scala-library:2.13.7-bin-072e68e
  not found: /Users/tisue/.ivy2/local/org.scala-lang/scala-library/2.13.7-bin-072e68e/ivys/ivy.xml
  not found: https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.7-bin-072e68e/scala-library-2.13.7-bin-072e68e.pom
  not found: /Users/tisue/Library/Caches/ScalaCli/local-repo/latest-384-1cf98a/org.scala-lang/scala-library/2.13.7-bin-072e68e/ivys/ivy.xml

It would also be nice if Scala PR validation snapshots were also supported; those come from https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots . For convenience ,scala-runners allows --scala-pr 8960 and figures out the version number.

TASTy version should depend on the Scala version

Scala 3.1.0 has a new TASTy version, however this makes using scala-cli unusable for 3.1.0 as it is hard coded to expect the same tasty version as Scala 3.0.0 (i.e. 28.0-0)

here is a good test file: (run with scala-cli -S 3.1.0 tastyVersion.sc)

import dotty.tools.tasty.TastyFormat.*

val isPreview =
  if ExperimentalVersion > 0 then
    s" (preview $ExperimentalVersion)"
  else
    ""

val tastyVersion = s"$MajorVersion.$MinorVersion$isPreview"

println(s"TASTy version is $tastyVersion")

currently the renaming step causes a crash due to unexpected TASTy:

Compiling project (Scala 3.1.0, JVM)
Compiled project (Scala 3.1.0, JVM)
Exception in thread "main" scala.build.tastylib.UnpickleException: TASTy signature has wrong version.
 expected: {majorVersion: 28, minorVersion: 0}
 found   : {majorVersion: 28, minorVersion: 1}

This TASTy file was produced by a more recent, forwards incompatible release.
To read this TASTy file, please upgrade your tooling.
The TASTy file was produced by Scala 3.1.0.

Ammonite REPL as standard REPL (for Scala 2? for Scala 3?)

I think this choice is debatable (and should be debated).

In Scala 2 world, although Ammonite has a substantial userbase, it is not the standard REPL and I think making it one exceeds the scala-cli's authority, as it were. Spark uses the standard REPL, books use the standard REPL, I don't think Ammonite should just be swapped in as the new default as if it were the standard. Could it be provided, but as an alternative? I think that would be wonderful.

I'm less sure what I think about Scala 3. Scala 3 is new and there's more of a chance to say what the new standard is. But if Ammonite is going to become the standard Scala 3 REPL -- if that's the decision, then it should be the decision, not just for scala-cli specifically but for the Scala 3 effort as a whole, which implies discontinuing the existing Scala 3 REPL and removing it from the lampepfl/dotty repo.

Add Metals support

The CLI already relies on bloop for compilation, so a BSP server is already around.

While discussing this with various people, two paths towards this support emerged:

  • have Metals depends on parts of the CLI published as libraries, and use those to do the steps required to go from .scala files to a bloop project
  • favor BSP, only have Metals download the native CLI, and talk to it through BSP.

Add using direcitve to define tests within directory

Currently, scala-cli recognizes only recognizes files as tests if:

  • file name ends up with .test.scala
  • file comes from a in directory input and it is a member (may be transitively) of test subdirecory
  • file contains using target test directive

In most build tools (sbt, Mill or Gradle) there is an option to define a test directory. Maybe we can introduce test.sources directive that will list a directories (or even patters) of files / directories to be treated as tests, relative to the current directory.

mill task system integration

The build module can be used a a library to build projects. It would be interesting to define a mill.define.Module relying on it to build Java and Scala projects. All options would be configured through mill tasks, and actual compilation / packaging / etc. would be triggered from mill tasks.

That would allow to (hopefully seamlessly) transition from scala-build projects to more complex, possibly multi-modules, projects built through mill.

shebang doesn't work with scala 2.13.6

➜ cat A.scala
#!/usr/bin/env scala-cli
object Main {
  def main(args: Array[String]): Unit = {
    println(s"Hello ${args(0)}")
  }
}

➜ ./A.scala -- World
Hello World

➜ scala-cli ./A.scala -- World
Hello World

➜ ./A.scala --scala-version 2.13.6 -- World
Compiling project (Scala 2.13.6, JVM)
[error] ./A.scala:1:1: expected class or object definition
[error] ^
Error compiling project (Scala 2.13.6, JVM)
Compilation failed

➜ scala-cli --scala-version 2.13.6 ./A.scala -- World
Compiling project (Scala 2.13.6, JVM)
[error] ./A.scala:1:1: expected class or object definition
[error] ^
Error compiling project (Scala 2.13.6, JVM)
Compilation failed

Add single-module library handling capabilities

The scala CLI can be used for scripts, but could be used to publish libraries with a few more features. Namely, for many libraries, the following extra features should do:

  • publishing to Maven repository (#12)
  • MiMA support
  • cross-Scala version and platform sources support
  • mdoc or other way to generate static documentation

Having the ability to deal with single-module libraries would allow to significantly expand the potential user base of the scala CLI.

Non-deterministic inability to connect to bloop at times

I have a Scala script that I run regularly, and at times, it fails with:

Exception in thread "main" java.io.IOException: Can't connect to 127.0.0.1:49442
        at scala.build.bloop.BloopServer$.create$1(BloopServer.scala:89)
        at scala.build.bloop.BloopServer$.connect(BloopServer.scala:97)
        at scala.build.bloop.BloopServer$.bsp(BloopServer.scala:120) 
        at scala.build.bloop.BloopServer$.buildServer(BloopServer.scala:138)
        at scala.build.bloop.BloopServer$.withBuildServer(BloopServer.scala:203)
        at scala.build.Build$.build(Build.scala:190)
        at scala.build.Build$.build(Build.scala:207)        
        at scala.cli.commands.Run$.run(Run.scala:52)                            
        at scala.cli.commands.DefaultBase.run(DefaultBase.scala:25)
        at scala.cli.commands.DefaultBase.run(DefaultBase.scala:5)
        at caseapp.core.app.CaseApp.main(CaseApp.scala:150)
        at caseapp.core.app.CommandsEntryPoint.main(CommandsEntryPoint.scala:112)
        at scala.cli.ScalaCli$.main(ScalaCli.scala:61)
        at scala.cli.ScalaCli.main(ScalaCli.scala)
Caused by: java.net.ConnectException: Connection refused (Connection refused)
        at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljava_net_ConnectException_2_0002e_0003cinit_0003e_00028Ljava_lang_String_2_00029V(JNIJavaCallWrappers.java:0)
        at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:609)
        at java.net.Socket.connect(Socket.java:558)
        at java.net.Socket.<init>(Socket.java:454)
        at java.net.Socket.<init>(Socket.java:231)
        at scala.build.blooprifle.internal.Operations$$anon$2.openSocket(Operations.scala:205)
        at scala.build.blooprifle.BloopRifle$$anon$2.openSocket(BloopRifle.scala:118)
        at scala.build.bloop.BloopServer$.create$1(BloopServer.scala:81)
        ... 13 more

I haven't found what causes the problem, nor did I find how to fix it...

Cryptic compile warning: pure expression does nothing in statement position; you may be omitting necessary parentheses

❯ scala-cli version
0.0.7
❯ cat run.sc
using lib "org.scalameta::munit:0.7.29"

class MySuite extends munit.FunSuite {
  test("basic") {
    println("HELLO WORLD")
  }
}

❯ scala-cli test run.sc
Compiling project (Scala 3.0.2, JVM)
[warn] ./run.sc:23:5: A pure expression does nothing in statement position; you may be omitting necessary parentheses
Compiled project (Scala 3.0.2, JVM)
HELLO WORLD
run$MySuite:
  + basic 0.117s

The compile warning "A pure expression does nothing in statement position; you may be omitting necessary parentheses" points to a line number that doesn't exist in run.sc. It's not clear what code this warning refers to.

Bloop doesn't "unload" compiler plugins

When enabling Scala.JS or Scala Native, it seems bloop doesn't disable them if we don't enable them later on:

$ rm -rf examples/utest/.scala utest-j*.jar

$ /mill -i cli.run package examples/utest --library -o utest-jvm.jar
$ unzip -l utest-jvm.jar
Archive:  utest-jvm.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
       25  06-10-2021 16:51   META-INF/MANIFEST.MF
     1338  06-10-2021 16:51   MyTests.class
     3912  06-10-2021 16:51   MyTests$.class
---------                     -------
     5275                     3 files

$ ./mill -i cli.run package examples/utest --library -o utest-js.jar --js
$ unzip -l utest-js.jar
Archive:  utest-js.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
       25  06-10-2021 16:58   META-INF/MANIFEST.MF
     1338  06-10-2021 16:58   MyTests.class
     1067  06-10-2021 16:58   MyTests.sjsir
     3441  06-10-2021 16:58   MyTests$.sjsir
     3912  06-10-2021 16:58   MyTests$.class
---------                     -------
     9783                     5 files

$ ./mill -i cli.run package examples/utest -o utest-native.jar --native --library
$ unzip -l utest-native.jar
Archive:  utest-native.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
       25  06-10-2021 16:59   META-INF/MANIFEST.MF
     1338  06-10-2021 16:59   MyTests.class
     1067  06-10-2021 16:58   MyTests.sjsir
     3441  06-10-2021 16:58   MyTests$.sjsir
     3912  06-10-2021 16:59   MyTests$.class
    15987  06-10-2021 16:59   MyTests$.nir
     1596  06-10-2021 16:59   MyTests$$$Lambda$4.nir
     1599  06-10-2021 16:59   MyTests$$$Lambda$5.nir
     1906  06-10-2021 16:59   MyTests$$$Lambda$1.nir
     1906  06-10-2021 16:59   MyTests$$$Lambda$2.nir
     1182  06-10-2021 16:59   MyTests$$SN$ReflectivelyInstantiate$.nir
     1596  06-10-2021 16:59   MyTests$$$Lambda$3.nir
---------                     -------
    35555                     12 files

$ ./mill -i cli.run package examples/utest --library -o utest-jvm-after-js-and-native.jar
$ unzip -l utest-jvm-after-js-and-native.jar
Archive:  utest-jvm-after-js-and-native.jar
  Length      Date    Time    Name
---------  ---------- -----   ----
       25  06-10-2021 17:01   META-INF/MANIFEST.MF
     1338  06-10-2021 17:01   MyTests.class
     1067  06-10-2021 16:58   MyTests.sjsir
     3441  06-10-2021 16:58   MyTests$.sjsir
     3912  06-10-2021 17:01   MyTests$.class
    15987  06-10-2021 16:59   MyTests$.nir
     1596  06-10-2021 16:59   MyTests$$$Lambda$4.nir
     1599  06-10-2021 16:59   MyTests$$$Lambda$5.nir
     1906  06-10-2021 16:59   MyTests$$$Lambda$1.nir
     1906  06-10-2021 16:59   MyTests$$$Lambda$2.nir
     1182  06-10-2021 16:59   MyTests$$SN$ReflectivelyInstantiate$.nir
     1596  06-10-2021 16:59   MyTests$$$Lambda$3.nir
---------                     -------
    35555                     12 files

That's in spite of scala clearing the class output directory before each run. (bloop seems to copy the .sjsir and .nir files from its internal class directory).

Add fix command

To apply scalafix rules to the current project.

We could also allow to read scalafix rules from a directory of *.scala files, compiled on-the-fly.

Fmt command should be aware of scala-fmt version from the configuration

  • scala-cli should read the scalafmt version from the configuration file if it is not provided manually. If we are not doing it then the user is "greeted" with:
error: invalid Scalafmt version.

This Scalafmt installation has version '3.0.3' and the version configured in '/Users/maman/Documents/openaq-streamer/.scalafmt.conf' is '2.6.4'.
To fix this problem, add the following line to .scalafmt.conf:

version = '3.0.3'


NOTE: this error happens only when running a native Scalafmt binary.
Scalafmt automatically installs and invokes the correct version of Scalafmt when running on the JVM.

Default Bloop to tcp for non standard systems

I've used Bloop before on FreeBSD so I figured I'd give this a shot. I was making a port for scala-cli and when trying to use the scala-cli artifact that is in the release page, and then trying to run it on FreeBSD results in the following:

> scala-cli run Hello.scala
Exception in thread "main" java.lang.UnsatisfiedLinkError
        at org.scalasbt.ipcsocket.NativeLoader.load(NativeLoader.java:104)
        at org.scalasbt.ipcsocket.JNIUnixDomainSocketLibraryProvider.<clinit>(JNIUnixDomainSocketLibraryProvider.java:78)
        at org.scalasbt.ipcsocket.UnixDomainSocketLibraryProvider.get(UnixDomainSocketLibraryProvider.java:26)
        at org.scalasbt.ipcsocket.UnixDomainSocket.<init>(UnixDomainSocket.java:50)
        at scala.build.blooprifle.internal.NamedSocketBuilder.create(NamedSocketBuilder.scala:15)
        at scala.build.blooprifle.internal.Operations$$anon$1.liftedTree1$1(Operations.scala:229)
        at scala.build.blooprifle.internal.Operations$$anon$1.openSocket(Operations.scala:227)
        at scala.build.blooprifle.BloopRifle$$anon$2.openSocket(BloopRifle.scala:130)
        at scala.build.bloop.BloopServer$.create$1(BloopServer.scala:76)
        at scala.build.bloop.BloopServer$.connect(BloopServer.scala:92)
        at scala.build.bloop.BloopServer$.bsp(BloopServer.scala:115)
        at scala.build.bloop.BloopServer$.buildServer(BloopServer.scala:133)
        at scala.build.bloop.BloopServer$.withBuildServer(BloopServer.scala:198)
        at scala.build.Build$.build(Build.scala:347)
        at scala.build.Build$.build(Build.scala:371)
        at scala.cli.commands.Run$.run(Run.scala:71)
        at scala.cli.commands.Run$.run(Run.scala:20)
        at scala.cli.commands.Run$.run(Run.scala:14)
        at caseapp.core.app.CaseApp.main(CaseApp.scala:150)
        at caseapp.core.app.CommandsEntryPoint.main(CommandsEntryPoint.scala:112)
        at scala.cli.ScalaCli$.main(ScalaCli.scala:97)
        at scala.cli.ScalaCli.main(ScalaCli.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at coursier.bootstrap.launcher.Bootstrap.main(Bootstrap.java:109)
        at coursier.bootstrap.launcher.ResourcesLauncher.main(ResourcesLauncher.java:79)

This happens for run, compile, etc. The -h does work though :). Just throwing this up here in case it's a quick fix.

System details:

openjdk version "1.8.0_302"
OpenJDK Runtime Environment (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (build 25.302-b08, mixed mode)

FreeBSD 12.2

Convert to sbt / mill project

We'd like to allow to convert scala projects to full-fledged sbt or mill projects, if users end up needing their capabilities at some point.

Add `update` command

Allowing to bump dependencies in one's scala project.

Ideally, it would support the same kind of magic as scala-steward, with scalafix rules for some version bumps, updating the names of some dependencies when needed, etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.