Macros support inside IntelliJ idea - scala

I am reading this tutorial on scala macro code generation
http://www.michaelpollmeier.com/2016/12/01/scalameta-code-generation-tutorial
Based on this I wrote my macro class
class Foo extends StaticAnnotation {
inline def apply(defn: Any) : Any = meta {
val q"..$mods class $tName (..$params) extends $template" = defn
q"""
..$mods class $tName(..$params) {
def sayMyName() : String = "Hello"
}
"""
}
}
Now I decorated my classes with the new attribute
package com.abhi
object Models {
#Foo case class Bar(...)
#Foo case class Baz(...)
}
If I write the following two lines
val x = Bar("test")
println(x.sayMyName())
and then compile using sbt sbt macros/compile root/compile and sbt run the code runs fine and I see that Hello is printed.
However the same code does not compile inside of intelliJ idea. (Ultimate 2016.3.3)

Related

Scala 2.10 "No implicit view available" error on type parameter that asks for a view

I have reduced this example from something encountered in a much larger project; the fundamental issue seems to be that Scala 2.10 has weird or possibly broken handling of view constraints:
trait Nameish {
def name: String
}
abstract class Namer[A <% Nameish](e: Class[A]) {
def doNameThing(x: A) = println("argument is named " + x.name)
}
class SubNamer[A <% Nameish](e: Class[A]) extends Namer(e) {
}
object TestViews extends App {
import scala.language.implicitConversions
implicit def nameStr(x: String): Nameish = new StringNamer(x);
class StringNamer(x: String) extends Nameish {
def name = x
}
println(new SubNamer(classOf[String]).doNameThing("foo"))
}
When I try to compile this, in scala 2.10 I get the errors:
TestViews.scala:8: error: No implicit view available from A => Nameish.
class SubNamer[A <% Nameish](e: Class[A]) extends Namer(e) {
^
TestViews.scala:18: error: value doNameThing is not a member of SubNamer[String]
println(new SubNamer(classOf[String]).doNameThing("foo"))
^
two errors found
Note that Scala 2.11 is fine with this code.
Unfortunately, re-tooling this code to a newer scala version would make this task explode in size. I need to find a way to make the existing scala accept a class hierarchy with a type parameter that has a view constraint.
Another attempt at a way around this has uncovered a different scala-2.10-only error case:
trait Nameish {
def name: String
}
abstract class Namer[A](e: Class[A])(implicit view: A => Nameish) {
def doNameThing(x: A) = println("argument is named " + x.name)
}
class SubNamer[A](e: Class[A])(implicit view: A => Nameish) extends Namer(e)(view) {
}
object TestViews extends App {
import scala.language.implicitConversions
implicit def nameStr(x: String): Nameish = new StringNamer(x);
class StringNamer(x: String) extends Nameish {
def name = x
}
println(new SubNamer(classOf[String]).doNameThing("foo"))
}
This is just replacing the view constraints with implicit arguments.
With this code, it again compiles just fine with Scala 2.11, but on Scala 2.10:
TestViews.scala:8: error: `implicit' modifier cannot be used for top-level objects
class SubNamer[A](e: Class[A])(implicit view: A => Nameish) extends Namer(e)(view) {
^
one error found
I don't understand what's going on here: I'm not trying to declare an implicit object, I'm trying to declare that the class takes an implicit parameter. Why is it fine for the first class, but not the second one?
Adding parameter type parameter A to Namer (in the Subnamer inheritance) worked for me (Scala version 2.10.7):
class SubNamer[A <% Nameish](e: Class[A]) extends Namer[A](e)
By the way your example without modification worked for me only from the Scala version 2.11.5.
Hope this helps.

Scala Mockito Guice and Partial Mocking .... methods get called twice

I have the following code written in Scala, Guice, Mockito and ScalaTest
import javax.inject.Singleton
import com.google.inject.Inject
#Singleton
class TestPartialMock #Inject()(t1: Test1, t2: Test2) {
def test3() = "I do test3"
def workHorse() : List[String] = {
println("+++++ came inside ++++++++")
List(t1.test1(), t2.test2(), test3())
}
}
class MainModule extends ScalaModule {
override def configure() = {
bind[Test1]
bind[Test2]
bind[TestPartialMock]
}
}
and I have written unit test cases with partial mocking
class PartialMockTest extends FunSpec with Matchers {
describe("we are testing workhorse but mock test3") {
it("should return mock for test3") {
val module = new TestModule
val injector = Guice.createInjector(module)
val tpm = injector.getInstance(classOf[TestPartialMock])
val result = tpm.workHorse()
result should contain ("i do test2")
result should contain ("i do test1")
result should contain ("I am mocked")
result should not contain ("I do test3")
}
}
}
class TestModule extends AbstractModule with ScalaModule with MockitoSugar {
override def configure() = {
val module = new MainModule()
val injector = Guice.createInjector(module)
val realobject = injector.getInstance(classOf[TestPartialMock])
val x = spy(realobject)
when(x.test3()).thenReturn("I am mocked")
when(x.workHorse()).thenCallRealMethod()
bind(classOf[TestPartialMock]).toInstance(x)
}
}
My tests are successful and I can see that it mocks the right set of methods and calls the actual implementation of the right set of methods. BUT when I look at the output I see
info] Compiling 5 Scala sources to /Users/IdeaProjects/GuicePartialMock/target/scala-2.12/classes...
[info] Compiling 1 Scala source to /Users/IdeaProjects/GuicePartialMock/target/scala-2.12/test-classes...
+++++ came inside ++++++++
+++++ came inside ++++++++
[info] PartialMockTest:
[info] we are testing workhorse but mock test3
[info] - should return mock for test3
[info] Run completed in 2 seconds, 92 milliseconds.
Why am I seeing the print statement came inside twice?
Edit::
Based on advice of Tavian ... this is the final code which worked
class TestModule extends AbstractModule with ScalaModule with MockitoSugar {
override def configure() = {
val module = new MainModule()
val injector = Guice.createInjector(module)
val realobject = injector.getInstance(classOf[TestPartialMock])
val x = spy(realobject)
when(x.test3()).thenReturn("I am mocked")
bind(classOf[TestPartialMock]).toInstance(x)
}
}
For spies, you need to be careful of expressions like
when(x.workHorse()).thenCallRealMethod()
because x.workHorse() really is invoked in this expression! x doesn't "know" that it's inside a when() call, as the expression is lowered into something like this:
tmp1 = x.workHorse();
tmp2 = when(tmp1);
tmp3 = tmp2.thenCallRealMethod();
Instead, you can write
doCallRealMethod().when(x).workHorse()
which will suppress the invocation of the real workHorse() implementation.
But, you don't need to do any of this for this example—calling real methods is the default behaviour of spies.
As you mentioned in the question title, you have a combination of 3 technologies. Actually 4 technologies including build tool that is used to run the test. You can isolate the problem by
1) Remove Guice and instantiate everything directly
2) Run code as a simple App instead of running as a test by sbt/gradle/maven.
Also it makes sense to print stack trace together with a came inside message to find a caller.

Scala macro annotation typecheck for implicit class fails

Macro sample code:
package macros
import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation
class Ant extends StaticAnnotation {
def macroTransform(annottees: Any*): Unit = macro Ant.impl
}
object Ant {
def impl(c: Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
c.internal.enclosingOwner.asType.toType // this line is Ok
// ! Any commented line below causes the same compilation error
// c.internal.enclosingOwner.asType.toType.decls
// c.mirror.staticClass(c.internal.enclosingOwner.fullName + ".A".toString)
// c.typecheck(annottees.head)
q"""implicit class A(val v: Int) extends AnyVal { def ask() = println("ok") }"""
}
}
Changing whitebox.Context to macros.Context or blackbox.Context does not help.
Changing arguments withImplicitViewsDisabled=true, or withMacrosDisabled=true has no effect.
Exec sample code:
package test
import macros.Ant
object Test extends App {
val a = new A(42)
a.ask() // Output should be "ok" (not 42)
// ! removing [implicit] lets code be compiled
#Ant implicit class A(v: Int) { def ask() = println(v)}
}
So, removing line c.typecheck(annottees.head) and / or word implicit in line #Ant implicit class A(v: Int) lets code be compiled.
Otherwise compilation crashes with error:
Error:scalac:
no progress in completing object Test: <?>
while compiling: D:\Projects\_Schemee\TestMacro1\src\test\Test.scala
during phase: globalPhase=typer, enteringPhase=namer
library version: version 2.11.6
compiler version: version 2.11.6
reconstructed args: -nobootcp -classpath ...
last tree to typer: Ident(v)
tree position: <unknown>
tree tpe: Int
symbol: value v
symbol definition: v: Int (a TermSymbol)
symbol package: test
symbol owners: value v -> method A -> object Test
call site: method A in object Test in package test
<Cannot read source file>
Compiled under latest IntelliJ. With and without Sbt.
The question is: how to use typecheck in macro annotation with implicit classes? (or am i missing something?)
EDITED:
Besides that that error is caused when trying to access enclosingOwner declarations or mirror class A "manually".
Github link
Issue link
It looks like an sbt bug or interaction with compiler behavior.
The original exception:
java.lang.NullPointerException
at xsbt.Dependency$ExtractDependenciesByMemberRefTraverser$$anonfun$1.isDefinedAt(Dependency.scala:142)
That location:
val typeSymbolCollector = new CollectTypeTraverser({
case tpe if !tpe.typeSymbol.isPackage => tpe.typeSymbol
})
The traverser has a comment suggesting similar issues:
/*
* Some macros appear to contain themselves as original tree.
* We must check that we don't inspect the same tree over and over.
* See https://issues.scala-lang.org/browse/SI-8486
* https://github.com/sbt/sbt/issues/1237
* https://github.com/sbt/sbt/issues/1544
*/

Scala Reflection - Loading or finding classes based on trait

Does the scala reflection API (2.10) provide any easier means of searching the loaded classes and filtering the list to specific classes which implement a defined trait?
ie;
trait Widget {
def turn(): Int
}
class Cog extends Widget {
def turn() = {
5
}
}
class Sprocket extends Widget {
def turn() = {
10
}
}
I want to search the class library for anything that extends Widget and instantiate those classes. So I would end up with an instance of Cog and Sprocket.
I've done similar in Java iterating through the class directories, forming class names and using Class.forName to load a Class object to then check. I'm just wondering if the scala reflection API gives any easier way to search. All examples I've seen thus far have always started from a known class being instantiated, and not from searching over available classes.
This is what ServiceLoader is for.
I think the reflection API does make it easier to sort out what you need (i.e., for filtering but not for querying the class loader).
If, by your phrase, "searching the loaded classes", you really mean classes that are already loaded, see this question for getting them.
You could imagine a widgets library with an initializer that just ensures that all the widget classes it knows about are loaded. Then the client only needs to know the initializer.
The type test is the same.
val need = typeOf[Whatsit[Cog]]
for (x <- (ServiceLoader load classOf[Whatsit[_]]).asScala) {
val im = currentMirror reflect x
if (im.symbol.toType weak_<:< need)
Console println s"$x is what I need"
else
Console println s"$x is not what I need, I'm looking for a $need"
}
Where you're looking for something with type parameters:
trait Whatsit[+A <: Widget] {
def widget: A
}
class Engine extends Whatsit[Cog] {
def widget = new Cog
}
class FlyWheel extends Whatsit[Sprocket] {
def widget = new Sprocket
}
Sample:
widgets.Engine#f9da0cd is what I need
widgets.FlyWheel#4cfdbb9f is not what I need, I'm looking for a widgets.Whatsit[widgets.Cog]
In case it's been ten years since you used ServiceLoader, and who doesn't need a refresher:
apm#mara:~/tmp$ ls -R META-INF
META-INF:
MANIFEST.MF services
META-INF/services:
widgets.Whatsit widgets.Widget
apm#mara:~/tmp$ cat META-INF/services/widgets.Widget
widgets.Cog
widgets.Sprocket
apm#mara:~/tmp$ cat META-INF/services/widgets.Whatsit
widgets.Engine
widgets.FlyWheel
Stuff:
package widgets
trait Widget {
def turn(): Int
override def toString = s"Widget ${getClass.getSimpleName}"
}
class Cog extends Widget {
def turn() = 5
}
class Sprocket extends Widget {
def turn() = 10
}
trait Whatsit[+A <: Widget] {
def widget: A
override def toString = s"Whatsit ${getClass.getSimpleName} of $widget"
}
class Engine extends Whatsit[Cog] {
def widget = new Cog
}
class FlyWheel extends Whatsit[Sprocket] {
def widget = new Sprocket
}
Comparing Scala and Java. I was going to get a sense of how many LOC to getGenericInterfaces and find what you want in Scala, but then I put an end to the exercise.
package findwidgets
import reflect._
import reflect.runtime.universe._
import reflect.runtime.currentMirror
import scala.collection.JavaConverters._
import java.util.ServiceLoader
object Test extends App {
import widgets.{ Widget, Whatsit, Cog }
val ws = (ServiceLoader load classOf[Widget]).asScala
for (w <- ws) {
Console println s"Turn a ${w.getClass} by ${w.turn}"
}
val need = typeOf[Whatsit[Cog]]
for (x <- (ServiceLoader load classOf[Whatsit[Cog]]).asScala) {
val im = currentMirror reflect x
if (im.symbol.toType weak_<:< need)
Console println s"$x is what I need"
else
Console println s"$x is not what I need, I'm looking for a $need"
// java says:
if (classOf[Whatsit[Cog]] isAssignableFrom x.getClass)
Console println s"Um, OK, I'll take the $x"
else
Console println s"${classOf[Whatsit[Cog]]} isn't ass'able from ${x.getClass}"
}
}

Is there anyway to create a new Scala object from a Java Class

I have a number of use cases for this, all around the idea of interop between existing Java libraries and new Scala Code. The use case I've selected is the easiest I think.
Use Case:
I working on providing a JUnit Runner for some scala tests (so that I can get my lovely red / green bar in Eclipse)
The runner needs to have a constructor with a java class as a parameter. So in Scala I can do the following:
class MyRunner(val clazz: Class[Any]) extends Runner {
def getDescription(): Description
def run(notifier: RunNotifier)
}
When I use either
#RunWith(MyRunner)
object MyTestObject
or
#RunWith(MyRunner)
class MyTestClass
then the runner is indeed instantiated correctly, and is passed a suitable class object
Unfortunately what i want to do now is to "get hold of" the object MyTestObject, or create a MyTestClass, which are both Scala entities. I would prefer to use Scala Reflection, but I also want to use the standard Junit jar.
What I have done
The following Stackover flow questions were educational, but not the same problem. There were the nearest questions I could find
How to create a TypeTag manually?
Any way to obtain a Java class from a Scala (2.10) type tag or symbol?
Using Scala reflection with Java reflection
The discussion on Environments, Universes and Mirrors in http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html was good, and the similar documents on other scala reflection also helped. Mostly through it is about the Scala reflection.
I browsed the Scaladocs, but my knowledge of Scala reflection wasn't enough (yet) to let me get what I wanted out of them.
Edit:
As asked here is the code of the class that is being created by reflection
#RunWith(classOf[MyRunner])
object Hello2 extends App {
println("starting")
val x= "xxx"
}
So the interesting thing is that the solution proposed below using the field called MODULE$ doesn't print anything and the value of x is null
This solution works fine if you want to use plan old java reflection. Not sure if you can use scala reflection given all you will have is a Class[_] to work with:
object ReflectTest {
import collection.JavaConversions._
def main(args: Array[String]) {
val fooObj = instantiate(MyTestObject.getClass())
println(fooObj.foo)
val fooClass = instantiate(classOf[MyTestClass])
println(fooClass.foo)
}
def instantiate(clazz:Class[_]):Foo = {
val rm = ru.runtimeMirror(clazz.getClassLoader())
val declaredFields = clazz.getDeclaredFields().toList
val obj = declaredFields.find(field => field.getName() == "MODULE$") match{
case Some(modField) => modField.get(clazz)
case None => clazz.newInstance()
}
obj.asInstanceOf[Foo]
}
}
trait Foo{
def foo:String
}
object MyTestObject extends Foo{
def foo = "bar"
}
class MyTestClass extends Foo{
def foo = "baz"
}