Skip to content

Commit

Permalink
Inherit fields when loading build file
Browse files Browse the repository at this point in the history
Centralise the logic for inheriting settings defined on the project
level or on base modules. Inheritance is now performed during
loading of build files. As a consequence, many functions do not need
to be aware of the project or the parent module anymore which
greatly simplifies the code for generating Bloop and IDEA
configurations.

Also, several missing fields which were only available on the
project-level were added to `Module`.

Closes #18.
  • Loading branch information
tindzk committed Aug 8, 2019
1 parent 3d13b4f commit 940210b
Show file tree
Hide file tree
Showing 24 changed files with 684 additions and 786 deletions.
15 changes: 11 additions & 4 deletions src/main/scala/seed/Cli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,12 @@ ${underlined("Usage:")} seed [--build=<path>] [--config=<path>] <command>
import command._
val config = SeedConfig.load(configPath)
val log = Log(config)
val BuildConfig.Result(build, projectPath, _) =
val BuildConfig.Result(projectPath, modules) =
BuildConfig.load(buildPath, log).getOrElse(sys.exit(1))
cli.Package.ui(
config,
projectPath,
build,
modules,
module,
output,
libs,
Expand All @@ -287,9 +287,16 @@ ${underlined("Usage:")} seed [--build=<path>] [--config=<path>] <command>
) =>
val config = SeedConfig.load(configPath)
val log = Log(config)
val BuildConfig.Result(build, projectPath, _) =
val BuildConfig.Result(projectPath, modules) =
BuildConfig.load(buildPath, log).getOrElse(sys.exit(1))
cli.Generate.ui(config, projectPath, projectPath, build, command, log)
cli.Generate.ui(
config,
projectPath,
projectPath,
modules,
command,
log
)
case Success(Config(configPath, _, command: Command.Server)) =>
val config = SeedConfig.load(configPath)
val log = Log(config)
Expand Down
241 changes: 90 additions & 151 deletions src/main/scala/seed/artefact/ArtefactResolution.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import java.nio.file.Path
import seed.Cli.PackageConfig
import MavenCentral.{CompilerVersion, PlatformVersion}
import seed.cli.util.Ansi
import seed.model.Build.{Dep, JavaDep, Module, ScalaDep}
import seed.model.Build.{Dep, JavaDep, Module, Resolvers, ScalaDep}
import seed.model.Platform.{JVM, JavaScript, Native}
import seed.model.{Artefact, Build, Platform, Resolution}
import seed.model.{Artefact, Platform, Resolution}
import seed.Log
import seed.config.BuildConfig
import seed.config.BuildConfig.Build

