IntelliJ IDEA Scala plugin good code red - scala

I've been using IntelliJ IDEA 2016 with scala plugin 3.0, but run into the following error:
IntelliJ tells me that
Type "V" overrides nothing.
NodeVisitor and Visitor are all trait:
trait NodeVisitor extends Visitor[NodeBase]{
override def visit[E >:NodeBase](node:E):Unit
}
However, the code compiles fine. The same code also shows no error in Eclipse. Is this IDEA's bug? Or do I have to configure something special?

Early definitions block is used to initialize fields of your class in the right order on a new instance creation. It may contain only val and var definitions by the language specification. You can override type member in the body of your class, as it doesn't depend on the order of initialization.
I'm not sure why scalac compiles it, seems like a bug to me.

Related

can`t bind[SttpBackend[Try, Nothing]]

I want to use sttp library with guice(with scalaguice wrapper) in my app. But seems it is not so easy to correctly bind things like SttpBackend[Try, Nothing]
SttpBackend.scala
Try[_] and Try[AnyRef] show some other errors, but still have no idea how it should be done correctly
the error I got:
kinds of the type arguments (scala.util.Try) do not conform to the expected kinds of the type parameters (type T).
[error] scala.util.Try's type parameters do not match type T's expected parameters:
[error] class Try has one type parameter, but type T has none
[error] bind[SttpBackend[Try, Nothing]].toProvider[SttpBackendProvider]
[error] ` ^
SttpBackendProvider looks like:
def get: SttpBackend[Try, Nothing] = TryHttpURLConnectionBackend(opts)
complete example in scastie
interesting that version scalaguice 4.1.0 show this error, but latest 4.2.2 shows error inside it with converting Nothing to JavaType
I believe you hit two different bugs in the Scala-Guice one of which is not fixed yet (and probably even not submitted yet).
To describe those issues I need a fast intro into how Guice and Scala-Guice work. Essentially what Guice do is have a mapping from type onto the factory method for an object of that type. To support some advanced features types are mapped onto some internal "keys" representation and then for each "key" Guice builds a way to construct a corresponding object. Also it is important that generics in Java are implemented using type erasure. That's why when you write something like:
bind(classOf[SttpBackend[Try, Nothing]]).toProvider(classOf[SttpBackendProvider])
in raw-Guice, the "key" actually becomes something like "com.softwaremill.sttp.SttpBackend". Luckily Guice developers have thought about this issue with generics and introduced TypeLiteral[T] so you can convey the information about generics.
Scala type system is more reach than in Java and it has some better reflection support from the compiler. Scala-Guice exploits it to map Scala-types on those more detailed keys automatically. Unfortunately it doesn't always work perfectly.
The first issue is the result of the facts that the type SttpBackend is defined as
trait SttpBackend[R[_], -S]
so it uses it expects its first parameter to be a type constructor; and that originally Scala-Guice used the scala.reflect.Manifest infrastructure. AFAIU such higher-kind types are not representable as Manifest and this is what the error in your question really says.
Luckily Scala has added a new scala.reflect.runtime.universe.TypeTag infrastructure to tackle this issue in a better and more consistent way and the Scala-Guice migrated to its usage. That's why with the newer version of Scala-Guice the compiler error goes away. Unfortunately there is another bug in the Scala-Guice that makes the code fail in runtime and it is a lack of handling of the Nothing Scala type. You see, the Nothing type is a kind of fake one on the JVM. It is one of the things where the Scala type system is more reach than the Java one. There is no direct mapping for Nothing in the JVM world. Luckily there is no way to create any value of the type Nothing. Unfortunately you still can create a classOf[Nothing]. The Scala-to-JVM compiler handles it by using an artificial scala.runtime.Nothing$. It is not a part of the public API, it is implementation details of specifically Scala over JVM. Anyway this means that the Nothing type needs additional handling when converting into the Guice TypeLiteral and there is none. There is for Any the cousin of Nothing but not for Nothing (see the usage of the anyType in TypeConversions.scala).
So there are really two workarounds:
Use raw Java-based syntax for Guice instead of the nice Scala-Guice one:
bind(new TypeLiteral[SttpBackend[Try, Nothing]]() {})
.toInstance(sttpBackend) // or to whatever
See online demo based on your example.
Patch the TypeConversions.scala in the Scala-Guice as in:
private[scalaguice] object TypeConversions {
private val mirror = runtimeMirror(getClass.getClassLoader)
private val anyType = typeOf[Any]
private val nothingType = typeOf[Nothing] // added
...
def scalaTypeToJavaType(scalaType: ScalaType): JavaType = {
scalaType.dealias match {
case `anyType` => classOf[java.lang.Object]
case `nothingType` => classOf[scala.runtime.Nothing$] //added
...
I tried it locally and it seems to fix your example. I didn't do any extensive tests so it might have broken something else.

Correct class names in IntelliJ debugger (scala)

I am new to scala & IntelliJ, so this might sound like a stupid question. However, I see that when debugging, IntelliJ will infer parameter types to some kind of "weird" type, in my case MapLike$MappedValues. The expected type would be Map[String, Iterable[Person]].
Why can IntelliJ not display the correct type? Right now this would be kind of important to me, because by debugging I am trying to find out the correct parameter type, because the API documentation on this part is not very clear (working with Apache Flink CEP)
Code example:
val result:DataStream[String] = patternStream.select(patterns => {
val person:Person = patterns.head._2.head
s"Person ${person.name} of age ${person.age} can drink!"
})
This is what I can see in the debugger:
According to the documentation:
"The select() method takes a selection function as argument, which is called for each matching event sequence. It receives a match in the form of Map[String, Iterable[IN]]"
Why does IntelliJ display MapLike$MappedValues and not something like Map[String,Iterable[Person]]?
The debugger is showing you the runtime class.
On the JVM, generic type parameters are "erased" at runtime, so they will not be visible in the debugger. Map is just an interface, but MapLike$MappedValues implements it as inheritor of AbstractMap.
Thus, the displayed class is compatible with the type of the value.
To find the compile time type of an expression, IntelliJ can help you:
select the expression
press the "type info" hotkey (usually shift+ctrl+p)

Intellij + FunSuite weird Behavior

I have a problem with Intellij running tests on scala. I guess It is a configuration issue but I can't figure it out.
1.- When I write some simple test like below, I got the message: "class MyTest must either be declare as abstract or implement abstract member 'expectedTestCount' ... "
class MyTest extends FunSuite {
test("a") {
assert(true)
}
}
But I am just following scala's documentation in which no overriding is going on. It compiles and I can run the test, but it is anoying
2.- The other weird thing is the triple equal operator (===). You can use it in scala for a better explanation on tests, but Intellij seems to not recognize It: "cannot resolve symbol ===" message pops up when writing it. Again It compiles and works OK but you get all your code in alarm red
Any suggestion?
Best regards

Does Scala have a global object or class?

I know programmers are supposed to wrap their code in an application object:
object Hello extends App {
println("Hello, World")
}
It is required in Eclipse, if I ever want to get any output. However, when I tried to write some code (very casually) in Emacs, I write like this:
class Pair[+T](val first: T, val second: T)
trait Friend[-T] {
def befriend(someone: T)
}
def makeFriendWith(s: Student, f: Friend[Student]) {
f.befriend(s)
}
It seems like there is no universal object or class that wraps over the function makeFriendWith. Is Scala like JavaScript, everything is attached to a global object? If not, what is this function attached to?
Also why can this work in console (I complied it with scala command and it worked) but does not work in Eclipse? What's the use of the Application object?
Scala doesn't have top-level defs, but your script can be run by either the REPL or the scala script runner.
The precise behavior of your script depends on which way you run it.
The REPL can run scripts line-by-line or whole hog. (Compare :paste and :paste -raw versus :load or -i init.script and the future option -I init.script.)
There is an issue about sensitive scripting. The script runner should realize if you're trying to run an App.
There is another effort to make scripting a compiler phase that is easily customized. Scroll to Scripter.scala for code comments about its current heuristics.
In short, your defs must be wrapped in a top-level entity, but exactly how that happens is context-dependent.
There was a recent effort to make an alternative baked-in wrapping scheme available for the REPL.
None of this is mandated by the language spec, any more than special rules pertaining to sbt build files are defined by the language.
You can define methods like this only in the console, which (behind the scenes) automatically wraps them in an anonymous class for you.
Outside of the console, there's no such luxury.
As a JVM language, Scala cannot truly create any top-level entities other than classes and interfaces.
It does, however, have the notion of a "package object" which creates the illusion of value entites (val, var and def) not enclosed in a class or trait.
See http://www.scala-lang.org/docu/files/packageobjects/packageobjects.html for information on package objects.
You can run code like this directly in Eclipse: use Scala worksheet. IntelliJ IDEA Scala plugin supports it as well.

IntelliJ, analyzing Scala code

When i am using IntelliJ to analyze (Analyze->Inspect code) my Java code, which happens to have an unused method, they are flagged. This same behavior does not seem to be happening with Scala.
For instance, IntelliJ finds no issues with
object Main {
def main(args: Array[String]) {
}
private def max(a: Int, b: Int) = { // <---- unused
if (a > b) a else b
}
}
Can i enable this (and other) checks somehow? What am i missing please?
As far as I can tell, the Scala plugin for IDEA doesn't have an inspection for unused methods (even private ones).
For Java, IDEA has "Unused declaration":
This inspection reports classes, methods or fields in the specified inspection scope that are not used or not reachable from entry points.
Unfortunately the only related inspection for Scala is "Unused Symbol."
The only related issue I could find is SCL-3121. You could add a feature request on the issue tracker for unused method highlighting.
I think it's appropriate that IntelliJ does not set it as unused because the max method is defined as a public method.