Handing Case Class Exceptions and Compiling them - scala

I am trying to get these two classes to link up.
PatientMonitorExceptions.scala
abstract class PatientMonitorExceptions extends Exception
case class InvalidHeartRate (str:String) extends PatientMonitorExceptions
Here is my main.scala that I am trying to compile with the following line:
main.scala
import gasguru.patient.PatientMonitor
import gasguru.patient.Patient
import gasguru.patient.exceptions.InvalidHeartRate
object Main extends App {
val p = new Patient("snyder","brad");
val v = p.vitalSigns
val pm = new PatientMonitor(p);
p.vitalSigns.heartRate = 160;
println("The patient's heart rate is: " + p.vitalSigns.heartRate + " bpm");
try { pm checkHeartRate v.heartRate
}
catch {
case InvalidHeartRate(x) => println(x);
case _ => println("Something else");
}
}
I am running: scala main.scala to compile this
error: error while loading InvalidHeartRate, Missing dependency 'class InvalidHeartRate', required by ./gasguru/patient/exceptions/InvalidHeartRate.class
What does this error message mean?

When main.scala references InvalidHeartRate, it is referring to the companion object created for your case class InvalidHeartRate, and invoking the unapply method on it to do the match. The InvalidHeartRate object is dependent on the InvalidHeartRate case class being in the classpath. The error message occurred because even though the companion object's .class file (InvalidHeartRate$.class) could be found, the .class file for the case class itself is missing (InvalidHeartRate.class). I would suggest deleting all your .class files and recompiling.

Related

Pattern matching ParseResult in unit test

