Поиск значения приводит к неправильной области видимости в плагине sbt - PullRequest
3 голосов
/ 01 октября 2019

Я пытаюсь написать плагин для sbt для моего проекта, который будет обрабатывать ресурсы. В двух словах, это maven профили, сделанные в sbt. Когда я проверяю prod:dictionary, я получаю ожидаемое состояние этого Map, однако, когда я пытаюсь prod:expandParameters, я получаю пустое Map. Как я могу получить значение dictionary из области точной конфигурации, с которой запускается команда?

project / ResourceFiltering.scala

import sbt._
import sbt.Keys._
import sbt.internal.util.ManagedLogger
import scala.util.matching.Regex

object ResourceFiltering extends AutoPlugin {

  override def trigger = AllRequirements

  sealed trait Keys {
    lazy val expandParameters = taskKey[Unit]("")

    lazy val extensions = settingKey[Seq[String]]("")
    lazy val pattern    = settingKey[Regex]("")
    lazy val dictionary = settingKey[Map[String, String]]("")
  }

  object autoImport extends Keys

  import autoImport._

  override val projectSettings: Seq[Def.Setting[_]] = Seq(
    Zero / extensions := Seq("conf", "properties", "xml"),
    Zero / pattern    := """(\$\{()\})""".r,
    Zero / dictionary := Map.empty,
    expandParameters := {
      val log: ManagedLogger = streams.value.log
      log.info(s"""|Parameter expansion
                   |Configuration: $configuration
                   |Extensions: ${extensions value}
                   |Pattern: ${pattern value}
                   |Dictionary: ${dictionary value}
                """.stripMargin)
    }
  )
}

build.sbt

enablePlugins(ResourceFiltering)

lazy val Prod  = config("prod")  extend Compile describedAs "Scope to build production packages."
lazy val Stage = config("stage") extend Compile describedAs "Scope to build stage packages."
lazy val Local = config("local") extend Compile describedAs "Scope to build local packages."

lazy val root = (project in file("."))
  .configs(Prod, Stage, Local)
  .settings(sharedSettings)

lazy val sharedSettings = 
  prodSettings ++ stageSettings ++ localSettings

lazy val defaults = Defaults.configSettings ++ Defaults.configTasks ++ Defaults.resourceConfigPaths

lazy val prodSettings = inConfig(Prod)(defaults ++ Seq(
  dictionary ++= Profiles.prod
))

lazy val stageSettings = inConfig(Stage)(defaults ++ Seq(
  dictionary ++= Profiles.stage
))

lazy val localSettings = inConfig(Local)(defaults ++ Seq(
  dictionary ++= Profiles.local
))

project / Profiles.scala

lazy val default: Map[String, String] = local

lazy val local: Map[String, String] = Map("example" -> "local")

lazy val stage: Map[String, String] = Map("example" -> "stage")

lazy val prod: Map[String, String] = Map("example" -> "prod")

1 Ответ

2 голосов
/ 02 октября 2019

Анализ Рекомендации по подключаемым модулям Документы Я бы сделал следующие рекомендации относительно конфигурации и области видимости.

Укажите значения по умолчанию в globalSettings вместо projectSettings, например,

override lazy val globalSettings = Seq(
  dictionary := Map.empty
)

Далее соберите базовую конфигурацию expandParameters в ее собственную последовательность следующим образом:

lazy val baseResourceFilteringSettings: Seq[Def.Setting[_]] = Seq(
  extensions := Seq("conf", "properties", "xml"),
  pattern := """(\$\{()\})""".r,
  expandParameters := {
    val log: ManagedLogger = streams.value.log
    log.info(
      s"""|Parameter expansion
          |Configuration: $configuration
          |Extensions: ${extensions value}
          |Pattern: ${pattern value}
          |Dictionary: ${dictionary value}
       """.stripMargin
    )
  }
)

Обратите внимание, что dictionary не инициализируется в baseResourceFilteringSettings, вместо этого по умолчанию он будет получен из globalSettings.

Теперь мы позаботились о наших настройках по умолчанию, и у нас есть базовая конфигурация, поэтому мы можем приступить к ее «специализации» в соответствии с областью конфигурации, используя inConfig, например,

lazy val localSettings = inConfig(Local)(defaults ++ Seq(
  dictionary ++= Profiles.local
) ++ baseResourceFilteringSettings)

Примечание. как мы расширили baseResourceFilteringSettings до Local конфигурации, а также dictionary ++= Profiles.local.

Теперь выполнение ;reload;local:expandParameters должно вывести

[info] Parameter expansion
[info] Configuration: SettingKey(This / This / This / configuration)
[info] Extensions: List(conf, properties, xml)
[info] Pattern: (\$\{()\})
[info] Dictionary: Map(example -> local)

, где мы видим Dictionary: Map(example -> local) как требуется.

Вот полный код ResourceFiltering

object ResourceFiltering extends AutoPlugin {

  override def trigger = AllRequirements

  sealed trait Keys {
    lazy val expandParameters = taskKey[Unit]("")

    lazy val extensions = settingKey[Seq[String]]("")
    lazy val pattern = settingKey[Regex]("")
    lazy val dictionary = settingKey[Map[String, String]]("")

    lazy val baseResourceFilteringSettings: Seq[Def.Setting[_]] = Seq(
      extensions := Seq("conf", "properties", "xml"),
      pattern := """(\$\{()\})""".r,
      expandParameters := {
        val log: ManagedLogger = streams.value.log
        log.info(
          s"""|Parameter expansion
              |Configuration: $configuration
              |Extensions: ${extensions value}
              |Pattern: ${pattern value}
              |Dictionary: ${dictionary value}
           """.stripMargin
        )
      }
    )
  }

  object autoImport extends Keys
  import autoImport._

  override lazy val globalSettings = Seq(
    dictionary := Map.empty
  )
}

Также рассмотрите возможность перемещения определений конфигурации в плагин следующим образом:

object ResourceFiltering extends AutoPlugin {

  override def trigger = AllRequirements

  sealed trait Keys {
    lazy val Prod = config("prod") extend Compile describedAs "Scope to build production packages."
    lazy val Stage = config("stage") extend Compile describedAs "Scope to build stage packages."
    lazy val Local = config("local") extend Compile describedAs "Scope to build local packages."

    lazy val expandParameters = taskKey[Unit]("")

    lazy val extensions = settingKey[Seq[String]]("")
    lazy val pattern = settingKey[Regex]("")
    lazy val dictionary = settingKey[Map[String, String]]("")

    lazy val baseResourceFilteringSettings: Seq[Def.Setting[_]] = Seq(
      extensions := Seq("conf", "properties", "xml"),
      pattern := """(\$\{()\})""".r,
      expandParameters := {
        val log: ManagedLogger = streams.value.log
        log.info(
          s"""|Parameter expansion
              |Configuration: $configuration
              |Extensions: ${extensions value}
              |Pattern: ${pattern value}
              |Dictionary: ${dictionary value}
           """.stripMargin
        )
      }
    )
  }

  object autoImport extends Keys
  import autoImport._

  override lazy val globalSettings = Seq(
    dictionary := Map.empty
  )

  override val projectSettings: Seq[Def.Setting[_]] =
    inConfig(Stage)(baseResourceFilteringSettings) ++
      inConfig(Prod)(baseResourceFilteringSettings) ++
      inConfig(Local)(baseResourceFilteringSettings)
}

Таким образом, нам не нужноне забудьте добавить baseResourceFilteringSettings в конфигурационную область и можете просто записатье

lazy val localSettings = inConfig(Local)(defaults ++ Seq(
  dictionary ++= Profiles.local
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...