All Projects → scalacenter → scala3-migrate

scalacenter / scala3-migrate

Licence: Apache-2.0 license
A tool to help migrating from Scala 2 to Scala 3

Programming Languages

scala
5932 projects
java
68154 projects - #9 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to scala3-migrate

Dotty
The Scala 3 compiler, also known as Dotty.
Stars: ✭ 4,836 (+5945%)
Mutual labels:  scala3
pfhais
Source code of the book Pure functional HTTP APIs in Scala including a chapter about upgrading to Scala 3.
Stars: ✭ 48 (-40%)
Mutual labels:  scala3
scala3-cross.g8
No description or website provided.
Stars: ✭ 12 (-85%)
Mutual labels:  scala3
why-roguelike
A multiplayer ASCII roguelike
Stars: ✭ 17 (-78.75%)
Mutual labels:  scala3
NDScala
N-dimensional arrays in Scala 3. Think NumPy ndarray, but type-safe over shapes, array/axis labels & numeric data types
Stars: ✭ 37 (-53.75%)
Mutual labels:  scala3
code-examples-manager
Software tool to manage your notes and code examples, to publish them as gists or snippets
Stars: ✭ 26 (-67.5%)
Mutual labels:  scala3
whilelang
A small programming language created with ANTLR and Scala
Stars: ✭ 29 (-63.75%)
Mutual labels:  scala3
Inkuire
Hoogle-like searches for Scala 3 and Kotlin
Stars: ✭ 70 (-12.5%)
Mutual labels:  scala3
scala-3-crash-course
Scala 3 workshop presenting the top new features of the language.
Stars: ✭ 34 (-57.5%)
Mutual labels:  scala3

scala3-migrate Latest version Build status

User documentation

For detailed documentation, refer to scala3-migrate section in the migration guide

Usage

scala3-migrate has been designed to make the migration to scala 3 easier.

It proposes an incremental approach that can be described as follows:

  • Migrating the library dependencies: using Coursier, it checks, for every library dependency, if there are versions available for Scala 3.
  • Migrating the Scala compiler options (scalacOptions): some compiler options of Scala 2 have been removed in Scala 3, others have been renamed, and some remain the same. This step helps you find how to evolve the compiler options of your project.
  • Migrating the syntax: this step relies on Scalafix and on existing rules to fix deprecated syntax that no longer compiles in Scala 3
  • Migrating the code: as explained in the section of type-inference, Scala 3 has a new type inference algorithm that may infer a different type than the one inferred by the Scala 2 compiler. This last step tries to find the minimum set of types to explicitly annotate in order to make the Scala 3 compiler work on a project without changing its meaning.

Requirements

  • sbt 1.5 or higher
  • java 8 or 11
  • scala 2.13, preferred 2.13.5

Installation

// project/plugins.sbt
addSbtPlugin("ch.epfl.scala" % "sbt-scala3-migrate" % "0.4.6")

Porting the build

The first step of the migration is to choose a single module that is going to be ported first. We will proceed with its migration then we will start again with another module.

If the chosen module is an aggregate project, only its own sources will be migrated, not the sources of its subprojects. Each subproject needs to be ported separately, one at a time.

We will port this simple build definition

