Плагин sbt динамически загружает пользовательский код?

Я работаю над плагином sbt, который генерирует модели Scala с учетом базы данных, используя Генератор кода

Я бы, конечно, хотел, чтобы пользователи переопределяли генератор кода, поэтому мой плагин должен поддерживать это:

  • В любом случае, я могу динамически загружать класс Scala, учитывая путь к нему в ключах плагина build.sbt? Например, в родительском файле build.sbt пользователя он должен предоставить что-то вроде codegen.override=com.company.project.CustomCodegenerator, которое выглядит так

  • Связано с вышеизложенным; пользовательский codegen может использовать некоторые другие библиотеки, поэтому простой динамической загрузки классов может быть недостаточно. В любом случае, плагин sbt может наследовать зависимости проекта, используя этот плагин?

Вот полное обсуждение этого: https://github.com/papauschek/play-slick-evolutions-plugin/issues/1


person pathikrit    schedule 19.11.2014    source источник
comment
Я не думаю, что вы можете использовать зависимости от проекта в своем плагине из-за разделения загрузчика классов. Но я думаю, что мой ответ на этот вопрос чем-то похож на то, чего вы хотите достичь.   -  person lpiepiora    schedule 14.12.2014
comment
Просто подсказка: не занимайтесь генерацией кода. Рассмотрите возможность использования небольших составных макросов, каждый из которых выполняет особую задачу. Довольно сложно найти ошибки в сгенерированном коде и исправить синтаксические ошибки в сгенерированном коде. С макросами вы управляете AST напрямую, поэтому меньше шансов что-то испортить.   -  person stefan.schwetschke    schedule 14.01.2015
comment
@stefan.schwetschke: Не могли бы вы подробнее объяснить, что вы имеете в виду? Чтобы было ясно, я не писал генератор кода сам, а просто использовал генератор slick. Все, что я делаю, это пишу плагин sbt для его автоматического вызова во время компиляции...   -  person pathikrit    schedule 14.01.2015


Ответы (1)


В конце дня вам нужно запустить некоторый код для создания исходных файлов Scala.

Создание файлов

Как вы знаете, в sbt есть хук для создания исходных файлов под названием sourceGenerators, который задокументирован в Создание файлов. Вы, как автор плагина, должны предоставить задачу, которая генерирует Seq[File] под (sourceManaged in Compile).value / "garfield", используя генератор кода Slick в качестве реализации по умолчанию. Назовем это generateModel. Ваш плагин может иметь следующие настройки:

sourceGenerators in Compile += generateModel.taskValue,
generateModel := defaultGenerateModel.value,
defaultGenerateModel := { ... }

Если пользователь сборки хочет перемонтировать generateModel, он может сделать это следующим образом:

generateModel := {
  val file = (sourceManaged in Compile).value / "garfield" / "Foo.scala"
  IO.write(file, """case class Foo() {}""")
  Seq(file)
}

Если генерация кода содержится в плагине sbt, как указано выше, вам не нужно делать никаких динамических действий. Поскольку play-slick-evolutions-codegen-plugin зависит от slick-codegen, это не должно быть проблемой.

Динамическая загрузка кода пользователя

Поскольку вопрос напрямую связан с динамической загрузкой пользовательского кода, я бы также добавил несколько указателей на это.

  • Один из способов — использовать sbt.Run API из существующая конфигурация. Это эквивалентно вызову задачи run с некоторым настраиваемым параметром. Если вы генерируете код для конфигурации Compile, использование бегуна для любой конфигурации, которая от него зависит, не будет хорошей идеей.
  • Другой аналогичный способ — использовать sbt.ForkAPI. . Форкинг позволяет запускать код вне плагина.

Учитывая, что sbt автоматически упорядочивает задачи на основе зависимостей между ними и запускает несколько задач параллельно, динамическое выполнение кода чревато неожиданными опасностями.

person Eugene Yokota    schedule 09.01.2015