What is the issue with this sbt file? - scala

When I import a SBT project into intelliJ, the build.sbt file is showing lot of errors as shown in the following screenshot. Wondering what might be the issue
IDEA Version 13.1.4
I also see the following
The following source roots are outside of the corresponding base directories:
C:\Users\p0c\Downloads\recfun\src\main\resources
C:\Users\p0c\Downloads\recfun\src\test\java
C:\Users\p0c\Downloads\recfun\src\test\scala
C:\Users\p0c\Downloads\recfun\src\test\resources
These source roots cannot be included in the IDEA project model. Please consider using shared SBT projects instead of shared source roots.

I think the question perhaps does not provide all the required information to answer conclusively, but I'll give it a spin anyways -
Since sbt runs correctly when invoked from the shell, we know the sbt file is fine. I use Idea for my Scala and sbt projects and I am sure the Idea sbt support works very well, but! Idea is far more restrictive than sbt when it comes to project structure. It is really easy to create a valid sbt project structure that Idea can't support very well.
Given that the source roots error indicates that the recfun/src folder is not in the project folder, it seems clear that this error is not emitted during the processing of recfun/build.sbt. The screenshot shows you have at least three different sbt files, progfun-recfun, submission and scala-recfun. Since Idea will also create projects like submission-build, and you have an assignment-build project there, something is probably broken in the project structure, not from the sbt viewpoint - there you're fine, you can build - but from the Idea viewpoint, which is more restrictive.
My suggestion to resolve this would be to change your project structure as follows. First, have a top level project with a build.sbt. Then create a sub-project for each src folder you want. Do not put a src folder in your top level project. Each sub-project needs a build.sbt as well.
Second, make sure the sub-projects build correctly with sbt when run from the shell. Arrange the sub-project build.sbt files with the proper dependencies, using this syntax:
lazy val a = ProjectRef(file("../a"), "a")
lazy val b = ProjectRef(file("../b"), "b")
lazy val root = Project(id = "c", base = file(".")) dependsOn (a, b)
(This example has three sister projects a, b and c, where c depends on a and b. The three projects are placed in directories with the same name, within the root directory. The code snippet is from the build file for c.)
Third, arrange your top level build.sbt to aggregate the sub-projects, using this syntax in the top level build.sbt:
lazy val a = ProjectRef(file("a"), "a")
lazy val b = ProjectRef(file("b"), "b")
lazy val c = ProjectRef(file("c"), "c")
lazy val root = (project in file(".")).
aggregate(a, b, c)
Building this top level project will build each of the sub-projects a, b and c, and the dependencies established in the sub-project build files will ensure they are built in the right order.
Fourth, import the top level project into Idea, and all should be well.
You can get fancy with the file structure if you want, because the project references use relative paths, but it's usually nice to at least start simple.
I had a lot of frustration with sbt and Idea at the start, I hope this helps :)

Related

How to import unmanaged dependencies into code

I'm trying to use sbt to pull down an existing github project and then (obviously) use it in my code. My abbreviated build.sbt is shown below:
lazy val myProjInGit = RootProject(
uri("git://github.com/me/sheet-ref.git#master"))
lazy val root = (project in file("."))
.dependsOn(myProjInGit)
.settings(
name := "MainProj",
)
libraryDependencies ++= Seq( /*other stuff... */)
This is probably a basic one, but how should I then be importing this into code? Could I use, say, import myProjInGit.SampleObject.sampleFunction in my Main.scala? I can see a disconcerting lack of info on SO about this topic so I'm not sure that I'm not barking up completely the wrong tree. Thanks in advance for any help.
EDIT: some further details here. The project I am trying to import is just a library, so it only contains a package object. To try to debug things a little, I'm trying to import it as a ProjectRef, rather than a RootProject. I've discovered the projects sbt command, and if I run it on the project I'm trying to import (not the main one), it gives me:
sbt:SheetRef> projects
[info] In file:/data/va-projects/sheet-ref/
[info] * SheetRef
So... it seems that external project is called SheetRef. If I try to import SheetRef using
lazy val sheetRef = ProjectRef(
uri("git://github.com/me/sheet-ref.git#master"), "SheetRef")
then I get an sbt error:
[error] No project 'SheetRef' in 'git://github.com/me/sheet-r
ef.git#master'.
[error] Valid project IDs: root
Which feels unintuitive. I can import it as root, but then I seem to be unable to access it from my code - if it requires an import statement, it's not obvious to me what it should be.
The dependency has to be an SBT project, so SBT knows how to build it. If it is, then yes, you access it just like any other dependency in your code, because it's added to the classpath (after being built) just like any other dependency.
Which feels unintuitive. I can import it as root, but then I seem to be unable to access it from my code - if it requires an import statement, it's not obvious to me what it should be.
The thing is, it doesn't matter how you add the dependency; it could be a normal library dependency, an unmanaged dependency, a source dependency, etc. Those are SBT concepts, which have no meaning to the Scala compiler.
So the import statement can't depend on project names, jar names or anything like that. In fact, it's the same as if you just put those files into your own project.
Is there someone that made such a thing work? I am trying the same, and somehow manage to get the git project imported but I have no idea how to access the imported scala components.