lazy val main = project
  .in(file("."))
  .settings(
    name := "main",
    scalaVersion := V.scala213,
    semanticdbEnabled := true,
    scalacOptions ++= Seq("-explaintypes", "-Wunused"),
    libraryDependencies += compilerPlugin("org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full),
    libraryDependencies += compilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1"),
    libraryDependencies ++= Seq(
      "org.typelevel" %% "cats-core"           % "2.2.0",
      "ch.epfl.scala"  % "scalafix-interfaces" % "0.9.26",
      "com.softwaremill.scalamacrodebug" %% "macros" % "0.4.1" % Test,
      "ch.epfl.scala" %% "scalafix-rules"      % "0.9.26" % Test
    )
  )

Migrating libraryDependencies

> migrate-libs main
[info] Starting to migrate libDependencies for main
[info]
[info] X             : Cannot be updated to scala 3
[info] Valid         : Already a valid version for Scala 3
[info] To be updated : Need to be updated to the following version
[info]
[info] com.softwaremill.scalamacrodebug:macros:0.4.1:test           -> X : Contains Macros and is not yet published for 3.0.0
[info] com.olegpy:better-monadic-for:0.3.1:plugin->default(compile) -> X : Scala 2 compiler plugins are not supported in scala 3.0.0. You need to find an alternative
[info] ch.epfl.scala:scalafix-interfaces:0.9.26                     -> Valid
[info] org.typelevel:cats-core:2.2.0                                -> "org.typelevel" %% "cats-core" % "2.4.2"
[info] ch.epfl.scala:scalafix-rules:0.9.26:test                     -> "ch.epfl.scala" % "scalafix-rules_2.13" % "0.9.26" % "test"
[info] org.typelevel:kind-projector:0.11.0:plugin->default(compile) -> -Ykind-projector : This compiler plugin has a scalacOption equivalent. Add it to your scalacOptions

In this case you need to find alternative to better-monadic-for and make the project compile without the plugin. For com.softwaremill.scalamacrodebug:macros which is a macro lib, it won't be possible to migrate until it's published for 3.0.0.

The ported build would look like: (if we consider possible to remove com.softwaremill.scalamacrodebug:macros)

lazy val main = project
  .in(file("."))
  .settings(
    name := "main",
    scalaVersion := V.scala213,
    semanticdbEnabled := true,
    scalacOptions ++= (if (scalaVersion.value.startsWith("3.0")) Seq("-explaintypes", "-Wunused", "-Ykind-projector")
                       else Seq("-explaintypes", "-Wunused")),
    libraryDependencies ++= (
      if (scalaVersion.value.startsWith("3.0")) Seq()
      else
        Seq(compilerPlugin("org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full))
    ),
    libraryDependencies ++= Seq(
      "org.typelevel"                    %% "cats-core"           % "2.4.2",
      "ch.epfl.scala"                     % "scalafix-interfaces" % "0.9.26",
      "ch.epfl.scala"                    % "scalafix-rules_2.13" % "0.9.26" % Test
    )
  )

Migrating scalacOptions

> migrate-scalacOptions main
[info]
[info] Starting to migrate the scalacOptions for main
[warn] Some scalacOptions are set by sbt plugins and don't need to be modified, removed or added.
[warn] The sbt plugin should adapt its own scalacOptions for Scala 3
[info]
[info] X       : The following scalacOption is specific to Scala 2 and doesn't have an equivalent in Scala 3
[info] Renamed : The following scalacOption has been renamed in Scala3
[info] Valid   : The following scalacOption is a valid Scala 3 option
[info]
[info] -Wunused      -> X
[info] -Yrangepos    -> X
[info] -explaintypes -> -explain-types
[info]
[info] The following scalacOption are specific to compiler plugins, usually added through `compilerPlugin` or `addCompilerPlugin`.
[info] In the previous step `migrate-libs`, you should have removed/fixed compiler plugins and for the remaining plugins and settings, they can be kept as they are.
[info]
[info] -Xplugin:/Users/meriamlachkar/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/typelevel/kind-projector_2.13.3/0.11.0/kind-projector_2.13.3-0.11.0.jar     -> Valid
[info] -Xplugin:/Users/meriamlachkar/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/com/olegpy/better-monadic-for_2.13/0.3.1/better-monadic-for_2.13-0.3.1.jar      -> Valid
[info] -Xplugin:/Users/meriamlachkar/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scalameta/semanticdb-scalac_2.13.3/4.4.0/semanticdb-scalac_2.13.3-4.4.0.jar -> Valid
[info] -P:semanticdb:synthetics:on                                                                                                                                           -> Valid
[info] -P:semanticdb:targetroot:/Users/meriamlachkar/perso/plugin-test/target/scala-2.13/meta                                                                                -> Valid
[info] -P:semanticdb:sourceroot:/Users/meriamlachkar/perso/plugin-test                                                                                                       -> Valid
[info] -P:semanticdb:failures:warning                                                                                                                                        -> Valid
[success]                                                                                                                                      -> Valid

So following the output, the build will look like:

    scalacOptions ++= (if (scalaVersion.value.startsWith("3")) Seq("-explain-types", "-Ykind-projector")
                       else Seq("-explaintypes",  "-Wunused")),

Migrating the code

Fix syntax incompatibilities

First reload the build to take into account the new libs and scalacOptions.

> reload

The command migrate-syntax fix number of incompatibilities by applying the following Scalafix rules:

  • ProcedureSyntax
  • fix.scala213.ConstructorProcedureSyntax
  • fix.scala213.ExplicitNullaryEtaExpansion
  • fix.scala213.ParensAroundLambda
  • fix.scala213.ExplicitNonNullaryApply
  • fix.scala213.Any2StringAdd
> migrate-syntax main
[success] Total time: 0 s, completed 12 Mar 2021, 20:55:51
[info] We are going to fix some syntax incompatibilities
[INFO ] migrate.ScalaMigrat.previewSyntaxMigration:79 - Successfully run fixSyntaxForScala3  in 7280 milliseconds
[INFO ] migrate.utils.ScalafixService.fixInPlace:40 - Syntax fixed for Incompat13.scala)
[INFO ] migrate.utils.ScalafixService.fixInPlace:40 - Syntax fixed for Cats6.scala)
[INFO ] migrate.utils.ScalafixService.fixInPlace:40 - Syntax fixed for Cats5.scala)
[info]
[info]
[info] We fixed the syntax of this main to be compatible with 3.0.0
[info] You can now commit the change!
[info] You can also execute the next command to try to migrate to 3.0.0
[info]
[info] migrate main
[info]

