Referring to a non-existent class java.io.File - scala

This question appears fundamentally the same as Linker error in ScalaJS: "Referring to non-existent class", but seems to differ in specifics. I don't specify a JVM version in build.sbt.
I'm trying to access a file in my scalajs app using scala.io.Source, or java.io.File. As soon as I attempt to use either I get a link fail:
...
[info] Fast optimizing C:\Users\Tim\Documents\GitHub\binpack\target\scala-2.11\binpack-fastopt.js
[error] Referring to non-existent class java.io.File
[error] called from client.jsClient$.onFileChosen(japgolly.scalajs.react.SyntheticEvent)scala.Function0
...
Is there a method by which I can diagnose what's going on here? I'm assuming the problem is not specific to java.io.File, but don't know what the next step would be.
This is scala 2.11.8, with sbt 0.13.7.

java.io.File is not portable to Scala.js because it's specifically tied to the JVM. See http://www.lihaoyi.com/hands-on-scala-js/#PortingJavaAPIs (just scroll to the very bottom) for a little more detail.
So, if you want to do filesystem IO in Scala.js, you'll need to use a solution specifically implemented for JavaScript, like io.js. Here's an example: http://bchazalet.github.io/2015/07/20/scalajs-electron-skeleton-part-2/

Related

How can I change the compiler flags of an sbt project without causing recompilation?

It often comes up during testing and debugging a Scala project built with sbt that I need to pass some extra compiler flags for a particular file. For example -Xlog-implicits to debug implicit resolution problems. However, changing scalacOptions either in build.sbt or the console invalidates the cache and causes the whole project / test suite to be recompiled. In addition to being annoying to wait so long, this also means that a lot of noise from irrelevant files is printed. Instead it would be better if I could compile a specific file with some extra flags from the sbt console, but I did not find a way to do this.
Problem
The reason why changing the scalac options triggers recompilation is because Zinc, Scala's incremental compiler, cannot possibly now which compiler flags affect the semantics of the incremental compilation, so it's pessimistic about it. I believe this can be improved, and some whitelisted flags can be supported, so that next time people like you don't have to ask about it.
Nevertheless, there's a solution to this problem and it's more generic than it looks like at first sight.
Solution
You can create a subproject in your sbt build which is a copy of the project you want to "log implicits" in, but with -Xlog-implicits enabled by default.
// Let's say foo is your project definition
lazy val foo = project.settings(???)
// You define the copy of your project like this
lazy val foo-implicits = foo
.copy(id = "foo-implicits")
.settings(
target := baseDirectory.value./("another-target"),
scalacOptions += "-Xlog-implicits"
)
Note the following properties of this code snippet:
We redefine the project ID because when we reuse a project definition the ID is still the same as the previous one (foo in this case). Sbt fails when there are projects that share the same id.
We redefine the target directory because we want to avoid recompilation. If we keep the same as before, then recompiling foo-implicits will delete the compilation products of the previous compilation (and viceversa). That's exactly what we want to avoid.
We add -Xlog-implicits to the Scalac options as you request in this question. In a generic solution, this piece of code should go away.
When is this useful?
This is useful not only for your use case, but when you want to have different modules of the same project in different Scala versions. The following has two benefits:
You don't use cross-compilation in sbt ++, which is known to have some memory issues.
You can add new library dependencies that only exist for a concrete Scala version.
It has more applications, but I hope this addresses your question.

Strange behaviour when importing types in Scala 2.10