I'm stepping through my first Scala project, and looking at parser combinators in particular. I'm having trouble getting a simple unit test scenario to work, and trying to understand what I'm missing.
I'm stuck on pattern matching a ParseResult into the case classes of Success, Failure and Error. I can't get Scala to resolve the case classes. There's a few examples around of this, but they all seem to be using them inside something that extends of of the parser classes. For example the tests on github are inside the same package. The example here is inside a class extending a parser.
The test i'm trying to write looks like:
package test.parsertests
import parser.InputParser // my sut
import scala.util.parsing.combinator._
import org.scalatest.FunSuite
class SetSuite extends FunSuite {
val sut = new InputParser()
test("Parsing a valid command") {
val result = sut.applyParser(sut.commandParser, "SOME VALID INPUT")
result match {
case Success(x, _) => println("Result: " + x.toString) // <-- not found: value Success
case Failure(msg, _) => println("Failure: " + msg) // similar
case Error(msg, _) => println("Error: " + msg) // similar
}
}
}
and the method I'm calling is designed to let me exersize each of my parsers on my SUT:
package parser
import scala.util.parsing.combinator._
import scala.util.parsing.combinator.syntactical._
class InputParser extends StandardTokenParsers {
def commandParser: Parser[Command] =
("Command " ~> coord ~ coord ~ direction) ^^ { case x ~ y ~ d => new Command(x, y, d) }
def applyParser[T](p: Parser[T], c: String): ParseResult[T] = {
val tokens = new lexical.Scanner(c)
phrase(p)(tokens)
}
The fundamental issue is getting the case classes resolved in my test scope. Based on the source for the Parsers class, how can I get them defined? Can I resolve this with some additional import statements, or are they only accessible via inheritance? I've tried all the combinations that should resolve this issue, but I'm obviously missing something here.
Right hand column FTW! I stumbled on an answer in this related question. The problem was identifying the case classes as nested classes of Parsers.

Spray won't convert my case class to json and expect a spray.httpx.marshalling.ToResponseMarshallable

I'm trying to reprocude this or this, but I keep getting an error I am not able to fix...
First of all, here are my dependencies:
compile 'io.spray:spray-can_2.11:1.3.1'
compile 'io.spray:spray-routing_2.11:1.3.1',
compile 'io.spray:spray-json_2.11:1.2.6'
Now what I'm trying to do is:
class WHttpService extends Actor with HttpService with ActorLogging {
implicit def actorRefFactory = context
def receive = runRoute(route)
lazy val route = logRequest(showReq _) {
// Way too much imports but I tried all I could find
import spray.json._
import DefaultJsonProtocol._
import MasterJsonProtocol._
import spray.httpx.SprayJsonSupport._
path("server" / Segment / DoubleNumber / DoubleNumber) { (login, first, second) =>
get {
complete {
Answer(1, "test")
}
}
}
}
private def showReq(req : HttpRequest) = LogEntry(req.uri, InfoLevel)
}
With:
case object MasterJsonProtocol extends DefaultJsonProtocol with SprayJsonSupport {
import spray.json._
case class Answer(code: Int, content: String)
implicit val anwserFormat: JsonFormat[Answer] = jsonFormat2(Answer)
}
Now I get this error:
Error:(42, 19) type mismatch;
found : MasterJsonProtocol.Answer
required: spray.httpx.marshalling.ToResponseMarshallable
Answer(1, "test")
^
I tried a lot of things but can't manage to make it works.
I tried with
Answer(1, "test").toJson
Answer(1, "test").toJson.asJsObject
Finally what I did was
complete {
Answer(1, "test").toJson.compactPrint
}
This works but it is sent to the client as Content-Type: text/plain when I need application/json.
Anyone see what the problem is here?
Edit: I added a sample project on github https://github.com/ydemartino/spray-test
Move your model outside of the json protocol and make it a regular object (not a case object)
case class Answer(code: Int, content: String)
object MasterJsonProtocol extends DefaultJsonProtocol {
implicit val anwserFormat = jsonFormat2(Answer)
}
Edit
Also clean up your imports:
class WHttpService extends Actor with HttpService with ActorLogging {
implicit def actorRefFactory = context
def receive = runRoute(route)
lazy val route = logRequest(showReq _) {
// Way too much imports but I tried all I could find
import MasterJsonProtocol._
import spray.httpx.SprayJsonSupport._
path("server" / Segment / DoubleNumber / DoubleNumber) { (login, first, second) =>
get {
complete {
Answer(1, "test")
}
}
}
}
private def showReq(req : HttpRequest) = LogEntry(req.uri, InfoLevel)
}
I created a pull request to fix your problem: https://github.com/ydemartino/spray-test/pull/1
The json protocol object has to be declared before it can be used implicitly. I'm not wholly sure why the compiler can't figure it out, but moving the object declaration to the top fixed it.
For your actual project make sure to declare packages in each file then use those packages to in the import statements.
In my case the name of the unresolvable implicit format instance conflicted with a local definition, so it got shadowed. The compiler was graciously silent about that. Only discovered that by accident after hours of head-banging.

Scala Compiler TypeRef to ClassDef

I am writing a plugin which watches for an #unmatchable annotation and throws a warning if it is found in pattern matching.
I have been able to find the TypeRef, but I can not convert it into a ClassDef so I can inspect the annoations.
I'm guessing that I need to get the root of the tree and use TreeOpts.find in order to get the actual ClassDef. However, I can not find where the root tree is.
EDIT: I need more than the root Compilation units in case a matchable annoation is included in a library.
Here is what I have so far.
class UnmatchablePlugin(val global: Global) extends Plugin {
val name = "unmatchable-check-gen"
val description = "marks a class unmatchable"
val components = List[PluginComponent](UnmatchableComponent)
private object UnmatchableComponent extends PluginComponent with Transform {
val global: UnmatchablePlugin.this.global.type = UnmatchablePlugin.this.global
val runsAfter = List("parser")
// Using the Scala Compiler 2.8.x the runsAfter should be written as below
// val runsAfter = List[String]("parser");
val phaseName = UnmatchablePlugin.this.name
def newTransformer(unit: global.CompilationUnit) = UnmatchableTransformer
object UnmatchableTransformer extends global.Transformer {
override def transform(tree: global.Tree) = {
import global._
tree match {
case cd # global.CaseDef(global.Bind(_, global.Typed(exp,tpt)) , _, _) => {
//Need to turn tpt.tpe.sym into a ClassDef
println("sym: " + tpt.tpe.sym)
tree
}
case t => super.transform(t)
}
}
}
}
}
In general, you cannot turn types/symbols into trees because there might be a symbol that has no tree corresponding to it. It's a case for example when symbol is corresponding to class defined in binary class file.
However, as far as I understand what you are trying to do you don't need ClassDef. Symbols you obtained already has all information about annotations. Check hasAnnotation and getAnnotation methods defined in Symbols.scala (lines 1115-1118).

Scala SBT: possible bug?