object ArtefactResolution {
def javaDepFromScalaDep(
Expand Down Expand Up @@ -52,9 +53,9 @@ object ArtefactResolution {
version
)

def jsPlatformDeps(build: Build, module: Module): Set[JavaDep] = {
val scalaVersion = BuildConfig.scalaVersion(build.project, List(module))
val scalaJsVersion = build.project.scalaJsVersion.get
def jsPlatformDeps(module: Module): Set[JavaDep] = {
val scalaVersion = module.scalaVersion.get
val scalaJsVersion = module.scalaJsVersion.get

Set(
Artefact.ScalaJsLibrary
Expand All @@ -70,9 +71,9 @@ object ArtefactResolution {
)
}

def nativePlatformDeps(build: Build, modules: List[Module]): Set[JavaDep] = {
val scalaVersion = BuildConfig.scalaVersion(build.project, modules)
val scalaNativeVersion = build.project.scalaNativeVersion.get
def nativePlatformDeps(module: Module): Set[JavaDep] = {
val scalaVersion = module.scalaVersion.get
val scalaNativeVersion = module.scalaNativeVersion.get

Set(
Artefact.ScalaNativeJavalib,
Expand All @@ -91,9 +92,9 @@ object ArtefactResolution {
)
}

def nativeLibraryDep(build: Build, modules: List[Module]): JavaDep = {
val scalaVersion = BuildConfig.scalaVersion(build.project, modules)
val scalaNativeVersion = build.project.scalaNativeVersion.get
def nativeLibraryDep(module: Module): JavaDep = {
val scalaVersion = module.scalaVersion.get
val scalaNativeVersion = module.scalaNativeVersion.get

javaDepFromArtefact(
Artefact.ScalaNativeNativelib,
Expand All @@ -104,67 +105,67 @@ object ArtefactResolution {
)
}

def jvmArtefacts(stack: List[Module]): Set[(Platform, Dep)] =
stack.flatMap(_.scalaDeps).map(dep => JVM -> dep).toSet ++
stack.flatMap(_.javaDeps).map(dep => JVM -> dep).toSet

def jvmDeps(build: Build, stack: List[Module]): Set[JavaDep] = {
val scalaVersion = BuildConfig.scalaVersion(build.project, stack)

stack
.flatMap(_.scalaDeps)
.map(dep => javaDepFromScalaDep(dep, JVM, scalaVersion, scalaVersion))
def jvmArtefacts(module: Module): Set[(Platform, Dep)] =
(module.scalaDeps ++ module.javaDeps).map(dep => JVM -> dep).toSet

def jvmDeps(module: Module): Set[JavaDep] =
module.scalaDeps
.map(
dep =>
javaDepFromScalaDep(
dep,
JVM,
module.scalaVersion.get,
module.scalaVersion.get
)
)
.toSet ++
stack.flatMap(_.javaDeps).toSet
}

def jsArtefacts(stack: List[Module]): Set[(Platform, Dep)] =
stack.flatMap(_.scalaDeps).map(dep => JavaScript -> dep).toSet

def jsDeps(build: Build, stack: List[Module]): Set[JavaDep] =
build.project.scalaJsVersion match {
case None => Set()
case Some(scalaJsVersion) =>
val scalaVersion = BuildConfig.scalaVersion(build.project, stack)
stack
.flatMap(_.scalaDeps)
.map(
dep =>
javaDepFromScalaDep(dep, JavaScript, scalaJsVersion, scalaVersion)
module.javaDeps.toSet

def jsArtefacts(module: Module): Set[(Platform, Dep)] =
module.scalaDeps.map(dep => JavaScript -> dep).toSet

def jsDeps(module: Module): Set[JavaDep] =
module.scalaDeps
.map(
dep =>
javaDepFromScalaDep(
dep,
JavaScript,
module.scalaJsVersion.get,
module.scalaVersion.get
)
.toSet
}

def nativeArtefacts(stack: List[Module]): Set[(Platform, Dep)] =
stack.flatMap(_.scalaDeps).map(dep => Native -> dep).toSet

def nativeDeps(build: Build, stack: List[Module]): Set[JavaDep] =
build.project.scalaNativeVersion match {
case None => Set()
case Some(scalaNativeVersion) =>
val scalaVersion = BuildConfig.scalaVersion(build.project, stack)
stack
.flatMap(_.scalaDeps)
.map(
dep =>
javaDepFromScalaDep(dep, Native, scalaNativeVersion, scalaVersion)
)
.toSet

def nativeArtefacts(module: Module): Set[(Platform, Dep)] =
module.scalaDeps.map(dep => Native -> dep).toSet

def nativeDeps(module: Module): Set[JavaDep] =
module.scalaDeps
.map(
dep =>
javaDepFromScalaDep(
dep,
Native,
module.scalaNativeVersion.get,
module.scalaVersion.get
)
.toSet
}
)
.toSet

def compilerDeps(build: Build, module: Module): List[Set[JavaDep]] = {
def f(build: Build, module: Module, platform: Platform): Set[JavaDep] = {
import build.project.scalaOrganisation
val platformModule = BuildConfig.platformModule(module, platform)
def compilerDeps(module: Module): List[Set[JavaDep]] = {
def f(module: Module, platform: Platform): Set[JavaDep] = {
val platformModule = BuildConfig.platformModule(module, platform).get

val platformVer = BuildConfig.platformVersion(build, module, platform)
val compilerVer =
BuildConfig.scalaVersion(build.project, platformModule.toList :+ module)
val platformVer = BuildConfig.platformVersion(module, platform)
val compilerVer = platformModule.scalaVersion.get
val organisation = platformModule.scalaOrganisation.get

val scalaDeps = Set(
Artefact.scalaCompiler(scalaOrganisation) -> compilerVer,
Artefact.scalaLibrary(scalaOrganisation) -> compilerVer,
Artefact.scalaReflect(scalaOrganisation) -> compilerVer
Artefact.scalaCompiler(organisation) -> compilerVer,
Artefact.scalaLibrary(organisation) -> compilerVer,
Artefact.scalaReflect(organisation) -> compilerVer
) ++ (
if (platform == Platform.Native)
Set(Artefact.ScalaNativePlugin -> platformVer)
Expand All @@ -173,10 +174,6 @@ object ArtefactResolution {
else Set()
)

val dependencies = mergeDeps[ScalaDep](
module.compilerDeps ++ platformModule.toList.flatMap(_.compilerDeps)
)

scalaDeps.map {
case (artefact, version) =>
javaDepFromArtefact(
Expand All @@ -186,110 +183,51 @@ object ArtefactResolution {
platformVer,
compilerVer
)
} ++ dependencies.map(
} ++ platformModule.compilerDeps.map(
dep => javaDepFromScalaDep(dep, platform, platformVer, compilerVer)
)
}

module.targets.map(target => f(build, module, target)).filter(_.nonEmpty)
module.targets.map(target => f(module, target)).filter(_.nonEmpty)
}

def allCompilerDeps(build: Build): List[Set[JavaDep]] =
build.module.values.toList.flatMap(compilerDeps(build, _)).distinct
build.values.toList.flatMap(m => compilerDeps(m.module)).distinct

def platformDeps(build: Build, module: Module): Set[JavaDep] =
module.targets.toSet[Platform].flatMap { target =>
if (target == JavaScript)
jsPlatformDeps(build, module.js.getOrElse(Module()))
else if (target == Native)
nativePlatformDeps(build, module.native.toList)
if (target == JavaScript) jsPlatformDeps(module.js.get)
else if (target == Native) nativePlatformDeps(module.native.get)
else Set[JavaDep]()
}

def libraryDeps(
build: Build,
module: Module,
platforms: Set[Platform],
parent: Module = Module()
): Set[JavaDep] = {
val targets = if (module.targets.isEmpty) parent.targets else module.targets
targets.toSet[Platform].intersect(platforms).flatMap { target =>
// Shared libraries
if (target == JVM)
jvmDeps(
build,
module.jvm.toList ++ parent.jvm.toList ++ List(module, parent)
)
else if (target == JavaScript)
jsDeps(
build,
module.js.toList ++ parent.js.toList ++ List(module, parent)
)
else
nativeDeps(
build,
module.native.toList ++ parent.native.toList ++ List(module, parent)
)
} ++
(if (!platforms.contains(JVM)) Set()
else
module.jvm.toSet.flatMap(
jvm =>
jvmDeps(build, List(jvm, parent.jvm.getOrElse(Module()), module))
)) ++
def libraryDeps(module: Module, platforms: Set[Platform]): Set[JavaDep] =
(if (!platforms.contains(JVM)) Set()
else module.jvm.toSet.flatMap(jvmDeps)) ++
(if (!platforms.contains(JavaScript)) Set()
else
module.js.toSet.flatMap(
js => jsDeps(build, List(js, parent.js.getOrElse(Module()), module))
)) ++
else module.js.toSet.flatMap(jsDeps)) ++
(if (!platforms.contains(Native)) Set()
else
module.native.toSet.flatMap(
native =>
nativeDeps(
build,
List(native, parent.native.getOrElse(Module()), module)
)
)) ++
module.test.toSet.flatMap(libraryDeps(build, _, platforms, module))
}
else module.native.toSet.flatMap(nativeDeps)) ++
module.test.toSet.flatMap(libraryDeps(_, platforms))

def libraryArtefacts(
build: Build,
module: Module,
parent: Module = Module()
): Set[(Platform, Dep)] =
module.targets.toSet[Platform].flatMap { target =>
if (target == JVM) jvmArtefacts(List(module, parent))
else if (target == JavaScript) jsArtefacts(List(module, parent))
else nativeArtefacts(List(module, parent))
} ++
module.jvm.toSet.flatMap(
jvm => jvmArtefacts(List(jvm, parent.jvm.getOrElse(Module()), module))
) ++
module.js.toSet.flatMap(
js => jsArtefacts(List(js, parent.js.getOrElse(Module()), module))
) ++
module.native.toSet.flatMap(
native =>
nativeArtefacts(
List(native, parent.native.getOrElse(Module()), module)
)
) ++
module.test.toSet.flatMap(libraryArtefacts(build, _, module))
def libraryArtefacts(module: Module): Set[(Platform, Dep)] =
module.jvm.toSet.flatMap(jvmArtefacts) ++
module.js.toSet.flatMap(jsArtefacts) ++
module.native.toSet.flatMap(nativeArtefacts) ++
module.test.toSet.flatMap(libraryArtefacts)

def allPlatformDeps(build: Build): Set[JavaDep] =
build.module.values.toSet.flatMap(platformDeps(build, _))
build.values.toSet.flatMap(m => platformDeps(build, m.module))

def allLibraryDeps(
build: Build,
platforms: Set[Platform] = Set(JVM, JavaScript, Native)
): Set[JavaDep] =
build.module.values.toSet.flatMap(libraryDeps(build, _, platforms))
build.values.toSet.flatMap(m => libraryDeps(m.module, platforms))

def allLibraryArtefacts(build: Build): Map[Platform, Set[Dep]] =
build.module.values.toSet
.flatMap(libraryArtefacts(build, _))
build.values.toSet
.flatMap(m => libraryArtefacts(m.module))
.groupBy(_._1)
.mapValues(_.map(_._2))

Expand Down Expand Up @@ -340,6 +278,7 @@ object ArtefactResolution {

def resolution(
seedConfig: seed.model.Config,
resolvers: Resolvers,
build: Build,
packageConfig: PackageConfig,
optionalArtefacts: Boolean,
Expand All @@ -356,15 +295,15 @@ object ArtefactResolution {
log.info("Configured resolvers:")
log.detail("- " + Ansi.italic(resolvedIvyPath.toString) + " (Ivy)")
log.detail("- " + Ansi.italic(resolvedCachePath.toString) + " (Coursier)")
build.resolvers.ivy
resolvers.ivy
.foreach(ivy => log.detail("- " + Ansi.italic(ivy.url) + " (Ivy)"))
build.resolvers.maven
resolvers.maven
.foreach(maven => log.detail("- " + Ansi.italic(maven) + " (Maven)"))

def resolve(deps: Set[JavaDep]) =
Coursier.resolveAndDownload(
deps,
build.resolvers,
resolvers,
resolvedIvyPath,
resolvedCachePath,
optionalArtefacts,
Expand Down
Loading

0 comments on commit 940210b

Please sign in to comment.