What are IntelliJ IDEA sbt imported 'xxx-build' modules for? - scala

When importing a multi-project build.sbt from intelliJ IDEA 2016.1.2 using the native sbt import function, it prompts me which modules I would like to include. The list includes the subprojects/subdirectories in the directory structure I would expect e.g. 'aaa', 'bbb', 'ccc', but then it also offers to import 'aaa-build', 'bbb-build', 'ccc-build', which I have not created.
Ignoring/deselecting the '-build' modules doesn't appear to have any adverse effects.
Can somebody tell me what the purpose of those extra modules is? Just curious.
The directory structure looks something like this:
root/bulid.sbt
root/project
root/aaa
root/aaa/build.sbt
root/aaa/src/main/scala
root/aaa/src/test/scala
root/bbb
root/bbb/build.sbt
...

A newer to scala,if something gets wrong with my answer, I'll improve it.
Those *-build ,they are project subfold in your projects,when you compile these projects with sbt, sbt will read it's peoperties and plugins from peoject fold. It's just like your config which has been compiled.

Related

How to make VS code able to lookup code in subproject directory for autocompletion?

I have project structure
-core_data
-core_domain
-core_ui
-core_launcher
The dependency of these 4 projects is
core_launcher -> core_ui -> core_domain -> core_data
4 projects are located in the same directory and I include one to another via pubspec.yaml file (for example core_launcher/pubspec.yaml):
dependencies:
flutter:
sdk: flutter
core_ui:
path: ../core_ui
The same thing I do with all projects to make dependency hierarchy.
The problem is that I can import all files from core_ui subproject when I'm currently editing some file in core_launcher but VSCode doesn't see any classes from his parents
(core_domain & core_data).
However, I can input import 'blah-blah-blah manually and VSCode see this class and import works well, but I can't do that with hit Alt+Enter that I do for fast-import.
So, I'm wondering why autocomplete is not working for inherited libraries.
Somebody had the same issue?
Code completion will only show classes from your direct dependencies. There are two possible reasons for this:
Relying on transitive dependencies is not a good idea, because it's possible that your dependencies will remove or change their dependencies and not consider that a breaking change.
If code completion listed all classes from all transitive dependencies the code completion list would be huge and include classes from packages you do not recognise (because they are just other packages dependencies). This would be a bad user experience and make it easy to accidentally rely on packages that are not listed in your pubspec.yaml.
The fix is to explicitly list core_domain and core_data in your pubspec.yaml too, because if your project is using classes from them, then they are dependencies.

GWT module xml source element to specify single class

I have a GWT application (FooGwtApp) and a library module (FooLib) used as a dependency in FooGwtApp. The package structure of FooLib looks like this:
packageFoo.ImportantClass
packageFoo.UnimportantClass
packageBar.OtherClass
I want ImportantClass (and only ImportantClass) to be compiled to JS by the GWT compiler. Moving ImportantClass to another package is not an option.
I created ImportantClass.gwt.xml within packageFoo with the following content:
<module>
<inherits name="com.google.gwt.user.User"/>
<source path="" includes="**/ImportantClass*"/>
</module>
Next I put an inherited reference to the ImportantClass module definition in FooGwtApp.gwt.xml (this seems to work: the IDE recognizes it, and is able to parse the reference to ImportantClass.gwt.xml).
Now If I put references to ImportantClass into FooGwtApp's client code, the GWT compiler fails, because it does not find ImportantClass on the source path:
No source code is available for type packageFoo.ImportantClass; did you forget to inherit a required module?
I likely messed up sommething in the source path / includes attribute in ImportantClass.gwt.xml - either defining the current package as root package with path="" is not a valid notation or something's wrong with the includes attribute. Or both. Or neither.
Can you give me a clue about where it all went wrong?
It turns out the problem was not in ImportantClass.gwt.xml, but in other Maven related stuff:
ImportantClass.gwt.xml should be placed under src/main/resources/packageFoo, not src/main/java/packageFoo, otherwise it won't be packaged into the binary jar.
GWT compiler compiles from Java source to Javascript source. This means we don't just need ImportantClass.class in FooLib.jar, but also its source. Best solution for this is to use maven-source-plugin in FooLib's pom.xml and also to import the FooLib dependency into FooGwtApp with sources classifier.
On the latter topic, see the following SO answers:
Maven: Distribute source code with with jar-with-dependencies
How to properly include Java sources in Maven?
After fixing the above problems, the source path declaration present in the question works.

