How to apply class exclusions to Scalac warnings options? - scala

We have problems when using Scalac -Xfatal-warnings in the following cases:
Implicit vals used by macros internally
Internal vals that macros auto-generate
In both cases, we see Scalac failing to compile because it detects some values are not used, while we know they are (simply, when we remove them, the code doesn't compile anymore)
Although the two might be symptoms of the same problem in Scalac, they boil down to the same issue for us: we need to disable the -Ywarn-unused in Scala 2.11.12
Is there a way to exclude specific class files so they won't be affected by the compiler flag?

As far as I know there is no way of disabling scalac flag for just one file (if you compile your whole project at once by e.g sbt). You can extract class into separate module with different compile flags.
In case of implicit vals used internally in macros, personally I use -Ywarn-macros:after flag, which make these implicits used in macro count as used. (Talking about Scala 2.12.4).

Related

How to generate top-level class/object with scala macro

As we know, it is easy to create an inner class in some methods with scala macro.
But I'd like to know is it possible to generate a top level class/object?
If the answer is yes, then how to avoid generate the same class twice?
my scala version is 2.11
Top-level expansions must retain the number of annottees, their flavors and their names, with the only exception that a class might expand into a same-named class plus a same-named module, in which case they automatically become companions as per previous rule.
https://docs.scala-lang.org/overviews/macros/annotations.html
So you can transform top-level
#annot
class A
into
class A
object A
or
#annot
object A
into
class A
object A
Also there existed c.introduceTopLevel but it was removed.
Context.introduceTopLevel. The Context.introduceTopLevel API, which used to be available in early milestone builds of Scala 2.11.0 as a stepping stone towards type macros, was removed from the final release, because type macros were rejected for including in Scala and discontinued in macro paradise.
https://docs.scala-lang.org/overviews/macros/changelog211.html
Scala Macro: Define Top Level Object
introduceTopLevel has provided a long-requested functionality of generating definitions that can be used outside macro expansions. However, metaprogrammers have
quickly discovered that introduceTopLevel is dangerous. Top-level scope is a resource shared between the typechecker and user metaprograms, so mutating it with
introduceTopLevel can lead to compilation order problems. For example, if one file
in a compilation run relies on definitions created by a macro expansion performed in
another file, compiling the former before the latter may lead to unexpected compilation
errors.
https://infoscience.epfl.ch/record/226166/files/EPFL_TH7159.pdf (section 5.2.3 Conclusion)
If the companion you want to generate already exists then the companion you return in macro annotation's macroTransform will replace the original. You don't need to beware that there will be two "companions", compiler will watch that. But surely normally you match if that's the case (whether there is only annottee or annottee + companion).

What does `<<=` mean in SBT?

I see this <<= symbol in lot of SBT code, but I don't what it does.
I tried googling for this symbol as well but I did not get any answers.
Can you please point me to some documentation or an example which clearly explains what does this symbol mean and what does it do?
Further to pfn's comment, this is described in the 0.12 docs under More Kinds of Settings. I guess it was dropped from the 0.13 docs because the same behaviour can now be defined in terms of :=.
Oh, the deep explanation is quite complicated.
Basically, the signature is:
def <<= (app: Initialize[Task[S]]): Setting[Task[S]] = macro std.TaskMacro.itaskAssignPosition[S]
So it involves this macro:
/* Implementations of <<= macro variations for tasks and settings. These just get the source position of the call site.*/
def itaskAssignPosition[T: c.WeakTypeTag](c: Context)(app: c.Expr[Initialize[Task[T]]]): c.Expr[Setting[Task[T]]] =
settingAssignPosition(c)(app)
I already used this kind of operator when dealing with AspectJ compilation:
products in Compile <<= products in Aspectj
Basically, it means: base the code source on the AspectJ source files (generated with a plugin), not the classical ones.
I interpret it as a kind of "replaceAll/erase":
Replace bunch of files to compile by the files involving AspectJ annotations.

shapeless breaks sbt incremental compilation

I have a scala project which I build using sbt 13.5.
Since I implemented a module using shapeless, whenever sbt tries to incrementally compile the project it fails in resolving the required implicits:
[...] could not find implicit value for parameter mapper [...]
[...] could not find implicit value for parameter folder [...]
and so on.
sbt clean and sbt compile solves the issue, but the project is fairly big and this is painfully slowing down the compilation times and my productivity in turn, as fresh build can take several minutes.
Any idea of what's going on here?
some extra info
So, after some more thinking I made some hypothesis. The issue occurs when using shapeless records, and by looking at the generated files, I think it could be an issue with the macro that generates the singleton type for each record key.
My module takes an HList of ColParser[T, K] declared as:
sealed trait ColParser[T, K] {
val columnL Witness.Aux[K]
}
So the compiler generates a Witness for each ColParser using a macro, and I'm afraid sbt loses track of the generated macros when deciding what to recompile, but this is just a sketchy hypothesis.
As a matter of fact, whenever I change something in the code that invokes my module (e.g. I add/remove a ColParser from the HList), I get the above error.
Forcing the recompilation of the module (by deleting the generated .class) fixes the issue.

Showing inferred types of Scala expressions

How can I see the types inferred by the Scala compiler for expressions etc.? I have some code with complicated type inference and implicit conversions, and it's hard to see what's going on just by reading the code.
I've tried adding
scalacOptions in Compile += "-Xprint-types"
in build.sbt, but this has no effect.
Using scalac directly isn't very appealing because I have lots of dependencies.
I use the Eclipse Scala plugin and ENSIME to write code, and SBT to build.
It needs to be
scalacOptions in Compile ++= Seq("-Xprint-types", "-Xprint:typer")
instead.
Unfortunately the output isn't very readable. :(
This exact feature has been added in Eclipse Scala IDE 3.0!
Select any portion of code and press Ctrl-Shift-W T (replacing Ctrl by Cmd on Mac) to see the inferred type.
Hoist the expression to a non-local def or val, without an explicit type - then it will appear in the Outline view in Eclipse, with an inferred type assigned.
However, this isn't an ideal solution because it requires some work, and it can't be used when recursion is involved.

Is there somewhere a guide to SBT for non-Scala programmers?

Someday, I'd like to learn Scala. What I see about the language from people who like it is very encouraging.
Today, though, is not that day. Today, I'd just like to make some changes to my team's build file. Unfortunately, this build file was put together with SBT, and is nearly incomprehensible.
My main issue is that it appears to me that SBT introduces some huge collection of new operators that do things with strings and lists to create some sort of sbt object. For example, in sbt:
"args4j" % "args4j" % "2.0.12"
Apparently is actually defined; however, I can't even tell what type it is at the scala repl, since at the repl I get the sensible error:
scala> val tstcrap = "args4j" % "args4j" % "2.0.12"
<console>:6: error: value % is not a member of java.lang.String
val tstcrap = "args4j" % "args4j" % "2.0.12"
I get this error even after setting up the classpath to include the sbt-launch.jar file and doing import sbt._.
Likewise, I'm dealing with stuff like this:
val jarSources = (descendents(classesOutput ##, "*") ---
assemblyExclude(classesOutput ##))
What's that ## operator, what's that --- doing, and more importantly what is the type of this expression? Are all these new operators documented somewhere, and is there some way to get a scala repl that's using the same language as is used in the sbt build files?
Looking at this sbt file reminds me of trying to decipher perl without ever reading any of the relevant man pages. (Not a recommended activity)
Update: After looking at the links in the answer below, and looking at other questions and answers tagged sbt, I've come across the major piece of scala knowledge that I was missing: scala allows one to define implicit conversions that will be invoked before methods are resolved. In this case, sbt defines inside the ManagedProject trait, an implicit conversion from String to the private class sbt.GroupID, so that
"a" % "b"
Is really something like
(new GroupID("a")) % "b"
I imagine the resolution order and other rules around implicit conversions must get very complicated; it almost reminds me of the nightmares you can introduce in C++ with operator overloading when done through non-member functions.
Since an SBT build file is a full-fledged Scala source file and relies on some libraries provided by SBT itself, it's difficult to cover SBT well without relying on some familiarity with Scala. I'm not aware of such a guide.
For the specific questions you raise, I think these wiki pages will help:
% operator for strings: http://code.google.com/p/simple-build-tool/wiki/LibraryManagement
## and --- operators: http://code.google.com/p/simple-build-tool/wiki/Paths
If you want to get a Scala REPL running with the SBT libraries available, try this:
$ sbt console-project
Some other useful commands are listed at http://code.google.com/p/simple-build-tool/wiki/RunningSbt .
Update 2016 (5 years later).
This is not a complete guide, but the article "Sbt heiroglyphs and multi-projects explained" from Divan Visagie can help starting to use sbt.
Plus, the sbt documentation is quite complete nowadays, and covers multiple projects in a single build.
The '---' operator is described in the PathFinder (since the 0.2 version).