UPDATE:
Nestled deep within the large accepted answer is the way to fix this; i.e. rename the method from main
to something else, or rename the object Main
to something else.
The conflict is a case insensitivity issue on the Windows (or MacOS) file system where having both the object
and the @main
marked method be the same case-insensitive value creates an issue.
Hopefully, the IntelliJ Scala Plugin guys can add this to their awesome "automated warnings system", so no one else falls into this Scala 3 rabbit hole.
UPDATE Older: Upon further investigation...This works in Scastie strongly suggesting it is an IntelliJ Scala Plugin issue (Jetbrains YouTrack ticket).
After creating a new Scala 3.3.3 project in IntelliJ(2024.1.1) with the Scala Plugin(2024.1.20), my "braceless syntax" Main.main
method is failing with "Could not find or load main class org.public_domain.main".
I must be missing something totally obvious. However, after an hour of tinkering with it, I give up. What am I missing?
Here's the ONLY file I've created in the entire project, and upon which I clicked the small green arrow in the left tray of the main
method to select "Run org.public_domain.main".
package org.public_domain
object Main:
@main def main(): Unit =
println("Hello World!")
SideNote: I'm noticing IntelliJ isn't properly referring to org.public_domain.Main.main
as the method I am running.
BTW, if I comment out object Main:
(which I very much do not want to do), it runs fine.
IOW, this works fine:
package org.public_domain
@main def main(): Unit =
println("Hello World!")
org.public_domain
inpackage org.public_domain
object Main:
@main def main(): Unit =
println("Hello World!")
then this file Main.scala
should be placed at /path/to/yourproject/src/main/scala/org/public_domain/Main.scala
sbt run
from the root of your project prints Hello World!
$ sbt run
[info] welcome to sbt 1.10.0 (Amazon.com Inc. Java 21.0.3)
[info] loading global plugins from /home/dmitin/.sbt/1.0/plugins
[info] loading project definition from /path/to/yourproject/project
[info] loading settings for project root from build.sbt ...
[info] set current project to yourproject (in build file:/path/to/yourproject/)
[info] compiling 1 Scala source to /path/to/yourproject/target/scala-3.3.3/classes ...
[warn] -- Warning: /path/to/yourproject/src/main/scala/org/public_domain/Main.scala:3:7
[warn] 3 |object Main:
[warn] | ^
[warn] |object Main differs only in case from class main in package org.public_domain. Such classes will overwrite one another on case-insensitive filesystems.
[warn] one warning found
[info] running org.public_domain.main
Hello World!
[success] Total time: 3 s, completed 18 мая 2024 г., 20:06:05
object Main differs only in case from class main in package org.public_domain. Such classes will overwrite one another on case-insensitive filesystems
. If you are on a case-insensitive filesystem (for example Windows or MacOS) then change the name of your method, for examplepackage org.public_domain
object Main:
@main def run(): Unit =
println("Hello World!")
target/scala-3.3.3/classes/org/public_domain
. There should be created several classes (with object name and @main
-annotated method name):$ cd target/scala-3.3.3/classes/org/public_domain
$ ls
main.class Main.class Main$.class main.tasty Main.tasty
(or run.class
instead of main.class
if you renamed the method).
Getting started: https://docs.scala-lang.org/getting-started/index.html
Sbt directory structure: https://www.scala-sbt.org/1.x/docs/Directories.html
the IntelliJ Scala plugin is incorrectly invoking
org.public_domain.main
as opposed to correctly invokingorg.public_domain.Main.main
I'm glad if you resolved your issues but I'm afraid you could misinterpret your findings. At least I can see some confusion. There are several classes here: Main.class
, Main$.class
, main.class
(or run.class
if we renamed the method). Main.class
and Main$.class
represent the object, main.class
represents the @main
-annotated method. It's exactly the class org.public_domain.main
that should be called (it has runnable method public static void main(java.lang.String[])
), not org.public_domain.Main
(it doesn't have main(String[])
). You can see methods in classes with javap
:
$ cd /path/to/yourproject/target/scala-3.3.3/classes/org/public_domain/
$ ls
main.class Main.class Main$.class main.tasty Main.tasty
$ cd /path/to/yourproject/target/scala-3.3.3/classes
$ javap org.public_domain.Main
Compiled from "Main.scala"
public final class org.public_domain.Main {
public static void main();
}
$ javap org.public_domain.Main$
Compiled from "Main.scala"
public final class org.public_domain.Main$ implements java.io.Serializable {
public static final org.public_domain.Main$ MODULE$;
public static {};
public void main();
}
$ javap org.public_domain.main
Compiled from "Main.scala"
public final class org.public_domain.main {
public org.public_domain.main();
public static void main(java.lang.String[]);
}
If you run your code with IntelliJ IDEA rather than with sbt (I recommended the latter) then you can configure what to run in the menu Run -> Edit configurations
IntelliJ writes the exact command that is run:
By default it's collapsed. If you click it expands. For me it's
/media/data/jdk1.8.0_351/bin/java -javaagent:/media/data/idea-IU-241.15989.150/lib/idea_rt.jar=38299:/media/data/idea-IU-241.15989.150/bin -Dfile.encoding=UTF-8 -classpath /media/data/jdk1.8.0_351/jre/lib/charsets.jar:/media/data/jdk1.8.0_351/jre/lib/deploy.jar:/media/data/jdk1.8.0_351/jre/lib/ext/cldrdata.jar:/media/data/jdk1.8.0_351/jre/lib/ext/dnsns.jar:/media/data/jdk1.8.0_351/jre/lib/ext/jaccess.jar:/media/data/jdk1.8.0_351/jre/lib/ext/jfxrt.jar:/media/data/jdk1.8.0_351/jre/lib/ext/localedata.jar:/media/data/jdk1.8.0_351/jre/lib/ext/nashorn.jar:/media/data/jdk1.8.0_351/jre/lib/ext/sunec.jar:/media/data/jdk1.8.0_351/jre/lib/ext/sunjce_provider.jar:/media/data/jdk1.8.0_351/jre/lib/ext/sunpkcs11.jar:/media/data/jdk1.8.0_351/jre/lib/ext/zipfs.jar:/media/data/jdk1.8.0_351/jre/lib/javaws.jar:/media/data/jdk1.8.0_351/jre/lib/jce.jar:/media/data/jdk1.8.0_351/jre/lib/jfr.jar:/media/data/jdk1.8.0_351/jre/lib/jfxswt.jar:/media/data/jdk1.8.0_351/jre/lib/jsse.jar:/media/data/jdk1.8.0_351/jre/lib/management-agent.jar:/media/data/jdk1.8.0_351/jre/lib/plugin.jar:/media/data/jdk1.8.0_351/jre/lib/resources.jar:/media/data/jdk1.8.0_351/jre/lib/rt.jar:/media/data/Projects2/scala3demo2/target/scala-3.3.3/classes:/home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.12/scala-library-2.13.12.jar:/home/dmitin/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.3.3/scala3-library_3-3.3.3.jar org.public_domain.main
Now it can be shortened to
$ cd /path/to/yourproject/target/scala-3.3.3/classes
$ java -classpath .:/path_to_jars/scala-library-2.13.12.jar:/path_to_jars/scala3-library_3-3.3.3.jar org.public_domain.main
Hello World!