Today I cleared my .ivy cache and cleaned my project output targets. Since then I have been getting really strange behaviour when running tests with SBT or editing in the Scala IDE.
Given the following:
package com.abc.rest
import com.abc.utility.IdTLabel
I will get the following error:
object utility is not a member of package com.abc.rest.com.abc
Notice that com.abc is repeated twice, so it appears that the compiler uses the context of the current package when doing the import (maybe it's supposed to do this, but I never noticed it before).
Also, if I try to access classes in package com.abc from anywhere inside com.abc.rest (even using the full path) the compiler will complain that the type can not be found.
It appears that the errors only occur when I try to include files from parent packages. What I do find strange is that my code used to work. It only started happening after I cleaned up my project and my ivy cache, so maybe a later version of the compiler is more strict than the previous one.
I would love some ideas on what I can be doing wrong, or how I can go about troubleshooting this.
Update:
By first importing the parent classes and then defining the current package, the problem goes away:
import com.abc.utility.IdTLabel
import com.abs._
package com.abc.rest {
// Define classes belonging to com.abc.rest here
}
So this works, but I would still love to know why on earth the other way around worked, and then stopped working, and how on earth I can fix it. I had a good look, and could find no packages, objects or traits by the name of com anywhere inside the parent package.
Update relating to Worksheets:
Scala worksheets belonging to the same package share the same scope, which sounds obvious, but wasn't. Worksheets are not sand-boxed - they can see the project, and the project can see them. So all the 'test' object, traits, and classes you create inside the worksheet files, also becomes visible in the rest of the project.
I have so many worksheets that I did not even try to see where the problem came in. I simply moved them all to their own package, and like magic, the problem went away.
So, lesson learned for the day: If you create stuff inside worksheets, it's visible from outside the worksheet.
Anyway, this new found knowledge will come in handy, meaning anything 'interesting' can be build, monitored and tweaked inside the worksheet, while the rest of the project can actually use it. Quite cool actually.
It's still interesting to think how a sbt clean and cleaned up ivy cache managed to highlight the problem that was hidden before, but hey, that's another story....
(At the request of JacobusR, I'm making a proper answer out of my earlier comments).
This can happen if you have defined some class/trait/object inside package com.abc.rest.com. As soon as package com.abc.rest.com exists, and given that you are in package com.abc.rest, com would designate com.abc.rest.com as opposed to _root_.com. Fastest (but non-conclusive) way to check, without even scanning the source files, is to look for any .class files in the "com/abc/rest/com" sub-folder.
In particular you would get this behaviour if any of your files has duplicate package definitions (as in package com.abc.rest; package com.abc.rest; ...). If you have this duplicate package clause somewhere in the same file where you get the error, you wouldn't even see anything fishy with the .class files, as the failure at compiling the file would prevent the generation of .class files for any class definition inside the file.
The final bit of useful information is that as you found out the scala Worksheets are not sandboxed, and what you define in the worksheets affects your project's code (rather than only having the project's code affecting the worksheet). So a duplicate package clause in a worksheet could very well cause the error you got.
If package names conflict, there might be a custom error message for that. See if specifying the full path resolves the issue by starting from __root__. Ex. import __root__.com.foo.bar._

Problems compiling routes after migrating to Play 2.1

After migrating to Play-2.1 I stuck into problem that routes compiler stopped working for my routes file. It's been completely fine with Play-2.0.4, but now I'm getting the build error and can't find any workaround for it.
In my project I'm using cake pattern, so controller actions are visible not through <package>.<controller class>.<action>, but through <package>.<component registry>.<controller instance>.<action>. New Play routes compiler is using all action path components except for the last two to form package name that will be used in managed sources (as far as I can get code in https://github.com/playframework/Play20/blob/2.1.0/framework/src/routes-compiler/src/main/scala/play/router/RoutesCompiler.scala). In my case it leads to situation when <package>.<component registry> is chosen as package name, which results in error during build:
[error] server/target/scala-2.10/src_managed/main/com/grumpycats/mmmtg/componentsRegistry/routes.java:5: componentsRegistry is already defined as object componentsRegistry
[error] package com.grumpycats.mmmtg.componentsRegistry;
I made the sample project to demonstrate this problem: https://github.com/rmihael/play-2.1-routes-problem
Is it possible to workaround this problem somehow without dropping cake pattern for controllers? It's the pity that I can't proceed with Play 2.1 due to this problem.
Because of reputation I can not create a comment.
The convention is that classes and objects start with upper case. This convention is applied to pattern matching as well. Looking at a string there seems to be no difference between a package object and normal object (appart from the case). I am not sure how Play 2.1 handles things, that's why this is not an answer but a comment.
You could try the new # syntax in the router. That allows you to create an instance from the Global class. You would still specify <package>.<controller class>.<action>, but in the Global you get it from somewhere else (for example a component registry).
You can find a bit of extra information here under the 'Managed Controller classes instantiation': http://www.playframework.com/documentation/2.1.0/Highlights
This demo project shows it's usage: https://github.com/guillaumebort/play20-spring-demo

Executing Scala objects in Eclipse without a main method

I have an assignment to code several methods in Scala. The methods will be encapsulated in an object that has no main method. The professor gave us a JAR file that contains an interface (my object implements this interface) as well as a sort of pseudo test object that performs various assert statements against each of my functions. This object also does not contain a main method.
Now in Intellij I simply had to declare the dependency on the JAR in the classpath, and it runs fine. Eclipse is giving me trouble though because when I go to define a Scala application run configuration it specifically asks me to name the class that contains a main method, and there is no main method.
I am assuming that I might be choosing the wrong project type for this type of set up, but I am inexperienced with this and I would appreciate any advice you might have for running something like this in eclipse.
Thanks.
I would either:
just write an object with a main method which calls the test object, or
start a Scala interpreter in your project (from context menu, under Scala).
Preferring the first approach, because it's faster to repeat tests after a modification.

Importing Groovy classes in a GWT module in Intellij

Basically I can't even import Groovy classes in a regular GWT EntryPoint:
import com.google.gwt.core.client.EntryPoint; // OK
import groovy.lang.Binding; // NOT OK
import groovy.util.GroovyScriptEngine; // NOT OK
Intellij 8.0's inspector keeps telling me this:
Class 'groovy.lang.Binding' is not present in JRE Emulation Library so it cannot be used in client code
Class 'groovy.util.GroovyScriptEngine' is not present in JRE Emulation Library so it cannot be used in client code
Obviously I end up having problems at runtime as well:
[ERROR] Line 11: No source code is available for type groovy.util.GroovyScriptEngine; did you forget to inherit a required module?
[ERROR] Line 12: No source code is available for type groovy.lang.Binding; did you forget to inherit a required module?
I've checked several times my module's dependencies, and groovy-all-1.6.1.jar is correctly defined in there. I'm probably missing something elsewhere...
Any idea?
Attempting to use Groovy makes no sense as the Gwt compiler only understands the Java language syntax along it it's subset of Java libraries. The compiler works on source not byte code. One reason includes the magic comments necessary to stash javascript (JSNI). The compiler is actually scanning the source path for *.java not *.class files.
Read the doco fir a more in depth understanding.
In some sense it would be pretty cool to have a groovy language gwt.
But then why go from one dynamic language to another? The point of gwt I thought was to get static typing and easy debugging of java.