After running this command, you can already commit those changes. Your module is still compiling in Scala 2 and is one step further to compile in Scala 3.

Add inferred types and implicits to make the project compile in Scala 3

Scala 3 uses a new type inference algorithm, therefore the Scala 3.0 compiler can infer a different type than the one inferred by the Scala 2.13. This command goal is to find the necessary types to add in order to make you code compiles.

> migrate main
[info] We are going to migrate your project main to scala 3
[INFO ] migrate.ScalaMigrat.buildMigrationFiles:140 - Found 20 patch candidate(s) in 7 file(s)after 1254 milliseconds
[INFO ] migrate.ScalaMigrat.compileInScala3:115 - Successfully compiled with scala 3 in 5997 milliseconds
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 5 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 2 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 1 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.migrate:24 - Found 1 required patch(es) in Incompat7.scala after 4385 milliseconds ms
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 2 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 1 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.migrate:24 - Found 1 required patch(es) in Incompat5.scala after 2243 milliseconds ms
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 2 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 1 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.migrate:24 - Found 1 required patch(es) in Incompat3.scala after 302 milliseconds ms
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 1 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.migrate:24 - Found 1 required patch(es) in ReflectiveCall.scala after 773 milliseconds ms
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 4 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 2 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 1 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.migrate:24 - Found 1 required patch(es) in Incompat9.scala after 1951 milliseconds ms
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 3 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 1 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.migrate:24 - Found 1 required patch(es) in PrivateLocalImplicitWithoutType.scala after 313 milliseconds ms
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 3 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.loopUntilNoCandidates:41 - 1 remaining candidate(s)
[INFO ] migrate.internal.FileMigration.migrate:24 - Found 1 required patch(es) in Incompat4.scala after 1225 milliseconds ms
[INFO ] migrate.ScalaMigrat.x$11:67 - Incompat7.scala has been successfully migrated
[INFO ] migrate.ScalaMigrat.x$11:67 - Incompat5.scala has been successfully migrated
[INFO ] migrate.ScalaMigrat.x$11:67 - Incompat9.scala has been successfully migrated
[INFO ] migrate.ScalaMigrat.x$11:67 - PrivateLocalImplicitWithoutType.scala has been successfully migrated
[INFO ] migrate.ScalaMigrat.x$11:67 - Incompat4.scala has been successfully migrated
[INFO ] migrate.ScalaMigrat.x$11:67 - ReflectiveCall.scala has been successfully migrated
[INFO ] migrate.ScalaMigrat.x$11:67 - Incompat3.scala has been successfully migrated
[info]
[info]
[info] main project has successfully been migrated to scala 3.0.0
[info] You can now commit the change!
[info] You can also execute the compile command:
[info]
[info] main / compile

What to do next ?

You can start again with another module MODULE2. If MODULE2 depends on the last module migrated, you need either to add -Ytasty-reader to MODULE2 scalacOptions, or reload or set MODULE-MIGRATED/scalaVersion := "2.13.5"

Once you're done, you can remove scala3-migrate from your plugins.

Contributions and feedbacks are welcome

The tool is still under development, and we would love to hear from you. Every feedback will help us build a better tool: typos, clearer log messages, better documentation, bug reports, ideas of features, so please open GitHub issues or contact us on gitter.

Acknowledgments

This tool is developed by Scala Center

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].