How do I exclude package from publishing with sbt?

I want to publish a library, which has some usage examples in runnable classes. When I call sbt run , it finds them and asks me, which of the main classes found I want, and then launches it. That's neat, I'd like this behaviour to stay. But those examples complicate my Android build ( more proguard configs ), so I don't want them in published artefacts.
For now, I totally exclude them, putting this into build.sbt :
excludeFilter in Compile ~= { _ ||
new FileFilter {
def accept(f: File) = f.getPath.containsSlice("/examples/")
} }
then, when I run sbt publish-local, I get jars without examples, but then one can't get the library source and see how it works, with just typing sbt run. How can I exclude examples package only from publishing, but let it still be compiled for local runs?
I'd recommend splitting examples into another subproject instead.

How to "include" a common sbt snippet in another sbt file

Let's say I have a common snippet of statements that I find myself having in many projects. Is there a way to "include" a shared sbt snippet inside another (without writing a plugin)?
e.g.
Snippet (common-mapping.sbt)
mappings in Universal ++= {
for (f <- (baseDirectory.value ** "*-prod.conf").get) yield {
f -> f.getName.replaceAll( """(\w+)-prod\.conf""", "$1.conf")
}
}.toSeq
Project1's build.sbt
...
include("path/to/common-mapping.sbt")
...
Project2's (build.sbt)
...
include("path/to/common-mapping.sbt")
...
Is there a way to do so? or do I need to write a plugin?
p.s. the projects are not necessarily part of the same root project
Plugin is designed to solve this problem, so it's the way to go. Plugins are basically a JAR library that are designed to be used for the builds, and not much else. Also take a look at auto plugins that'll be out in 0.13.5.

Why does the scala-ide not allow multiple package definitions at the top of a file?

In scala it is common practice to stack package statements to allow shorter imports, but when I load a file using stacked packages into the scala ide and I attempt to use an import starting with the same organization I get a compiler error from what appears to be the presentation compiler. The code compiles fine in sbt outside of the IDE.
An example code snippet is as follows:
package com.coltfred
package util
package time
import com.github.nscala_time.time.Imports._
On the import I get the error object github is not a member of package com.coltfred.util.com.
If I move the import to a single line the error will go away, but we've used this practice frequently in our code base so changing them all to be single line package statements would be a pain.
Why is this happening and is there anything I can do to fix it?
Edit:
I used the eclipse-sbt plugin to generate the eclipse project file for this. The directory structure is what it should be and all of the dependencies are in the classpath.
Edit 2:
It turns out there was a file in the test tree of the util package (which should have been in the same package), but had a duplicate package statement at the top. I didn't check the test tree because it shouldn't affect the compilation of the main tree, but apparently I was wrong.
Not sure why the Scala IDE is not liking this, but you can force the import to start at the top level using _root_:
import _root_.com.github.nscala_time.time.Imports._
See if that avoids irritating the IDE.
This is a common annoyance that annoyed paulp into an attempt to fix it. His idea was that a dir that doesn't contribute class files shouldn't be taken as a package. If you can take util as scala.util, you should do so in preference to foo.util where that util is empty.
The util dir is the usual suspect, because who doesn't have a util dir lying around, and in particular, ./util?
apm#mara:~/tmp/coltfred$ mkdir -p com/coltfred/util/time
apm#mara:~/tmp/coltfred$ mkdir -p com/coltfred/util/com
apm#mara:~/tmp/coltfred$ vi com/coltfred/util/time/test.scala
apm#mara:~/tmp/coltfred$ scalac com/coltfred/util/time/test.scala
./com/coltfred/util/time/test.scala:5: error: object github is not a member of package com.coltfred.util.com
import com.github.nscala_time.time._
^
one error found
apm#mara:~/tmp/coltfred$ cat com/coltfred/util/time/test.scala
package com.coltfred
package util
package time
import com.github.nscala_time.time._
class Test
apm#mara:~/tmp/coltfred$
To debug, find out where the offending package is getting loaded from.