The meaning of _root_ in sbt

I have two separate Scala projects. In both projects, the build.sbt has the line:
lazy val V = _root_.scalafix.sbt.BuildInfo
The two projects contain several projects so both build.sbt files are multi-project builds. In my research, I came across the idea of a root project and I think _root_ in the above value denotes the root project.
My problem is that in one of the projects, sbt cannot resolve the symbol scalafix in lazy val V = _root_.scalafix.sbt.BuildInfo. When I search scalafix.sbt.BuildInfo in this project, I can find the related jar but sbt somehow misses it. The two projects in so far as I can tell are almost identical but one resolves scalafix while the other does not.
For both projects, the jar seems to be located at the below directory in my Mac:
/Users/soft/.ivy2/cache/scala_2.12/sbt_1.0/ch.epfl.scala/sbt-scalafix/jars/sbt-scalafix-0.6.0-M19.jar!/scalafix/sbt
What is _root_ and how can I help sbt resolve scalafix?
I think root in the above value denotes the root project.
No, this is not true.
All sbt files are scala code and _root_ has the same meaning as _root_ in scala. Thus the answer is the same as in What is the root package in Scala.
The two projects in so far as I can tell are almost identical but one resolves scalafix while the other does not.
The problem is most probably the missing sclafix plugin.
Check that the plugin is enabled in project/plugins.sbt with line
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.1")

IntelliJ IDEA - sbt plugin - 'Expression type Def.Setting[...] must conform DslEntry in sbt file'

I looked for similar questions, I found this:
Expression type DslEntry must conform to Def.SettingsDefinition in SBT file at line enablePlugins(JavaServerAppPackaging)
My issue is similar, but happens in every row.
When I try to run, it compiles and runs successfully.
When I click "Import Project", the yellow notification does not disapear, but the project reloads successfully.
If I rewrite any row as, for example, val _ = scalaVersion := "2.12.4", the error disapear, but it looks awful.
I had the same issue. This solution worked me everytime.
1. Click on sbt tab of right side in IntelliJ Idea
2. Click on Refresh symbol
It will revalidate the Local cache and Gradle dependencies.
That's it.
I closed and removed the project in IntelliJ, then, in my project folder, I removed the subfolders project/, target/ and .idea/. Then there were remaining only build.sbt and src/. Afterwards, in IntelliJ, I did: File -> New -> Project from existing sources -> import project from external model -> sbt.
This procedure has generated a new .idea Project file.
Expression type Def.Setting[String] must conform to DslEntry in SBT file has been gone now.
Hope this helps.
UPDATE 2018-11-17:
When shuffling with modules and projects in IntellIJ SBT, try replacing
lazy val root = (project in file("."))
with an always distinguished
lazy val root = Project(id="module_xyz", base = file("."))
In my case, the problem was solved this way! It occured from having multiple (project in file(".")) in different modules/build.sbt files belonging to the same IntelliJ SBT project. It seems to me that there can only be one (project in file(".")) in an IntelliJ SBT multi module project. So having many different Project(id="module_xyz", base = file(".")) can solve this.
You can also try cutting and pasting everything in your build.sbt file to a word doc, importing your changes, and then pasting it back into the build.sbt file.
I simply installed the newest sbt version on my system and updated project/build.properties so it contains the new version number. This solved the issue for me. You might have to trigger a refresh in IntelliJ manually.

sbt : Is there a better way of structuring large build.sbt files

Problem description: large sbt file
Our current build.sbt spanns 250+ lines.
We have two problems:
readability
current approach grouping of data and comments:
// Plugins ///////////////////////////////////////////////////
enablePlugins(DockerPlugin)
// basic configuration : projects ///////////////////////////
name := """projectName"""
lazy val projectName =
(project in file(".")).....
logic reuse
We have some configuration logic we would like to share between different projects.
Question
Is there a way to include other *.sbt files?
Or do you have a suggestion how to solve this problem without resorting to write a sbt plugin?
Is there a way to include other *.sbt files?
Yes, you can simply put parts of your build.sbt file into other *.sbt files within your project root. SBT picks up all *.sbt files and merges them together, as there was only a single large file.
One thing you can do is to factor out parts of your build info into scala files in the project directory.
E.g. in our build we have a file Dependencies.scala in the project directory, which contains all dependencies of the various projects in one place:
object Dependencies {
val akka_actor = "com.typesafe.akka" %% "akka-actor" % "2.3.13"
// ...
}
This can then be imported from the build.sbt:
import Dependencies._
lazy val foo = Project(...) dependsOn (akka_actor, ...)
You can also put tasks and commands into objects in the project directory.
Update: One thing I often do when looking for inspiration about how to organize a build is to look at the build of complex, high-profile scala projects such as akka. As you can see, they have moved a lot of logic into scala files in the project directory. The build itself is defined in AkkaBuild.scala.

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.