diff --git a/build.sbt b/build.sbt index e89a7febb..050184561 100644 --- a/build.sbt +++ b/build.sbt @@ -20,6 +20,22 @@ lazy val core = crossProject import com.typesafe.tools.mima.core._ Seq( + ProblemFilters.exclude[FinalClassProblem]("coursier.core.Activation$Os"), + ProblemFilters.exclude[FinalClassProblem]("coursier.core.Version"), + ProblemFilters.exclude[FinalClassProblem]("coursier.core.Authentication"), + ProblemFilters.exclude[FinalClassProblem]("coursier.core.VersionInterval"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.Pattern"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.Pattern$Chunk$Opt"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.PropertiesPattern$ChunkOrProperty$Const"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.PropertiesPattern$ChunkOrProperty$Opt"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.PropertiesPattern"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.Pattern$Chunk$Var"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.IvyRepository"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.Pattern$Chunk$Const"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.PropertiesPattern$ChunkOrProperty$Prop"), + ProblemFilters.exclude[FinalClassProblem]("coursier.ivy.PropertiesPattern$ChunkOrProperty$Var"), + ProblemFilters.exclude[FinalClassProblem]("coursier.maven.MavenRepository"), + ProblemFilters.exclude[FinalClassProblem]("coursier.maven.MavenSource"), ProblemFilters.exclude[IncompatibleResultTypeProblem]("coursier.package#Resolution.apply$default$9"), ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.package#Resolution.apply"), ProblemFilters.exclude[IncompatibleResultTypeProblem]("coursier.core.Resolution.copy$default$9"), @@ -126,6 +142,9 @@ lazy val cache = project import com.typesafe.tools.mima.core._ Seq( + ProblemFilters.exclude[FinalClassProblem]("coursier.TermDisplay$DownloadInfo"), + ProblemFilters.exclude[FinalClassProblem]("coursier.TermDisplay$CheckUpdateInfo"), + ProblemFilters.exclude[FinalClassProblem]("coursier.util.Base64$B64Scheme"), ProblemFilters.exclude[MissingClassProblem]("coursier.TermDisplay$Message$Stop$"), ProblemFilters.exclude[MissingClassProblem]("coursier.TermDisplay$Message"), ProblemFilters.exclude[MissingClassProblem]("coursier.TermDisplay$Message$"), diff --git a/cache/src/main/scala/coursier/TermDisplay.scala b/cache/src/main/scala/coursier/TermDisplay.scala index 89b8b1db4..72b1f56f6 100644 --- a/cache/src/main/scala/coursier/TermDisplay.scala +++ b/cache/src/main/scala/coursier/TermDisplay.scala @@ -79,7 +79,7 @@ object TermDisplay { def display(): String } - private case class DownloadInfo( + private final case class DownloadInfo( downloaded: Long, previouslyDownloaded: Long, length: Option[Long], @@ -127,7 +127,7 @@ object TermDisplay { private def formatTimestamp(ts: Long): String = format.format(new Timestamp(ts)) - private case class CheckUpdateInfo( + private final case class CheckUpdateInfo( currentTimeOpt: Option[Long], remoteTimeOpt: Option[Long], isDone: Boolean diff --git a/cache/src/main/scala/coursier/util/Base64.scala b/cache/src/main/scala/coursier/util/Base64.scala index 0019a80c8..58cf0c888 100644 --- a/cache/src/main/scala/coursier/util/Base64.scala +++ b/cache/src/main/scala/coursier/util/Base64.scala @@ -16,7 +16,7 @@ import scala.collection.mutable.ArrayBuilder object Base64 { - case class B64Scheme(encodeTable: Array[Char], strictPadding: Boolean = true, + final case class B64Scheme(encodeTable: Array[Char], strictPadding: Boolean = true, postEncode: String => String = identity, preDecode: String => String = identity) { lazy val decodeTable = { diff --git a/cli/src/main/scala-2.11/coursier/cli/Bootstrap.scala b/cli/src/main/scala-2.11/coursier/cli/Bootstrap.scala index 3ae44f51a..071de1c5e 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Bootstrap.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Bootstrap.scala @@ -11,7 +11,7 @@ import caseapp._ import coursier.cli.util.Zip import coursier.internal.FileUtil -case class Bootstrap( +final case class Bootstrap( @Recurse artifactOptions: ArtifactOptions, @Recurse diff --git a/cli/src/main/scala-2.11/coursier/cli/Coursier.scala b/cli/src/main/scala-2.11/coursier/cli/Coursier.scala index f8e8a9fcf..1cb732438 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Coursier.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Coursier.scala @@ -7,7 +7,7 @@ import caseapp.core.{ ArgsApp, CommandsMessages } import shapeless.union.Union // Temporary, see comment in Coursier below -case class CoursierCommandHelper( +final case class CoursierCommandHelper( command: CoursierCommandHelper.U ) extends ArgsApp { def setRemainingArgs(remainingArgs: Seq[String], extraArgs: Seq[String]): Unit = diff --git a/cli/src/main/scala-2.11/coursier/cli/Fetch.scala b/cli/src/main/scala-2.11/coursier/cli/Fetch.scala index 132d1b00e..a541e02f0 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Fetch.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Fetch.scala @@ -7,7 +7,7 @@ import caseapp._ import scala.language.reflectiveCalls -case class Fetch( +final case class Fetch( @Recurse options: FetchOptions ) extends App { diff --git a/cli/src/main/scala-2.11/coursier/cli/Launch.scala b/cli/src/main/scala-2.11/coursier/cli/Launch.scala index c8bd5f048..074daaba6 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Launch.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Launch.scala @@ -79,7 +79,7 @@ trait ExtraArgsApp extends caseapp.core.DefaultArgsApp { extraArgs1 } -case class Launch( +final case class Launch( @Recurse options: LaunchOptions ) extends App with ExtraArgsApp { diff --git a/cli/src/main/scala-2.11/coursier/cli/Options.scala b/cli/src/main/scala-2.11/coursier/cli/Options.scala index 72b4100bb..deb6df077 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Options.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Options.scala @@ -5,7 +5,7 @@ import caseapp.{ HelpMessage => Help, ValueDescription => Value, ExtraName => Sh import coursier.util.Parse -case class CommonOptions( +final case class CommonOptions( @Help("Keep optional dependencies (Maven)") keepOptional: Boolean = false, @Help("Download mode (default: missing, that is fetch things missing from cache)") @@ -94,13 +94,13 @@ case class CommonOptions( lazy val classifier0 = classifier.flatMap(_.split(',')).filter(_.nonEmpty) } -case class CacheOptions( +final case class CacheOptions( @Help("Cache directory (defaults to environment variable COURSIER_CACHE or ~/.coursier/cache/v1)") @Short("C") cache: String = Cache.default.toString ) -case class IsolatedLoaderOptions( +final case class IsolatedLoaderOptions( @Value("target:dependency") @Short("I") isolated: List[String] = Nil, @@ -174,7 +174,7 @@ object ArtifactOptions { def defaultArtifactTypes = Set("jar", "bundle") } -case class ArtifactOptions( +final case class ArtifactOptions( @Help("Artifact types that should be retained (e.g. jar, src, doc, etc.) - defaults to jar,bundle") @Value("type1,type2,...") @Short("A") @@ -197,7 +197,7 @@ case class ArtifactOptions( } } -case class FetchOptions( +final case class FetchOptions( @Help("Fetch source artifacts") @Short("S") sources: Boolean = false, @@ -213,7 +213,7 @@ case class FetchOptions( common: CommonOptions = CommonOptions() ) -case class LaunchOptions( +final case class LaunchOptions( @Short("M") @Short("main") mainClass: String = "", @@ -226,7 +226,7 @@ case class LaunchOptions( common: CommonOptions = CommonOptions() ) -case class BootstrapOptions( +final case class BootstrapOptions( @Short("M") @Short("main") mainClass: String = "", @@ -253,7 +253,7 @@ case class BootstrapOptions( common: CommonOptions = CommonOptions() ) -case class SparkSubmitOptions( +final case class SparkSubmitOptions( @Short("M") @Short("main") @Help("Main class to be launched (optional if in manifest)") diff --git a/cli/src/main/scala-2.11/coursier/cli/Resolve.scala b/cli/src/main/scala-2.11/coursier/cli/Resolve.scala index fd1a78e86..8536de833 100644 --- a/cli/src/main/scala-2.11/coursier/cli/Resolve.scala +++ b/cli/src/main/scala-2.11/coursier/cli/Resolve.scala @@ -3,7 +3,7 @@ package cli import caseapp._ -case class Resolve( +final case class Resolve( @Recurse common: CommonOptions ) extends App { diff --git a/cli/src/main/scala-2.11/coursier/cli/SparkSubmit.scala b/cli/src/main/scala-2.11/coursier/cli/SparkSubmit.scala index 4df696265..72f48b777 100644 --- a/cli/src/main/scala-2.11/coursier/cli/SparkSubmit.scala +++ b/cli/src/main/scala-2.11/coursier/cli/SparkSubmit.scala @@ -50,7 +50,7 @@ object SparkSubmit { * @author Han Ju */ @CommandName("spark-submit") -case class SparkSubmit( +final case class SparkSubmit( @Recurse options: SparkSubmitOptions ) extends App with ExtraArgsApp { diff --git a/cli/src/main/scala-2.11/coursier/cli/spark/Assembly.scala b/cli/src/main/scala-2.11/coursier/cli/spark/Assembly.scala index 6cc1a59fc..8ddb6b674 100644 --- a/cli/src/main/scala-2.11/coursier/cli/spark/Assembly.scala +++ b/cli/src/main/scala-2.11/coursier/cli/spark/Assembly.scala @@ -24,8 +24,8 @@ object Assembly { def path: String } - case class Exclude(path: String) extends PathRule - case class ExcludePattern(path: Pattern) extends Rule + final case class Exclude(path: String) extends PathRule + final case class ExcludePattern(path: Pattern) extends Rule object ExcludePattern { def apply(s: String): ExcludePattern = @@ -34,8 +34,8 @@ object Assembly { // TODO Accept a separator: Array[Byte] argument in these // (to separate content with a line return in particular) - case class Append(path: String) extends PathRule - case class AppendPattern(path: Pattern) extends Rule + final case class Append(path: String) extends PathRule + final case class AppendPattern(path: Pattern) extends Rule object AppendPattern { def apply(s: String): AppendPattern = diff --git a/core/shared/src/main/scala/coursier/core/Activation.scala b/core/shared/src/main/scala/coursier/core/Activation.scala index 79e980815..1b98abc2d 100644 --- a/core/shared/src/main/scala/coursier/core/Activation.scala +++ b/core/shared/src/main/scala/coursier/core/Activation.scala @@ -47,7 +47,7 @@ final case class Activation( object Activation { - case class Os( + final case class Os( arch: Option[String], families: Set[String], name: Option[String], diff --git a/core/shared/src/main/scala/coursier/core/Definitions.scala b/core/shared/src/main/scala/coursier/core/Definitions.scala index 3a5fc6b46..3331b8fc2 100644 --- a/core/shared/src/main/scala/coursier/core/Definitions.scala +++ b/core/shared/src/main/scala/coursier/core/Definitions.scala @@ -219,7 +219,7 @@ object Artifact { } } -case class Authentication( +final case class Authentication( user: String, password: String ) { diff --git a/core/shared/src/main/scala/coursier/core/Version.scala b/core/shared/src/main/scala/coursier/core/Version.scala index 34da4d71d..08b2c3652 100644 --- a/core/shared/src/main/scala/coursier/core/Version.scala +++ b/core/shared/src/main/scala/coursier/core/Version.scala @@ -8,7 +8,7 @@ import coursier.core.compatibility._ * * Same kind of ordering as aether-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java */ -case class Version(repr: String) extends Ordered[Version] { +final case class Version(repr: String) extends Ordered[Version] { lazy val items = Version.items(repr) lazy val rawItems: Seq[Version.Item] = { val (first, tokens) = Version.Tokenizer(repr) diff --git a/core/shared/src/main/scala/coursier/core/Versions.scala b/core/shared/src/main/scala/coursier/core/Versions.scala index d59ecfec9..3512b4ed7 100644 --- a/core/shared/src/main/scala/coursier/core/Versions.scala +++ b/core/shared/src/main/scala/coursier/core/Versions.scala @@ -3,10 +3,12 @@ package coursier.core import scalaz.{ -\/, \/, \/- } import scalaz.Scalaz.ToEitherOps -case class VersionInterval(from: Option[Version], - to: Option[Version], - fromIncluded: Boolean, - toIncluded: Boolean) { +final case class VersionInterval( + from: Option[Version], + to: Option[Version], + fromIncluded: Boolean, + toIncluded: Boolean +) { def isValid: Boolean = { val fromToOrder = diff --git a/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala b/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala index 250fba614..8956db9f2 100644 --- a/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala +++ b/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala @@ -8,7 +8,7 @@ import scala.language.higherKinds import scalaz._ import scalaz.Scalaz._ -case class IvyRepository( +final case class IvyRepository( pattern: Pattern, metadataPatternOpt: Option[Pattern], changing: Option[Boolean], diff --git a/core/shared/src/main/scala/coursier/ivy/Pattern.scala b/core/shared/src/main/scala/coursier/ivy/Pattern.scala index 98704eff8..f8031e6bb 100644 --- a/core/shared/src/main/scala/coursier/ivy/Pattern.scala +++ b/core/shared/src/main/scala/coursier/ivy/Pattern.scala @@ -4,7 +4,7 @@ import scalaz._, Scalaz._ import fastparse.all._ -case class PropertiesPattern(chunks: Seq[PropertiesPattern.ChunkOrProperty]) { +final case class PropertiesPattern(chunks: Seq[PropertiesPattern.ChunkOrProperty]) { def string: String = chunks.map(_.string).mkString @@ -51,7 +51,7 @@ case class PropertiesPattern(chunks: Seq[PropertiesPattern.ChunkOrProperty]) { } } -case class Pattern(chunks: Seq[Pattern.Chunk]) { +final case class Pattern(chunks: Seq[Pattern.Chunk]) { def +:(chunk: Pattern.Chunk): Pattern = Pattern(chunk +: chunks) @@ -101,17 +101,17 @@ object PropertiesPattern { } object ChunkOrProperty { - case class Prop(name: String, alternative: Option[Seq[ChunkOrProperty]]) extends ChunkOrProperty { + final case class Prop(name: String, alternative: Option[Seq[ChunkOrProperty]]) extends ChunkOrProperty { def string: String = s"$${" + name + alternative.fold("")(alt => "-" + alt.map(_.string).mkString) + "}" } - case class Var(name: String) extends ChunkOrProperty { + final case class Var(name: String) extends ChunkOrProperty { def string: String = "[" + name + "]" } - case class Opt(content: ChunkOrProperty*) extends ChunkOrProperty { + final case class Opt(content: ChunkOrProperty*) extends ChunkOrProperty { def string: String = "(" + content.map(_.string).mkString + ")" } - case class Const(value: String) extends ChunkOrProperty { + final case class Const(value: String) extends ChunkOrProperty { def string: String = value } @@ -159,13 +159,13 @@ object Pattern { } object Chunk { - case class Var(name: String) extends Chunk { + final case class Var(name: String) extends Chunk { def string: String = "[" + name + "]" } - case class Opt(content: Chunk*) extends Chunk { + final case class Opt(content: Chunk*) extends Chunk { def string: String = "(" + content.map(_.string).mkString + ")" } - case class Const(value: String) extends Chunk { + final case class Const(value: String) extends Chunk { def string: String = value } diff --git a/core/shared/src/main/scala/coursier/maven/MavenRepository.scala b/core/shared/src/main/scala/coursier/maven/MavenRepository.scala index 796b7f5ca..eaee02d20 100644 --- a/core/shared/src/main/scala/coursier/maven/MavenRepository.scala +++ b/core/shared/src/main/scala/coursier/maven/MavenRepository.scala @@ -75,7 +75,7 @@ object MavenRepository { } -case class MavenRepository( +final case class MavenRepository( root: String, changing: Option[Boolean] = None, /** Hackish hack for sbt plugins mainly - what this does really sucks */ diff --git a/core/shared/src/main/scala/coursier/maven/MavenSource.scala b/core/shared/src/main/scala/coursier/maven/MavenSource.scala index fd3c60145..6bdec3c94 100644 --- a/core/shared/src/main/scala/coursier/maven/MavenSource.scala +++ b/core/shared/src/main/scala/coursier/maven/MavenSource.scala @@ -2,7 +2,7 @@ package coursier.maven import coursier.core._ -case class MavenSource( +final case class MavenSource( root: String, changing: Option[Boolean] = None, /** See doc on MavenRepository */ diff --git a/core/shared/src/main/scala/coursier/util/Print.scala b/core/shared/src/main/scala/coursier/util/Print.scala index c53321981..eb8de860c 100644 --- a/core/shared/src/main/scala/coursier/util/Print.scala +++ b/core/shared/src/main/scala/coursier/util/Print.scala @@ -71,7 +71,7 @@ object Print { else ("", "", "") - case class Elem(dep: Dependency, excluded: Boolean) { + final case class Elem(dep: Dependency, excluded: Boolean) { lazy val reconciledVersion = resolution.reconciledVersions .getOrElse(dep.module, dep.version) @@ -144,7 +144,7 @@ object Print { if (reverse) { - case class Parent( + final case class Parent( module: Module, version: String, dependsOn: Module, diff --git a/http-server/src/main/scala-2.11/coursier/HttpServer.scala b/http-server/src/main/scala-2.11/coursier/HttpServer.scala index b6cdbbf6d..11e3b732b 100644 --- a/http-server/src/main/scala-2.11/coursier/HttpServer.scala +++ b/http-server/src/main/scala-2.11/coursier/HttpServer.scala @@ -16,7 +16,7 @@ import scala.collection.JavaConverters._ import scalaz.concurrent.Task -case class HttpServerApp( +final case class HttpServerApp( @ExtraName("d") @ValueDescription("served directory") directory: String, diff --git a/plugin/src/main/scala-2.10/coursier/Credentials.scala b/plugin/src/main/scala-2.10/coursier/Credentials.scala index c3229fe17..ac55f8579 100644 --- a/plugin/src/main/scala-2.10/coursier/Credentials.scala +++ b/plugin/src/main/scala-2.10/coursier/Credentials.scala @@ -15,11 +15,11 @@ sealed abstract class Credentials extends Product with Serializable { object Credentials { - case class Direct(user: String, password: String) extends Credentials { + final case class Direct(user: String, password: String) extends Credentials { override def toString = s"Direct($user, ******)" } - case class FromFile(file: File) extends Credentials { + final case class FromFile(file: File) extends Credentials { private lazy val props = { val p = new Properties() diff --git a/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala b/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala index 8d0cc8553..43ea07d77 100644 --- a/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala +++ b/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala @@ -65,7 +65,7 @@ object FallbackDependenciesRepository { } -case class FallbackDependenciesRepository( +final case class FallbackDependenciesRepository( fallbacks: Map[(Module, String), (URL, Boolean)] ) extends Repository { diff --git a/plugin/src/main/scala-2.10/coursier/InterProjectRepository.scala b/plugin/src/main/scala-2.10/coursier/InterProjectRepository.scala index 88b6e91a1..affb10273 100644 --- a/plugin/src/main/scala-2.10/coursier/InterProjectRepository.scala +++ b/plugin/src/main/scala-2.10/coursier/InterProjectRepository.scala @@ -4,7 +4,7 @@ import scala.language.higherKinds import scalaz.{ -\/, \/-, Monad, EitherT } -case class InterProjectRepository(projects: Seq[Project]) extends Repository { +final case class InterProjectRepository(projects: Seq[Project]) extends Repository { private val map = projects .map { proj => proj.moduleVersion -> proj } diff --git a/plugin/src/main/scala-2.10/coursier/ResolutionError.scala b/plugin/src/main/scala-2.10/coursier/ResolutionError.scala index 951e4d502..cc246c3d9 100644 --- a/plugin/src/main/scala-2.10/coursier/ResolutionError.scala +++ b/plugin/src/main/scala-2.10/coursier/ResolutionError.scala @@ -39,11 +39,11 @@ sealed abstract class ResolutionError extends Product with Serializable { object ResolutionError { case object MaximumIterationsReached extends ResolutionError - case class UnknownException(ex: Throwable) extends ResolutionError - case class UnknownDownloadException(ex: Throwable) extends ResolutionError - case class Conflicts(description: String) extends ResolutionError + final case class UnknownException(ex: Throwable) extends ResolutionError + final case class UnknownDownloadException(ex: Throwable) extends ResolutionError + final case class Conflicts(description: String) extends ResolutionError - case class MetadataDownloadErrors(errors: Seq[(Dependency, Seq[String])]) extends ResolutionError { + final case class MetadataDownloadErrors(errors: Seq[(Dependency, Seq[String])]) extends ResolutionError { def description(): String = { def grouped(errs: Seq[String]) = @@ -86,7 +86,7 @@ object ResolutionError { } } - case class DownloadErrors(errors: Seq[FileError]) extends ResolutionError { + final case class DownloadErrors(errors: Seq[FileError]) extends ResolutionError { def description(verbose: Boolean): String = { diff --git a/plugin/src/main/scala-2.10/coursier/Tasks.scala b/plugin/src/main/scala-2.10/coursier/Tasks.scala index 2dbcc116b..ebd28996c 100644 --- a/plugin/src/main/scala-2.10/coursier/Tasks.scala +++ b/plugin/src/main/scala-2.10/coursier/Tasks.scala @@ -250,7 +250,7 @@ object Tasks { } } - private case class ResolutionCacheKey( + private final case class ResolutionCacheKey( project: Project, repositories: Seq[Repository], userEnabledProfiles: Set[String], @@ -258,7 +258,7 @@ object Tasks { sbtClassifiers: Boolean ) - private case class ReportCacheKey( + private final case class ReportCacheKey( project: Project, resolution: Resolution, withClassifiers: Boolean, diff --git a/tests/shared/src/test/scala/coursier/test/TestRepository.scala b/tests/shared/src/test/scala/coursier/test/TestRepository.scala index 1bbb38024..94e51dcb0 100644 --- a/tests/shared/src/test/scala/coursier/test/TestRepository.scala +++ b/tests/shared/src/test/scala/coursier/test/TestRepository.scala @@ -8,7 +8,7 @@ import scala.language.higherKinds import scalaz.{ Monad, EitherT } import scalaz.Scalaz._ -case class TestRepository(projects: Map[(Module, String), Project]) extends Repository { +final case class TestRepository(projects: Map[(Module, String), Project]) extends Repository { val source = new core.Artifact.Source { def artifacts( dependency: Dependency, diff --git a/web/src/main/scala/coursier/web/Backend.scala b/web/src/main/scala/coursier/web/Backend.scala index 64e3511b3..0573bda17 100644 --- a/web/src/main/scala/coursier/web/Backend.scala +++ b/web/src/main/scala/coursier/web/Backend.scala @@ -15,11 +15,11 @@ import scala.concurrent.Future import scala.scalajs.js import js.Dynamic.{ global => g } -case class ResolutionOptions( +final case class ResolutionOptions( followOptional: Boolean = false ) -case class State( +final case class State( modules: Seq[Dependency], repositories: Seq[(String, MavenRepository)], options: ResolutionOptions,