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

scala.build.info.ScopedBuildInfo.scala Maven / Gradle / Ivy

package scala.build.info

import coursier.ivy.IvyRepository
import coursier.maven.MavenRepository
import coursier.{Dependency, LocalRepositories, Repositories}
import dependency.AnyDependency

import java.nio.charset.StandardCharsets

import scala.build.options.{BuildOptions, ConfigMonoid}
import scala.reflect.io.Path

final case class ScopedBuildInfo(
  sources: Seq[String] = Nil,
  scalacOptions: Seq[String] = Nil,
  scalaCompilerPlugins: Seq[ExportDependencyFormat] = Nil,
  dependencies: Seq[ExportDependencyFormat] = Nil,
  compileOnlyDependencies: Seq[ExportDependencyFormat] = Nil,
  resolvers: Seq[String] = Nil,
  resourceDirs: Seq[String] = Nil,
  customJarsDecls: Seq[String] = Nil
) {
  def +(other: ScopedBuildInfo): ScopedBuildInfo =
    ScopedBuildInfo.monoid.orElse(this, other)

  def generateContentLines(): Seq[String] =
    Seq(
      Seq("/** sources found for the scope */", "val sources = ")        -> sources,
      Seq("/** scalac options for the scope */", "val scalacOptions = ") -> scalacOptions,
      Seq(
        "/** compiler plugins used in this scope */",
        "val scalaCompilerPlugins = "
      ) -> scalaCompilerPlugins.map(_.toString()),
      Seq("/** dependencies used in this scope */", "val dependencies = ") -> dependencies.map(
        _.toString()
      ),
      Seq("/** dependency resolvers used in this scope */", "val resolvers = ")    -> resolvers,
      Seq("/** resource directories used in this scope */", "val resourceDirs = ") -> resourceDirs,
      Seq("/** custom jars added to this scope */", "val customJarsDecls = ") -> customJarsDecls
    ).flatMap { case (Seq(scaladoc, prefix), values) =>
      val sb = new StringBuilder
      sb.append(prefix)
      if (values.isEmpty) sb.append("Nil")
      else sb.append {
        values.map(str => s"\"${BuildInfo.escapeBackslashes(str)}\"")
          .mkString("Seq(", ", ", ")")
      }
      Seq(scaladoc, sb.toString())
    }
}

object ScopedBuildInfo {
  def empty: ScopedBuildInfo = ScopedBuildInfo()

  def apply(options: BuildOptions, sourcePaths: Seq[String]): ScopedBuildInfo =
    Seq(
      ScopedBuildInfo(sources = sourcePaths),
      scalaCompilerPlugins(options),
      scalacOptionsSettings(options),
      dependencySettings(options),
      repositorySettings(options),
      customResourcesSettings(options),
      customJarsSettings(options)
    )
      .reduceLeft(_ + _)

  private def scalacOptionsSettings(options: BuildOptions): ScopedBuildInfo =
    ScopedBuildInfo(scalacOptions = options.scalaOptions.scalacOptions.toSeq.map(_.value.value))

  private def scalaCompilerPlugins(options: BuildOptions): ScopedBuildInfo =
    val compilerPlugins = options.scalaOptions.compilerPlugins.map(_.value)
      .map(ExportDependencyFormat(_, options.scalaParams.getOrElse(None)))

    ScopedBuildInfo(scalaCompilerPlugins = compilerPlugins)

  private def dependencySettings(options: BuildOptions): ScopedBuildInfo = {
    val directDeps = options.classPathOptions.extraDependencies.toSeq.map(_.value)
      .map(ExportDependencyFormat(_, options.scalaParams.getOrElse(None)))
    val compileDeps = options.classPathOptions.extraCompileOnlyDependencies.toSeq.map(_.value)
      .map(ExportDependencyFormat(_, options.scalaParams.getOrElse(None)))

    ScopedBuildInfo(
      dependencies = directDeps,
      compileOnlyDependencies = compileDeps
    )
  }

  private def repositorySettings(options: BuildOptions): ScopedBuildInfo = {
    val resolvers = options.finalRepositories
      .getOrElse(Nil)
      .appended(Repositories.central)
      .appended(LocalRepositories.ivy2Local)
      .collect {
        case repo: MavenRepository => repo.root
        case repo: IvyRepository   => s"ivy:${repo.pattern.string}"
      }
      .distinct

    ScopedBuildInfo(resolvers = resolvers)
  }

  private def customResourcesSettings(options: BuildOptions): ScopedBuildInfo =
    ScopedBuildInfo(resourceDirs = options.classPathOptions.resourcesDir.map(_.toNIO.toString))

  private def customJarsSettings(options: BuildOptions): ScopedBuildInfo = {

    val customCompileOnlyJarsDecls =
      options.classPathOptions.extraCompileOnlyJars.map(_.toNIO.toString)

    val customJarsDecls = options.classPathOptions.extraClassPath.map(_.toNIO.toString)

    ScopedBuildInfo(
      customJarsDecls = customCompileOnlyJarsDecls ++ customJarsDecls
    )
  }

  private val charSet = StandardCharsets.UTF_8

  implicit val monoid: ConfigMonoid[ScopedBuildInfo] = ConfigMonoid.derive
}

final case class ExportDependencyFormat(groupId: String, artifactId: ArtifactId, version: String) {
  override def toString(): String = {
    val sb = new StringBuilder
    sb.append(groupId)
    sb.append(':')
    sb.append(artifactId.fullName)
    sb.append(':')
    sb.append(version)
    sb.toString()
  }
}

final case class ArtifactId(name: String, fullName: String)

object ExportDependencyFormat {
  def apply(dep: Dependency): ExportDependencyFormat = {
    val scalaVersionStartIndex = dep.module.name.value.lastIndexOf('_')
    val shortDepName = if (scalaVersionStartIndex == -1)
      dep.module.name.value
    else
      dep.module.name.value.take(scalaVersionStartIndex)
    new ExportDependencyFormat(
      dep.module.organization.value,
      ArtifactId(shortDepName, dep.module.name.value),
      dep.version
    )
  }

  def apply(
    dep: AnyDependency,
    scalaParamsOpt: Option[dependency.ScalaParameters]
  ): ExportDependencyFormat = {
    import scala.build.internal.Util.*
    dep.toCs(scalaParamsOpt)
      .map(ExportDependencyFormat.apply)
      .getOrElse(
        ExportDependencyFormat(
          dep.module.organization,
          ArtifactId(dep.module.name, dep.module.name),
          dep.version
        )
      )
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy