How to include a Scala compiler plugin from a local path? - scala

I'm developing a Scala compiler plugin, and right now I have to go to the plugin project, run sbt publishLocal, come back to my project, and run sbt clean compile.
This is because I'm using addCompilerPlugin(...) in my build.sbt
I wonder if there's a way to refer the compiler plugin's local path, so that I can simply run sbt compile.
Thank you.

Here's how we can achieve it:
scalacOptions in Compile ++= {
val jar = (Keys.`package` in (plugin, Compile)).value
System.setProperty("sbt.paths.plugin.jar", jar.getAbsolutePath)
val addPlugin = "-Xplugin:" + jar.getAbsolutePath
// Thanks Jason for this cool idea (taken from https://github.com/retronym/boxer)
// add plugin timestamp to compiler options to trigger recompile of
// main after editing the plugin. (Otherwise a 'clean' is needed in the current project)
val dummy = "-Jdummy=" + jar.lastModified
Seq(addPlugin, dummy)
}
Here's an example: https://github.com/GIVESocialMovement/scala-named-argument-compiler-plugin/blob/master/test-project/build.sbt#L26
This above runs package on the plugin project, gets its jar, and adds the plugin through scalacOptions on the current project.
Thanks this redditor for answering my question: https://www.reddit.com/r/scala/comments/aq2bt6/just_made_a_compiler_plugin_to_enforce_named/

Related

Scala's build.sbt not recognised by IntelliJ

I'm having an issue where my build.sbt file is not being picked up properly using IntelliJ (Ultimate 2020.2.3). I create a new Scala sbt project using the IntelliJ wizard (file > new > project > scala / sbt) and add a new dependancy to the buid.sbt file but when I try to import it into one of my class files, IntelliJ will not compile my project due to a dependancy issue.
The sbt tool window picks up the external dependancies but my project "external dependancies" doesn't contain the library at all, even after I refresh the project. Also, my build.sbt file has a bunch of errors in it like it's not being recognised properly by IntelliJ but I've installed the Scala plugin so I don't know what else I could do?
Here you can see that I've added the org.slf4j dependancy into my build.sbt; It's picked up by the sbt tool window (on the right) but not by my project (on the left)
When I hover over the libraryDependencies in the build.sbt file it doesn't seem to recognise the sbt syntax:
I cannot import the library into my class file and the project wont build:
I'm new to Scala and I'm simply trying to create a basic hello world project but I can't seem to get past this frustrating issue.
You can try first to create an SBT project manually in some directory. build.sbt alone would be enough.
Then run sbt in that directory to see that SBT shell works properly. Try some commands like sbt compile, sbt run with some helloworld app. When you create helloworld app mind the directory structure where you put it, i.e.: src/main/scala/HelloWorld.scala.
If all that works go to IntelliJ and import/open project from there - select build.sbt.
When you create or import SBT project from IntelliJ it takes a while to bootstrap everything and download compiler, etc. Just leave it until it's done. Same goes for first time compilation when the compiler needs to be compiled :).
To setup a sample project you can issue these shell commands:
mkdir untitled
cd untitled/
echo 'name := "untitled"
version := "0.1"
scalaVersion := "2.13.3"
libraryDependencies ++= Seq(
"org.slf4j" % "slf4j-simple" % "1.7.26",
)
' > build.sbt
mkdir -p src/main/scala/
echo 'object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
' > src/main/scala/HelloWorld.scala
sbt run
If there are not issues with these steps then import build.sbt into IntelliJ.
I was finally able to get past this issue. I'm not 100% sure what solved it in the end unfortunately but disabling a bunch of plugins I wasn't using seemed to fix the issue for me.
I suspect it may have been the Gradle plugin since I saw some errors in the idea.log file but after re-enabling the Gradle plugin to test everything is still working so not sure.

SBT Plugin in an unmanaged jar file

The requirement: an SBT plugin code is in an unmanaged jar, for example in lib/unmanaged-sbt-plugin-0.0.1.jar.
I was expecting the jar file would be picked up by SBT automatically and the plugin would work out-of-the-box, i.e.: the tasks would be accessible from SBT command line, but that is not the case.
The jar file has the sbt/sbt.autoplugins file in it and the plugin works if pulled from a remote repo into the local one and imported via addSbtPlugin(...). Please note I cannot do that - it's a requirement to get it to load from the lib/unmanaged-sbt-plugin-0.0.1.jar and not from the local/remote repo.
Putting the following line in the build.sbt doesn't make the plugin work (there's not error either):
unmanagedJars in Compile += file("lib/unmanaged-sbt-plugin-0.0.1.jar")
The implementation of addSbtPlugin(...) is simply (according to http://www.scala-sbt.org/0.12.2/docs/Getting-Started/Using-Plugins.html):
def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =
libraryDependencies <+= (sbtBinaryVersion in update, scalaBinaryVersion in update)
{ (sbtV, scalaV) => sbtPluginExtra(dependency, sbtV, scalaV) }
I'm wondering if the above info can be used to resolve my issue?
Thank you in advance!
So you can specify an explicit URL for library dependencies (ModuleID):
addSbtPlugin("org.my-org" % "unmanaged-sbt-plugin" % "0.0.1"
from "file:///./lib/unmanaged-sbt-plugin-0.0.1.jar")
Have been struggling to get this to work.
Could not get it to work with proposed solution using from "file://.." (using sbt 1.0.4).
Got it to work by putting the plugin in project/lib folder and adding all the plugin dependencies to plugins.sbt using libraryDependencies ++= Seq(..) like in build.sbt. You can find the plugin dependencies by looking at the plugin pom file, usually in .ivy2/local/<org>/<pluginname>/poms folder.

IntelliJ Idea sbt managed source file

I am using sbt-buildinfo plugin that generates Scala source from my build definitions, allowing me to reference project name, version, etc. from my Scala code.
It does this by generating a file BuiltInfo.scala with the following contents:
package hello
case object BuildInfo {
val name = "helloworld"
val version = "0.1-SNAPSHOT"
val scalaVersion = "2.10.3"
val sbtVersion = "0.13.2"
}
in
target/scala-2.10/src_managed/main/sbt-buildinfo/BuildInfo.scala.
Everything compiles and I can reference those vals.
However, IntelliJ Idea doesn't recognize BuildInfo.scala as a managed source file, so that it would stop showing me errors. Any idea how to do that?
Thanks!
Grega, are you working in a Play Framework project? Or do you have any SBT sub-projects? I don't have a complete answer, but may have a lead.
This same problem shows up in my IDEA projects when using sbt-buildinfo and sbt-scalaxb. Frustratingly, it has worked intermittently—usually after lots of tinkering around, but inexplicably stops.
I wound up digging a bit deeper (and eventually issued bug report SCL-7182 to JetBrains), and noticed the root cause was having a sub-project. When present, IDEA doesn't correctly identify src_managed for the root project, but does for the sub-project.
A work-around, for now, is to manually add the correct src_managed directory to your project's sources using the Project Structure dialog.
For reference, I'm running version 0.38.437 of the Scala plugin on IntelliJ IDEA 13.1.3.

IntelliJ Play2 and Scala plugins are not compatible. Makes IntelliJ 12 no longer work as expected

I upgraded my IntelliJ(12.1.4) to the new Play 2.0 Support(0.5.54) plugin and two things happened:
IntelliJ no longer recompiles my .scala classes, this meaning that if
I e.g change the signature of a method from def something(s1:
String) = {} to def something(s1: String, s2: String) = {} I get an
error that ) is expected after the first param. I run the app from
the terminal with play debug ~run and there the app recompiles
without a problem.
The scala.html are not evaluated properly and I get a lot of syntax
errors. The color encoding is also wrong. I tried to change the
Scala plugin to the nightly build(0.10.281) as suggested in the
comments but it still doesn't work.
This is crazy bad since it makes working with the IntelliJ painful and counterproductive.
There is a bug reported: http://youtrack.jetbrains.com/issue/SCL-5749 but what
should I do in the meantime? Anybody solved this issue?
For me play2.0 version 0.2.49 with scala version 0.10.279 does the trick.
With the other versions I ether get bugs, or my IDE just doesn't work correct.
link to play plugin: http://plugins.jetbrains.com/plugin/download?pr=&updateId=13272
link to scala plugin: http://plugins.jetbrains.com/plugin/download?pr=&updateId=13504
instructions:
1 download the .zip (do not extract)
2 make sure there are no play or scala plugins in your IDE folder (C:\Program Files (x86)\JetBrains\IntelliJ IDEA 12.1.2\plugins)
3 op the IDE and open the plugin menu. (file -> settings... -> plugins
4 click the button "install from disk" and select the play zip file and the scala zip file. (you don't need to disable the play and scala plugin in the plugin list, they get swapped after the IDE restart
5 restart your IDE
6(optional) report back here if it worked or not
Use the IntelliJ sbt plugin and compile your classes from sbt with "~compile". You can start play with "container:start".
Here is my own Build.scala file I run from within IntelliJ:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "Blade_Night_App"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
// Add your project dependencies here,
jdbc,
anorm
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
)
}
And here the plugins.sbt:
// Comment to get more information during initialization
logLevel := Level.Warn
// The Typesafe repository
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
// Use the Play sbt plugin for Play projects
addSbtPlugin("play" % "sbt-plugin" % "2.1.0")
Additional I have a Debug configuration for a Scala application with
Main class: xsbt.boot.Boot
VM-Options: -Dfile.encoding=UTF8 -Dsbt.boot.properties=file:///.../play-2.1-RC4/framework/sbt/sbt.boot.properties -Dplay.version=2.1-RC4 -Dsbt.ivy.home=.../play-2.1-RC4\repository -Dplay.home=.../play-2.1-RC4/framework -Xms128M -Xmx512M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M
Program argument: run
This replaces the Play plugin completely for me :-)
The problem here is that there is a massive incompatibility with the newer Scala plugins and the Play plugin in general. To get it to work, you have to use Scala plugin version 0.7.264 (that is the specific version number the support person gave to me anyway). I had this issue as well and, to be safe, I also reverted back to Play plugin version 0.2.26. Everything works as it did before now.
To go back to the previous version, you have to download the ZIP archive from the JetBrains plugin site and choose "install from disk" in IntelliJ IDEA. Here is the link to get the older Scala plugin version you need: http://plugins.jetbrains.com/plugin/?id=1347
This is a big compatibility issue and apparently JetBrains is aware of it, but only by contacting their help desk did I find out how to fix it for now until a more permanent solution comes along.
Good news everyone: Play 2.0 plugin and Scala plugin versions are synchronized again! For IDEA12 there are 0.13.286 versions (of both) now. After updating I see some new highlighting errors, but at least they work, and there are no error messages about incompatibility!
So, it seems like it is safe now to update to the latest version of both through the built-in mechanism.
From now the build process of Scala and Play 2.0 plugins is common, so Play 2.0 plugin has the same build number.
— this also gives some hopes for not repeating the same problem in future.

How to declare a project dependency in SBT 0.10?

I use SBT 0.10.0.
How do I download/retrieve project dependencies?
For example, for slf4s only this line is mentioned:
val slf4s = "com.weiglewilczek.slf4s" %% "slf4s" % "1.0.6
Where do I need to put this line, and how do I get the library?
I presume you're using SBT 0.10.0, because earlier versions will put your deps in lib_managed automatically.
In build.sbt, put the following line:
retrieveManaged := true
You create a project/build subdirectory in your project and put a scala file with the above content there.
Then when you start sbt from your project root directory the
update
command will retrieve your dependencies.
Note that it will only analyse your project configuration once by default. If you change it, you have to call reload
UPDATE:
let the project class extend DefaultProject:
class SomeProjectName(info: ProjectInfo) extends DefaultProject(info)
I don't know which version of sbt you are using.
For 0.10, Daniel C. Sobral made a blog post about creation of an sbt project:
dcsobral-project-creation-guide
Maybe this helps.