When I "sbt run" the following code,
package com.example
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.FileInputStream
import java.io.FileOutputStream
object SimpleFailure extends App {
case class MyClass(a: String, b: Int, c: Double)
def WriteObjectToFile[A](obj: A, filename: String) {
val output = new ObjectOutputStream(new FileOutputStream(filename, false))
output.writeObject(obj)
}
def ReadObjectFromFile[A](filename: String)(implicit m: Manifest[A]): A = {
val obj = new ObjectInputStream(new FileInputStream(filename)) readObject
obj match {
case a if m.erasure.isInstance(a) => a.asInstanceOf[A]
case _ => { sys.error("Type not what was expected when reading from file") }
}
}
val orig = MyClass("asdf", 42, 2.71)
val filename = "%s/delete_me.spckl".format(System.getProperty("user.home"))
WriteObjectToFile(List(orig), filename)
val loaded = try {
ReadObjectFromFile[List[MyClass]](filename)
} catch { case e => e.printStackTrace; throw e }
println(loaded(0))
}
I get the following exception:
java.lang.ClassNotFoundException: com.example.SimpleFailure$MyClass
However, I can run the code fine in Eclipse with the Scala plugin. Is this an SBT bug? Interestingly, the problem only comes up when wrapping MyClass in a List (see how "orig" is wrapped in a List in the WriteObjectToFile call). If I don't wrap in a List, everything works fine.
Put this in your build.sbt or project file:
fork in run := true
The problem seems to be with the classloader that gets used when sbt loads your code. ObjectInputStream describes it's default classloader resolution, which walks the stack. Normally, this ends up finding the loader associated with the program in mind, but in this case, it ends up using the wrong one.
I was able to work around this by including the following class in my code, and using it instead of ObjectInputStream directly.
package engine;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
class LocalInputStream extends ObjectInputStream {
LocalInputStream(InputStream in) throws IOException {
super(in);
}
#Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws ClassNotFoundException
{
return Class.forName(desc.getName(), false,
this.getClass().getClassLoader());
}
}
This overrides the resolveClass method, and always uses one associated with this particular class. As long as this class is the one that is part of your app, this should work.
BTW, this is both faster than requiring fork in run, but it also works with the Play framework, which currently doesn't support forking in dev mode.
I was able to reproduce this too using sbt 0.10.1 and scalaVersion := "2.9.0-1". You should probably just report it on github or bring it up on the mailing list.

Objects being "turned" to null randomly

Hey guys,
im working on a project in scala and i encountered very weird problem. This is a part of the code :
class Entity(val id:String){
override def toString = id
}
class RequirementType
case class DependsEither(t:List[(Entity,Int)]) extends RequirementType
case class Depends(t:(Entity,Int)) extends RequirementType
class BuildableEntity(override val id:String,
val mineralCost:Int,
val gasCost:Int,
val buildTime:Int,
val buildCount:Int,
val supplyCount:Int,
val req:List[RequirementType],
val onBuildStart: GameState => GameState,
val onBuildFinish: GameState => GameState
)extends Entity(id)
class SimpleBuilding(id:String,
mineralCost:Int,
gasCost:Int,
buildTime:Int,
req:List[RequirementType]
) extends BuildableEntity(id,mineralCost,gasCost,buildTime,1,0,req:::List(ConsumesOnStart((Drone,1))),{s=>s},{x=>x})
object SpawningPool extends SimpleBuilding("spawningPool",200,0,65,List(DependsEither(List((Hatchery,1),(Lair,1),(Hive,1)))))
object Lair extends SimpleBuilding("lair",150,100,80,List(ConsumesOnFinish(Hatchery,1),Depends(SpawningPool,1)))
object InfestationPit extends SimpleBuilding("infestationPit",100,100,50,List(DependsEither(List((Lair,1),(Hive,1)))))
Now, when i call println(Lair.req), it sometimes prints as
List(ConsumesOnFinish((hatchery,1)), Depends((null,2)), ConsumesOnStart((drone,1)))
and sometimes as
List(ConsumesOnFinish((hatchery,1)),
Depends((spawningPool,2)), ConsumesOnStart((drone,1)))
Please, if anyone has any idea about what could be going wrong, i would love you for ever. I have no clue why is it act as it does. I have more extensions of SimpleBuilding but they seem to be working properly
EDIT:
I should also mention that the outcome changes after compilation. I mean that when i run unit test it sometimes appear as null and sometimes as proper instance.
This is indeed a case of circular dependency and initialization. Here is a shorter version of your issue:
class X(val x: List[X])
object A extends X(List(B))
object B extends X(List(A))
object Main {
def main(args:Array[String]) {
println("A.x: " + A.x)
println("B.x: " + B.x)
}
}
This will print this:
$ scala -cp classes Main
A.x: List(B$#143c8b3)
B.x: List(null)
You can use by names parameter to allow object construction to finish before you use it:
class X(x0: => List[X]) {
lazy val x = x0
}
object A extends X(List(B))
object B extends X(List(A))
The fix works on the small test case:
$ scala -cp classes Main
A.x: List(B$#1feca64)
B.x: List(A$#6d084b)
Based on this you may want to change req:List[RequirementType] to req0: => List[RequirementType] and add a lazy val req = req0.
If that works for you, we should retitle the question to mention object initialization and circular dependencies. Note this is very similar to this question/answer.
Lair use SpawningPool in its constructor and reciprocally. But at that time, the other doesn't exists.
You've got recursive definitions in constructors, and although I believe that is supported, it looks like something's going wrong. Can you try lazy vals instead and see if the problem goes away? That is,
object X extends C("this",that,1) { /* code */ }
becomes
lazy val X = new C("this",that,1) { /* code */ }