Type error when mocking Slick Query using ScalaMock: what does "some other" mean? - eclipse

I have used Java for several years, however I'm new to Scala and am still trying to figure out its type system. I'm using Scala 2.10.2, Slick 1.0.1, and ScalaMock 2.10-3.0-M4 in Eclipse Scala IDE 3.0.1
I'm trying to mock out Slick in updateNameById using ScalaMock.
def updateNameById(id: Int, input: String, users: RichTable[Object]) = {
users.where(_.id === id).map{ e => e.test }.update(input)
}
abstract class RichTable[T](name: String = "blank")
extends slick.driver.MySQLDriver.simple.Table[T](name) {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def test = column[String]("test")
}
(I'm actually passing in users: RichTable[User] where User has a complex inheritance hierarchy, but I've temporarily removed the uses of User to simplify the example)
users.where returns a scala.slick.lifted.Query, so I try to mock this out as follows
class ModelTest extends FlatSpec with MockFactory {
def test = {
val mockUsers = mock[RichTable[Object]]
// mockQuery definition
val mockQuery = mock[scala.slick.lifted.Query[RichTable[Object],
scala.slick.lifted.NothingContainer#TableNothing]]
(mockUsers.where _).expects(*).returns(mockQuery)
Main.updateNameById(1, "asdf", mockUsers)
}
}
The mockQuery definition gives me these cryptic type errors
type mismatch;
found : scala.slick.lifted.Query[O(in method union),
scala.slick.lifted.NothingContainer#TableNothing]
required: scala.slick.lifted.Query[(some other)O(in method union),
scala.slick.lifted.NothingContainer#TableNothing]
type mismatch;
found : scala.slick.lifted.Query[O(in method unionAll),
scala.slick.lifted.NothingContainer#TableNothing]
required: scala.slick.lifted.Query[(some other)O(in method unionAll),
scala.slick.lifted.NothingContainer#TableNothing]
I have no idea what "O(in method union[all])" vs. "(some other)O(in method union[All])" means, and Google hasn't been any help (it doesn't help matters that "some other" is an extremely generic phrase - googling "scala some other type error" produces pretty much the same results as "scala type error"). Does anybody know what this means and/or how to fix the type error?

Related

IntelliJ unable to resolve certain types, ex: EnumValue on a Mongo record - Scala

For Example:
object CampaignTypes extends Enumeration {
type CampaignType = Value
val ABC,DEF = Value
}
object campaignTypeId extends EnumNameField(this, CampaignTypes) {
override val defaultValue = CampaignTypes.ABC
}
IntelliJ underlines CampaignTypes.ABC in red with message Expression of type CampaignTypes.Value doesn't conform to expected type EnumType#Value
The code compiles & works. But, IntelliJ marks it as an error, making it difficult to read code (as there are many other cases, which is also not resolved by IntelliJ). The right Scala plugin is also used. Is there a way to resolve this?
Another example w.r.t methods defined on a BsonRecord
sealed trait Product {...}
class Document extends BsonRecord[Document] {
object productType extends StringField(this, 20)
....
def toTyped: Option[Product] = this.productType.get match {//something which returns an Option[Product] from a List[Product]}
}
object documents extends BsonRecordListField(this, Document) {
def toProducts: Set[Product] =
this.get.flatMap(_.toTyped)(breakOut) //Cannot resolve symbol toTyped
}
Yes, you can help Intellij by providing type hints :
object campaignTypeId extends EnumNameField[A, CampaignsTypes.type](this, CampaignTypes) {
override val defaultValue = CampaignTypes.ABC
}
where A is the type of the encapsulating class/object
For a general solution :
Try to always provide generic types instead of relying on inference, as you can see the one in Intellij IDEA is not great in diffucult cases.
If that doesn't cut it, try to provide compiler hints. Lift relies on Manifest, but it can be classTag or other things. Expliciting this kind of implicits can help IDEA resolve types correctly
For BsonRecordListField, expliciting generic types should solve it too.

Why is the Scala compiler giving me an error when passing a Kotlin sealed class into a constructor?

I have a sealed class, written in Kotlin:
sealed class Schema {
class RecordSchema(val fields: List<Field>): Schema()
class ArraySchema(val elementSchema: Schema): Schema()
...
}
And another class that takes RecordSchema as a parameter:
class Enrichment(config: Config, val schema: RecordSchema) { ... }
In Scala I have a class that, among other things, get an instance of the RecordSchema and then create an instance of the Enrichment.
object Job {
def main(args: Array[String]): Unit = {
/// some initializing of resources... and then...
val recordSchema = schemas.getSchema(id) // type is Schema.RecordSchema
val enrichment = Enrichment(config, recordSchema) // this is where scalac errors out
}
}
The scala compiler ends up printing this error message:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.com.companyname.enricher.schemas.com.companyname.enricher.schemas.
required: com.companyname.enricher.schemas.(some other)com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema)
If I cast recordSchema using asInstanceOf I get another, not so useful, error:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.Schema.RecordSchema
required: com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema.asInstanceOf[RecordSchema])
Overall, I have no idea why this is happening. If I make the constructor take the parent class as a parameter rather than nested class, it compiles just fine (which is my workaround for now). If I do the same type of thing, except having written the sourcecode in Java rather than Kotlin, this error does not happen. I am using Java 1.8, Kotlin 1.0.4, Scala 2.11.8.
UPDATE:
demonstrated bug here:
https://github.com/mjburghoffer/scala-kotlin-innerclass-bug/tree/master
Looks like Kotlin generates different number of classes for this case. I compiled Java and Kotlin sources and found that Java has additional file ParentSealedJava$1.class. Bytecode of Parent and Sealed classes in Java and Kotlin pretty the same (i inspect bytecode using javap -c), so i think Scala compiler relies somehow on this missing file in Kotlin.

MappedEnum - No implicit view available

Can someone help me to understand what is wrong with the code below? The problem is inside the "join" method - I am not able to set "state" field. Error message is -
No implicit view available from code.model.Membership.MembershipState.Val => _14.MembershipState.Value.
[error] create.member(user).group(group).state(MembershipState.Accepted).save
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
What does _14 mean? I tried similar thing with MappedGender and it works as expected, so why MappedEnum fails?
scala 2.10
lift 2.5
Thanks
package code
package model
import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
class Membership extends LongKeyedMapper[Membership] with IdPK {
def getSingleton = Membership
object MembershipState extends Enumeration {
val Requested = new Val(1, "Requested")
val Accepted = new Val(2, "Accepted")
val Denied = new Val(3, "Denied")
}
object state extends MappedEnum(this, MembershipState)
{
override def defaultValue = MembershipState.Requested
}
object member extends MappedLongForeignKey(this, User) {
override def dbIndexed_? = true
}
object group extends MappedLongForeignKey(this, Group) {
override def dbIndexed_? = true
}
}
object Membership extends Membership with LongKeyedMetaMapper[Membership] {
def join (user : User, group : Group) = {
create.member(user).group(group).state(MembershipState.Accepted).save
}
}
Try moving your MembershipState enum outside of the MembershipClass. I was getting the same error as you until I tried this. Not sure why, but the code compiled after I did that.
_14 means a compiler-generated intermediate anonymous value. In other words, the compiler doesn't know how to express the type it's looking in a better way.
But if you look past that, you see the compiler is looking for a conversion from [...].Val to [...].Value. I would guess that changing
val Requested = new Val(1, "Requested")
to
val Requested = Value(1, "Requested")
would fix the error.
(I'm curious where you picked up the "new Val" style?)
What's strange is that Val actually extends Value. So if the outer type was known correctly (not inferred to the odd _14) Val vs. Value wouldn't be a problem. The issue here is that Lift from some reason defines the setters to take the now-deprecated view bound syntax. Perhaps this causes the compiler, rather than going in a straight line and trying to fit the input type into the expected type, instead to start from both ends, defining the starting type and the required type, and then start searching for an implicit view function that can reconcile the two.

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"
}

Specs implicit conversion conflicts with Scala Predef

I have a type alias in my code like so:
type Time = Double
And I often in both tests and in applications pass Long values to functions that use this type. For instance:
def at(time : Time) : T = {
// Do Something
}
at(System.currentTimeMillis)
This code works fine unless run in my tests where I get the following error:
found : Long
required: com.github.oetzi.echo.Echo.Time
Note that implicit conversions are not applicable because they are ambiguous:
both method long2double in object Predef of type (x: Long)Double
and method longToDouble in trait NumericBaseMatchers of type (s: Long)Double
are possible conversion functions from Long to com.github.oetzi.echo.Echo.Time
After looking up NumericBaseMatchers it seems its part of the Specs testing framework (my tests are written in Specs 1). I tried running code to get the error in the interpreter and it was fine out side of the tests.
Is there any way I can somehow remove the ambiguity so I can pass Long to values to a Double/Time function? Why does Specs try and create its own LongToDouble conversion when Scala already provides this?
If you want to deactivate an inherited implicit conversion you can do this:
override def longToDouble(s: Long) = super.longToDouble(s)
For convenience if you add it to a new trait, you can mix-in your trait to your specification when needed:
trait NoConversion {
override def longToDouble(s: Long) = super.longToDouble(s)
}
class MySpecification extends NoConversion {
...
}
Try unimporting one of them.
import NumericBaseMatchers.{longToDouble => _}