Using Scala Compiler Plugins From Gradle

Scala Compiler Plugins with Gradle

The Scala compiler like just about every other modern programming language compiler has a plugin/extensibility story. It universally accepted that sbt is the default build tool for Scala. So users of sbt benefit from sbt’s first class support of Scala compiler plugins.

For those of us who choose (or are forced to use) other build tools, life is a little more difficult. It is more likely than not, that the ReadMe of your favorite compiler plugin does not include instructions on how to use the plugin outside of sbt. Alas, all hope is not gone. Repeat after me, “Yes we can!” You too can join in with the cool kids, and use compiler plugins.

NewType

The scalamacro.paradise plugin is a fairly popular plugin that many other plugins leverage. In this post, we are going to use macro paradise to enable scala-newtype macro expansion. The scala-newtype package includes a @newtype annotation that leverages scalamacro.paradise to allow you to generate new types that map to a wrapped type with zero runtime overhead.

import io.estatico.newtype.macros.newtype

package object types {

@newtype case class OrderId(value: String)
}

This is similar to the newtype keyword in Haskell, from which the library derives its name.

-- Haskell newtype example
newtype OrderId = OrderId String

The scala-newtype package/library is also very similar to theopaque type alias feature which is coming in Scala 3.0.

//Scala 3.0 / Dotty opaque type
opaque type OrderId = String

Gradle Paradise

I’m going to outline how you would go about enabling macro-paradise so you can use newtype in all its glory.

First, lets add a custom configuration to our gradle file.

We can achieve this by simply adding the following:

configurations {    
scalaCompilerPlugin
}

With that configuration in place, we can now add the macro paradise compiler plugin.

dependencies {
...
compile 'org.scala-lang:scala-library:2.12.6'
compile 'io.estatico:newtype_2.12:0.4.2'
scalaCompilerPlugin 'org.scalamacros:paradise_2.12.6:2.1.1'
...
}

At this point you should have something that looks like below:

scalaCompilerPlugin Configuration

Okay, we now have the plugin available, but that’s not enough. Now we need to make the Scala compiler aware of the scalamacro.paradise plugin by adding it to the scalaCompileOptions of the ScalaCompile task.

Adding Plugin to scalaCompileOptions

With this in place, you should now be able to use scala-newtype in anger with successful macro generation.

Wrapping Up

Once done you should have a build.gradle file that looks something like below:

Full code example

Though this post outlined adding the scalamacro.paradise plugin, you can use this same procedure to include other Scala compiler plugins. Enjoy!

You can also take a look at the corresponding repository for this post on GitHub.