В IntelliJ (2024.1.1) с плагином Scala (2024.1.20) Main.main завершается с ошибкой: «Не удалось найти или загрузить основной класс org.public_domain.main»

ОБНОВЛЯТЬ: Глубоко внутри общепринятого ответа находится способ исправить это; то есть переименуйте метод с main на что-нибудь другое или переименуйте object Main на что-нибудь другое.

Конфликт — это проблема нечувствительности к регистру в файловой системе Windows (или MacOS), где наличие одного и того же регистронезависимого значения для методов, отмеченных object и @main, создает проблему.

Будем надеяться, что ребята из IntelliJ Scala Plugin смогут добавить это в свою потрясающую «автоматическую систему предупреждений», чтобы никто больше не попал в эту кроличью нору Scala 3.


ОБНОВЛЕНИЕ После дальнейшего расследования... Это работает в Scastie , настоятельно предполагая, что это проблема плагина IntelliJ Scala ( Билет Jetbrains YouTrack).


После создания нового проекта Scala 3.3.3 в IntelliJ (2024.1.1) с плагином Scala (2024.1.20) мой метод «синтаксиса без скобок» Main.main дает сбой: «Не удалось найти или загрузить основной класс org.public_domain.main» .

Должно быть, я упускаю что-то совершенно очевидное. Однако после часа возни с этим я сдаюсь. Что мне не хватает?

Вот ЕДИНСТВЕННЫЙ файл, который я создал во всем проекте, и на котором я щелкнул маленькую зеленую стрелку в левом трее метода main, чтобы выбрать «Запустить org.public_domain.main».

package org.public_domain

object Main:
  @main def main(): Unit =
    println("Hello World!")

SideNote: я заметил, что IntelliJ неправильно называет org.public_domain.Main.main методом, который я использую.

Кстати, если я закомментирую object Main: (чего мне очень не хочется делать), всё работает нормально.

IOW, это отлично работает:

package org.public_domain

@main def main(): Unit =
  println("Hello World!")

Из-за такой ерунды тем, кто начинает работать со Scala, так трудно придерживаться ее. Количество глупых технических нюансов, с которыми мне приходится сталкиваться при создании проекта Scala, по сути, меня расстраивает, поскольку я никогда полностью не попадаю в сверхпродуктивное состояние «потока». И я ОБОЖАЮ Scala и выступаю за Scala с января 2011 года.

chaotic3quilibrium 18.05.2024 17:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
116
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  • Если посылка org.public_domain в
package org.public_domain

object Main:
  @main def main(): Unit =
    println("Hello World!")

то этот файл Main.scala следует разместить по адресу /path/to/yourproject/src/main/scala/org/public_domain/Main.scala

  • Затем запуск sbt run из корня вашего проекта распечатывает 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. Если вы используете файловую систему без учета регистра (например, Windows или MacOS), измените имя вашего метода, например
package org.public_domain

object Main:
  @main def run(): Unit =
    println("Hello World!")
  • Посмотрите в каталоге target/scala-3.3.3/classes/org/public_domain. Должно быть создано несколько классов (с именем объекта и именем метода, аннотированным @main):
$ cd target/scala-3.3.3/classes/org/public_domain
$ ls
main.class  Main.class  Main$.class  main.tasty  Main.tasty

(или run.class вместо main.class, если вы переименовали метод).


плагин IntelliJ Scala неправильно вызывает org.public_domain.main, а не правильно org.public_domain.Main.main

Я рад, если вы решили свои проблемы, но боюсь, что вы можете неправильно истолковать свои выводы. По крайней мере, я вижу некоторую путаницу. Здесь есть несколько классов: Main.class, Main$.class, main.class (или run.class, если мы переименовали метод). Main.class и Main$.class представляют объект, main.class представляет аннотированный @main метод. Следует вызывать именно класс org.public_domain.main (у него есть работоспособный метод public static void main(java.lang.String[])), а не org.public_domain.Main (у него нет main(String[])). Вы можете увидеть методы в классах с помощью 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[]);
}

Если вы запускаете свой код с помощью IntelliJ IDEA, а не с помощью sbt (я рекомендовал последний), вы можете настроить, что запускать, в меню Run -> Edit configurations

IntelliJ записывает точную выполняемую команду:

По умолчанию он свернут. Если щелкнуть, он расширяется. Для меня это

/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

Теперь его можно сократить до

$ 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!

Хотя я ценю ваш подробный ответ, он не решает основную проблему, которую я выявил (нажав на зеленую стрелку и выбрав «Выполнить» из Intellij). Однако это подтверждает вывод, к которому я предварительно пришел после посещения класса Main в Скасти; то есть плагин IntelliJ Scala неправильно вызывает org.public_domain.main, а не правильно org.public_domain.Main.main.

chaotic3quilibrium 18.05.2024 19:40

Ах. Я только что увидел ваше переименование предложения метода main. И ЭТО решает проблему.

chaotic3quilibrium 18.05.2024 19:48

@chaotic3quilibrium Итак, вы используете Windows или MacOS

Dmytro Mitin 18.05.2024 19:59

Вы правильно догадались, что я на Windows.

chaotic3quilibrium 18.05.2024 20:03

Я не понимаю, откуда взялся main.class. Я понимаю Main.class и Main$.class. Однако main — это метод в Main, а не класс. Итак, что именно происходит за аннотацией @main? Генерирует ли он скрытый вложенный main класс Scala, как следует из вашего последнего снимка экрана? Если так, то даже с моим нынешним обширным опытом работы со Scala я бы ни за что не догадался об этом.

chaotic3quilibrium 18.05.2024 20:11

Кстати, в версии IntelliJ, которую я использую в Windows, у меня нет sbt в Терминале (генерирует странную ошибку). Вместо этого мне приходится использовать вкладку «оболочка sbt», доступную в нижней части панели (рядом с Git, «Выполнить», «Профилировщик», «Сборка», «Службы» и т. д.). И когда я запускаю «оболочку sbt» и жду завершения ее инициализации, команда, позволяющая заставить ее делать то, что вы делаете на терминале, — «запустить», а не «запустить sbt». Оказывается, вводить «sbt{space}» в «sbtshell» совершенно не нужно. Эта оболочка предполагает префикс «sbt{space}» для каждой введенной команды.

chaotic3quilibrium 18.05.2024 20:19

@chaotic3quilibrium Вы можете установить sbt вне IDE scala-sbt.org

Dmytro Mitin 18.05.2024 20:37

Tysvm за это. Похоже, вы подтверждаете, что аннотация @main на самом деле вызывает сборку и компиляцию целого класса object main Scala в фоновом режиме. IOW, это основная причина конфликта. И именно поэтому переименование его в run превращает его в класс object run Scala, который создается и компилируется в фоновом режиме, что разрешает конфликт.

chaotic3quilibrium 18.05.2024 20:39

@chaotic3quilibrium Если вы устанавливаете sbt вне IDE, то в терминале вне IDE вы можете выполнить sbt some_command, например sbt clean, sbt compile, sbt run. Или вы можете запустить sbt в интерактивном режиме, просто нажав sbt, и выполнить там clean, compile, run. Если вы выполните sbt some_command в терминале внутри IDE или some_command в sbt-оболочке IDE, то IDE сможет перехватить вашу команду (IDE имеет /home/dmitin/.local/share/JetBrains/IntelliJIdea2024.1/Scala‌​/launcher/sbt-launch‌​.jar при установке).

Dmytro Mitin 18.05.2024 20:46

Другие вопросы по теме