scala.meta


1.3.0 (released on 11 Nov 2016)

Scala.meta is a clean-room implementation of a metaprogramming toolkit for Scala, designed to be simple, robust and portable. We are striving for scala.meta to become a successor of scala.reflect, the current de facto standard in the Scala ecosystem.

Scala.meta provides functionality that's unprecedented in the Scala ecosystem. Our killer feature is abstract syntax trees that capture the code exactly as it is written - with all the original formatting and attention to minor syntactic details.

With scala.meta, we are building a community of next-generation tooling for Scala. Codacy's Scala engine and Scalafmt take advantage of our unique features and deliver user experiences that have been unreachable for the most of the traditional Scala tools.

Features


High-fidelity parsing. Note how the abstract syntax trees in the printout below contain comprehensive information about formatting and comments. This is an exclusive feature of scala.meta.

scala> "x + y /* adds x and y */".parse[Term]
res0: scala.meta.parsers.Parsed[scala.meta.Term] = x + y /* adds x and y */

scala> "List[ Int ]".parse[Type]
res1: scala.meta.parsers.Parsed[scala.meta.Type] = List[ Int ]

Tokens. Scala.meta takes even the finest details of Scala code into account. We achieve this by attaching tokens, data structures representing atomic units of Scala syntax, to our abstract syntax trees. Note that the abstract syntax tree in the printout doesn't have the comment per se - it is stored in tokens instead.

scala> val tree = "x + y /* adds x and y */".parse[Term].get
tree: scala.meta.Term = x + y /* adds x and y */

scala> tree.syntax
res0: String = x + y /* adds x and y */

scala> tree.structure
res1: String = Term.ApplyInfix(Term.Name("x"), Term.Name("+"), Nil, Seq(Term.Name("y")))

scala> tree.tokens.structure
res2: String = Tokens(BOF [0..0), x [0..1),   [1..2), + [2..3),   [3..4), y [4..5),   [5..6), /* adds x and y */ [6..24), EOF [24..24))

Dialects. Scala.meta is designed from the ground up to be platform-independent. This means that we understand different versions of the base language: Scala 2.10, Scala 2.11 and even Dotty. We also support Sbt build files to make sure we cover as much Scala code as possible.

scala> import scala.meta.dialects.Sbt0137
import scala.meta.dialects.Sbt0137

scala> Sbt0137("""
  lazy val root = (project in file(".")).
  settings(name := "hello")
""").parse[Source]
res0: scala.meta.parsers.Parsed[scala.meta.Source] =

  lazy val root = (project in file(".")).
  settings(name := "hello")

Quasiquotes. Scala.reflect is notorious for being obscure and user-unfriendly, but it has its moments. Quasiquotes have proven to be an amazing productivity booster, so we implemented them in scala.meta, and now they are better than ever. Note how the precise types for x and y prevent the programmer from generating invalid code. Learn more about quasiquotes in our documentation.

scala> val addition = q"x + y"
addition: meta.Term.ApplyInfix = x + y

scala> val q"$x + $y" = addition
x: scala.meta.Term = x
y: meta.Term.Arg = y

scala> q"$y + $x"
<console>:17: error: type mismatch when unquoting;
 found   : scala.meta.Term.Arg
 required: scala.meta.Term
       q"$y + $x"
         ^

Getting started


To get started with scala.meta, add the following to your build.sbt:

libraryDependencies += "org.scalameta" %% "scalameta" % "1.3.0"

Next, you'll need to add a single wildcard import to the files where you'll be using scala.meta. Unlike with scala.reflect, the metaprogramming library from the standard distribution, no complicated setup is necessary.

import scala.meta._

To learn more about practical aspects of using scala.meta, take a look at our tutorial, which is based on a workshop given by Ólafur Pall Geirsson at Scala World 2016.

Roadmap


Semantic API. Our first priority is to come up with an API that will provide functionality to perform typechecking, name resolution, implicit inference, etc. It is crucial to fully model the language and achieve feature parity with scala.reflect.

New-style ("inline") macros. As announced at ScalaDays NYC 2016, macros based on scala.reflect are going to be dropped from the future versions of Scala. We are now working on the replacement, so-called inline macros, under the banner of Macro Paradise 3.0. You may be interested in visiting https://github.com/scalameta/paradise to check out the state of the art.

Other execution environments. The current version of scala.meta can only be run with Scala 2.11. This means that it is very hard or outright impossible to write scala.meta-based tools targetting Scala 2.10 (e.g. running in sbt 0.13.x) or Scala.js. Vote for #295 and #359 on our issue tracker if that's important for you.

Talks


Metaprogramming 2.0 (ScalaDays Berlin 2016). This talk explains the status of scala.meta, demonstrates key features, presents the early adopters and publishes our plans for the future. In Berlin, we provided an extensive story of what's going to happen to compile-time metaprogramming in Scala, featuring a live demo of new-style ("inline") macros that support integration with IntelliJ IDEA.

Video: https://www.youtube.com/watch?v=IPnd_SZJ1nM
Slides: http://scalamacros.org/paperstalks/2016-06-17-Metaprogramming20.pdf

Supporters


               

(c) 2014 - 2016 scala.meta contributors
Fork me on GitHub