All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.build.preprocessing.DeprecatedDirectives.scala Maven / Gradle / Ivy

package scala.build.preprocessing

import scala.build.Logger
import scala.build.errors.Diagnostic.TextEdit
import scala.build.internal.Constants
import scala.build.internal.util.WarningMessages.{deprecatedToolkitLatest, deprecatedWarning}
import scala.build.preprocessing.directives.{
  DirectiveHandler,
  DirectiveUtil,
  StrictDirective,
  Toolkit
}
import scala.build.warnings.DeprecatedWarning

object DeprecatedDirectives {

  /** Used to represent a general form of a deprecated directive, and its replacement
    * @param keys
    *   representation of deprecated keys
    * @param values
    *   representation of deprecated value
    */
  case class DirectiveTemplate(keys: Seq[String], values: Option[Seq[String]]) {
    def appliesTo(foundKey: String, foundValues: Seq[String]): Boolean =
      (keys.isEmpty || keys.contains(foundKey)) &&
      // FIXME values.contains is not perfect, but is enough for now since we don't look for specific multiple values
      (values.isEmpty || values.contains(foundValues))
  }

  type WarningAndReplacement = (String, DirectiveTemplate)

  private def keyReplacement(replacement: String)(warning: String): WarningAndReplacement =
    (warning, DirectiveTemplate(Seq(replacement), None))

  private def valueReplacement(replacements: String*)(warning: String): WarningAndReplacement =
    (warning, DirectiveTemplate(Nil, Some(replacements.toSeq)))

  private def allAliasesOf(key: String, handler: DirectiveHandler[_]): Seq[String] =
    handler.keys.find(_.nameAliases.contains(key))
      .toSeq
      .flatMap(_.nameAliases)

  private def allKeysFrom(handler: DirectiveHandler[_]): Seq[String] =
    handler.keys.flatMap(_.nameAliases)

  private val deprecatedCombinationsAndReplacements = Map[DirectiveTemplate, WarningAndReplacement](
    DirectiveTemplate(Seq("lib"), None) -> keyReplacement("dep")(deprecatedWarning("lib", "dep")),
    DirectiveTemplate(Seq("libs"), None) -> keyReplacement("dep")(deprecatedWarning(
      "libs",
      "deps"
    )),
    DirectiveTemplate(Seq("compileOnly.lib"), None) -> keyReplacement("compileOnly.dep")(
      deprecatedWarning("compileOnly.lib", "compileOnly.dep")
    ),
    DirectiveTemplate(Seq("compileOnly.libs"), None) -> keyReplacement("compileOnly.dep")(
      deprecatedWarning("compileOnly.libs", "compileOnly.deps")
    ),
    DirectiveTemplate(
      allKeysFrom(directives.Toolkit.handler),
      Some(Seq("latest"))
    ) -> valueReplacement("default")(deprecatedToolkitLatest()),
    DirectiveTemplate(
      allKeysFrom(directives.Toolkit.handler),
      Some(Seq(s"${Toolkit.typelevel}:latest"))
    ) -> valueReplacement(s"${Toolkit.typelevel}:default")(
      deprecatedToolkitLatest()
    ),
    DirectiveTemplate(
      allKeysFrom(directives.Toolkit.handler),
      Some(Seq(s"${Constants.typelevelOrganization}:latest"))
    ) -> valueReplacement(s"${Toolkit.typelevel}:default")(
      deprecatedToolkitLatest()
    )
  )

  def warningAndReplacement(directive: StrictDirective): Option[WarningAndReplacement] =
    deprecatedCombinationsAndReplacements
      .find(_._1.appliesTo(directive.key, directive.toStringValues))
      .map(_._2) // grab WarningAndReplacement

  def issueWarnings(
    path: Either[String, os.Path],
    directives: Seq[StrictDirective],
    logger: Logger
  ) =
    directives.map(d => d -> warningAndReplacement(d))
      .foreach {
        case (directive, Some(warning, replacement)) =>
          val newKey    = replacement.keys.headOption.getOrElse(directive.key)
          val newValues = replacement.values.getOrElse(directive.toStringValues)
          val newText   = s"$newKey ${newValues.mkString(" ")}"

          // TODO use key and/or value positions instead of whole directive
          val position = directive.position(path)

          val diagnostic = DeprecatedWarning(
            warning,
            Seq(position),
            Some(TextEdit(s"Change to: $newText", newText))
          )
          logger.log(Seq(diagnostic))
        case _ => ()
      }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy