Refactor RefThenConfig to be an opaque type

This commit is contained in:
Eugene Yokota 2024-11-26 04:55:08 -05:00
parent 320a8c7204
commit eb7d43c363
7 changed files with 42 additions and 20 deletions

View File

@ -14,7 +14,8 @@ import java.net.URI
import sbt.internal.util.AttributeKey
import sbt.io.IO
import sbt.librarymanagement.Configuration
import sbt.ScopeAxis.{ Select, This, RefThenConfig }
import sbt.Scope.RefThenConfig
import sbt.ScopeAxis.{ Select, This }
// in all of these, the URI must be resolved and normalized before it is definitive
@ -25,13 +26,13 @@ sealed trait Reference:
private[sbt] def asScope: Scope =
Scope(asScopeAxis, This, This, This)
def /(c: ConfigKey): RefThenConfig = RefThenConfig(asScope.rescope(c))
def /(c: ConfigKey): RefThenConfig = RefThenConfig(asScopeAxis, c)
def /(c: Configuration): RefThenConfig = RefThenConfig(asScope.rescope(c))
def /(c: Configuration): RefThenConfig = RefThenConfig(asScopeAxis, c: ConfigKey)
// This is for handling `Zero / Zero / name`.
def /(configAxis: ScopeAxis[ConfigKey]): RefThenConfig =
RefThenConfig(asScope.copy(config = configAxis))
RefThenConfig(asScopeAxis, configAxis)
final def /[K](key: Scoped.ScopingSetting[K]): K = asScope.scope(key)

View File

@ -430,4 +430,23 @@ object Scope:
t <- withZeroAxis(scope.task)
e <- withZeroAxis(scope.extra)
} yield Scope(Zero, c, t, e)
/**
* Temporary data structure to capture first two axis using slash syntax.
* In theory, we might be able to express this as type parameters of Scope,
* like Scope[Select[ThisBuild.type], Select[ConfigKey], This, This] but then
* scope becomes more complicated to deal with.
*/
opaque type RefThenConfig = (ScopeAxis[Reference], ScopeAxis[ConfigKey])
object RefThenConfig:
def apply(project: ScopeAxis[Reference], config: ScopeAxis[ConfigKey]): RefThenConfig =
(project, config)
def apply(project: ScopeAxis[Reference], config: ConfigKey): RefThenConfig =
(project, Select(config))
extension (in: RefThenConfig)
def project: ScopeAxis[Reference] = in._1
def config: ScopeAxis[ConfigKey] = in._2
end RefThenConfig
end Scope

View File

@ -10,10 +10,9 @@ package sbt
import sbt.internal.util.Util.*
import sbt.librarymanagement.Configuration
import sbt.internal.util.AttributeKey
enum ScopeAxis[+A1]:
import ScopeAxis.RefThenConfig
import Scope.RefThenConfig
/**
* Select is a type constructor that is used to wrap type `S`
@ -57,12 +56,12 @@ enum ScopeAxis[+A1]:
inline def /[K](key: Scoped.ScopingSetting[K])(using A1 <:< Reference): K = key.rescope(asScope)
inline def /(c: ConfigKey)(using A1 <:< Reference): RefThenConfig =
RefThenConfig(asScope.rescope(c))
RefThenConfig(this.asInstanceOf, c)
inline def /(c: Configuration)(using A1 <:< Reference): RefThenConfig =
RefThenConfig(asScope.rescope(c))
RefThenConfig(this.asInstanceOf, c: ConfigKey)
// This is for handling `Zero / Zero / name`.
inline def /(configAxis: ScopeAxis[ConfigKey])(using A1 <:< Reference): RefThenConfig =
RefThenConfig(asScope.copy(config = configAxis))
RefThenConfig(this.asInstanceOf, configAxis)
end ScopeAxis
object ScopeAxis:
@ -72,15 +71,4 @@ object ScopeAxis:
def fromOption[A1](o: Option[A1]): ScopeAxis[A1] = o match
case Some(v) => ScopeAxis.Select(v)
case None => ScopeAxis.Zero
/** Temporary data structure to capture first two axis using slash syntax. */
class RefThenConfig(val scope: Scope):
override def toString(): String = scope.toString()
def /[K](key: Scoped.ScopingSetting[K]): K = scope / key
def /(task: AttributeKey[?]): Scope = scope.copy(task = Select(task))
/** This is for handling `Zero / Zero / Zero / name`. */
def /(taskAxis: ScopeAxis[AttributeKey[?]]): Scope = scope.copy(task = taskAxis)
end RefThenConfig
end ScopeAxis

View File

@ -11,6 +11,8 @@ package sbt
import sbt.librarymanagement.Configuration
import sbt.internal.util.AttributeKey
import sbt.ScopeAxis.{ Select, This }
import sbt.Scope.RefThenConfig
import sbt.Scope.RefThenConfig.{ project, config }
/**
* SlashSyntax implements part of the slash syntax to scope keys for build.sbt DSL.
@ -39,6 +41,15 @@ trait SlashSyntax:
def asScope: Scope = (c: ConfigKey).asScope
def /[K](key: Scoped.ScopingSetting[K]): K = (c: ConfigKey) / key
def /(task: AttributeKey[?]): Scope = (c: ConfigKey) / task
extension (in: RefThenConfig)
def asScope: Scope = in.project.asScope.copy(config = in.config)
def toString(): String = asScope.toString()
def /[K](key: Scoped.ScopingSetting[K]): K = asScope / key
def /(task: AttributeKey[?]): Scope = asScope.copy(task = Select(task))
/** This is for handling `Zero / Zero / Zero / name`. */
def /(taskAxis: ScopeAxis[AttributeKey[?]]): Scope = asScope.copy(task = taskAxis)
end SlashSyntax
private[sbt] object SlashSyntax0 extends SlashSyntax

View File

@ -19,6 +19,7 @@ import lmcoursier.definitions.{
import sbt.librarymanagement._
import sbt.Keys._
import sbt.ProjectExtra.extract
import sbt.SlashSyntax0.*
object CoursierArtifactsTasks {
def coursierPublicationsTask(

View File

@ -18,6 +18,7 @@ import sbt.Def.Initialize
import sbt.internal.util.{ Attributed, Dag }
import sbt.librarymanagement.{ Configuration, TrackLevel }
import sbt.librarymanagement.Configurations.names
import sbt.SlashSyntax0.*
import sbt.std.TaskExtra._
import sbt.util._
import scala.jdk.CollectionConverters.*

View File

@ -18,6 +18,7 @@ import sbt.Keys._
import sbt.ProjectExtra.*
import sbt.ScopeFilter.Make._
import sbt.Scoped.richTaskSeq
import sbt.SlashSyntax0.*
import sbt.StandardMain.exchange
import sbt.internal.bsp._
import sbt.internal.langserver.ErrorCodes