Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala 3 Native and cleanup #376

Merged
merged 17 commits into from
May 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/scala.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ jobs:
- name: Cache scala dependencies
uses: coursier/cache-action@v6
- name: Run tests
if: ${{ matrix.platform != 'Native' || !startsWith(matrix.scala, '3.') }}
run: sbt ++${{ matrix.scala }}! scalajavatimeTests${{ matrix.platform }}/test
# TODO: investigate why tests fail on Scala 3 JVM
if: ${{ matrix.platform != 'JVM' || !startsWith(matrix.scala, '3.') }}
run: sbt ++${{ matrix.scala }}! tests${{ matrix.platform }}/test
- name: Run demo
if: ${{ matrix.platform != 'Native' || !startsWith(matrix.scala, '3.') }}
run: sbt ++${{ matrix.scala }}! demo${{ matrix.platform }}/run

build:
Expand Down
125 changes: 57 additions & 68 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ val versions: Map[String, String] = {
val scalaVer = versions("2.13")
val scala3Ver = versions("3")
val tzdbVersion = "2019c"
val scalajavaLocalesVersion = "1.3.0"
val scalajavaLocalesVersion = "1.4.0"
Global / onChangedBuildSource := ReloadOnSourceChanges

Global / resolvers += Resolver.sonatypeRepo("public")

lazy val downloadFromZip: TaskKey[Unit] =
taskKey[Unit]("Download the tzdb tarball and extract it")

Expand Down Expand Up @@ -54,25 +52,33 @@ inThisBuild(
)
)

publish / skip := true

def scalaVersionSpecificFolders(srcName: String, srcBaseDir: java.io.File, scalaVersion: String) = {
def extraDirs(suffix: String) =
List(CrossType.Pure, CrossType.Full)
.flatMap(_.sharedSrcDir(srcBaseDir, srcName).toList.map(f => file(f.getPath + suffix)))
CrossVersion.partialVersion(scalaVersion) match {
case Some((2, y)) => extraDirs("-2.x") ++ (if (y >= 13) extraDirs("-2.13+") else Nil)
case Some((0 | 3, _)) => extraDirs("-2.13+") ++ extraDirs("-3.x")
case _ => Nil
}
}
lazy val root = project
.in(file("."))
.settings(commonSettings)
.settings(
publish / skip := true
)
.aggregate(
core.js,
core.jvm,
core.native,
tzdb.js,
tzdb.jvm,
tzdb.native,
tests.js,
tests.jvm,
tests.native,
demo.js,
demo.jvm,
demo.native
)

lazy val commonSettings = Seq(
description := "java.time API implementation in Scala and Scala.js",
scalaVersion := scalaVer,
crossScalaVersions := versions.toList.map(_._2),
// Don't include threeten on the binaries
Compile / packageBin / mappings := (Compile / packageBin / mappings).value.filter { case (f, s) =>
Compile / packageBin / mappings := (Compile / packageBin / mappings).value.filter { case (_, s) =>
!s.contains("threeten")
},
Compile / scalacOptions ++= {
Expand All @@ -91,15 +97,16 @@ lazy val commonSettings = Seq(
Seq.empty
}
},
Compile / unmanagedSourceDirectories ++= scalaVersionSpecificFolders("main",
baseDirectory.value,
scalaVersion.value
),
Test / unmanagedSourceDirectories ++= scalaVersionSpecificFolders("test",
baseDirectory.value,
scalaVersion.value
),
scalacOptions ++= { if (isDotty.value) Seq.empty else Seq("-target:jvm-1.8") },
scalacOptions --= {
if (isDotty.value)
List(
"-Xfatal-warnings"
)
else
List(
)
},
javaOptions ++= Seq("-Dfile.encoding=UTF8"),
autoAPIMappings := true,
Compile / doc / sources := { if (isDotty.value) Seq() else (Compile / doc / sources).value }
Expand All @@ -122,7 +129,7 @@ def copyAndReplace(srcDirs: Seq[File], destinationDir: File): Seq[File] = {
false
)

val onlyScalaDirs = srcDirs.filter(_.getName.matches(".*scala(-\\d\\.x)?"))
val onlyScalaDirs = srcDirs.filter(_.getName.matches(".*scala(-\\d)?"))
// Copy the source files from the base project, exclude classes on java.util and dirs
val generatedFiles: List[java.io.File] = onlyScalaDirs
.foldLeft(Set.empty[File]) { (files, sourceDir) =>
Expand Down Expand Up @@ -152,13 +159,13 @@ def copyAndReplace(srcDirs: Seq[File], destinationDir: File): Seq[File] = {
generatedFiles
}

lazy val scalajavatime = crossProject(JVMPlatform, JSPlatform, NativePlatform)
lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Full)
.in(file("core"))
.settings(commonSettings: _*)
.settings(commonSettings)
.settings(
name := "scala-java-time",
libraryDependencies += ("org.portable-scala" %%% "portable-scala-reflect" % "1.1.1")
libraryDependencies += ("org.portable-scala" %%% "portable-scala-reflect" % "1.1.2")
.cross(CrossVersion.for3Use2_13)
)
.jsSettings(
Expand Down Expand Up @@ -191,7 +198,6 @@ lazy val scalajavatime = crossProject(JVMPlatform, JSPlatform, NativePlatform)
)
)
.nativeSettings(
crossScalaVersions -= scala3Ver,
Compile / sourceGenerators += Def.task {
val srcDirs = (Compile / sourceDirectories).value
val destinationDir = (Compile / sourceManaged).value
Expand All @@ -202,26 +208,24 @@ lazy val scalajavatime = crossProject(JVMPlatform, JSPlatform, NativePlatform)
)
)

lazy val scalajavatimeTZDB = crossProject(JVMPlatform, JSPlatform, NativePlatform)
lazy val tzdb = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Full)
.in(file("tzdb"))
.settings(commonSettings)
.settings(
name := "scala-java-time-tzdb"
name := "scala-java-time-tzdb",
includeTTBP := true
)
.jsSettings(
dbVersion := TzdbPlugin.Version(tzdbVersion),
includeTTBP := true,
dbVersion := TzdbPlugin.Version(tzdbVersion),
Compile / sourceGenerators += Def.task {
val srcDirs = (Compile / sourceManaged).value
val destinationDir = (Compile / sourceManaged).value
copyAndReplace(Seq(srcDirs), destinationDir)
}.taskValue
)
.nativeSettings(
crossScalaVersions -= scala3Ver,
dbVersion := TzdbPlugin.Version(tzdbVersion),
includeTTBP := true,
tzdbPlatform := TzdbPlugin.Platform.Native,
Compile / sourceGenerators += Def.task {
val srcDirs = (Compile / sourceManaged).value
Expand All @@ -230,44 +234,36 @@ lazy val scalajavatimeTZDB = crossProject(JVMPlatform, JSPlatform, NativePlatfor
}.taskValue
)
.jvmSettings(
includeTTBP := true,
tzdbPlatform := TzdbPlugin.Platform.Jvm
)
.dependsOn(scalajavatime)

lazy val scalajavatimeTZDBJVM = scalajavatimeTZDB.jvm.enablePlugins(TzdbPlugin)
lazy val scalajavatimeTZDBJS = scalajavatimeTZDB.js.enablePlugins(TzdbPlugin)
lazy val scalajavatimeTZDBNative = scalajavatimeTZDB.native.enablePlugins(TzdbPlugin)
.dependsOn(core)
.enablePlugins(TzdbPlugin)

lazy val scalajavatimeTests = crossProject(JVMPlatform, JSPlatform, NativePlatform)
lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Full)
.in(file("tests"))
.settings(commonSettings: _*)
.settings(commonSettings)
.settings(
name := "scala-java-time-tests",
// No, SBT, we don't want any artifacts for root.
// No, not even an empty jar.
publish := {},
publishLocal := {},
publishArtifact := false,
name := "tests",
publish / skip := true,
Keys.`package` := file(""),
Compile / skip := isDotty.value,
libraryDependencies +=
"org.scalatest" %%% "scalatest" % "3.2.12" % "test",
"org.scalatest" %%% "scalatest" % "3.2.12" % Test,
scalacOptions ~= (_.filterNot(
Set("-Wnumeric-widen", "-Ywarn-numeric-widen", "-Ywarn-value-discard", "-Wvalue-discard")
))
)
.jvmSettings(
// Fork the JVM test to ensure that the custom flags are set
Test / fork := true,
Test / baseDirectory := baseDirectory.value.getParentFile,
Test / fork := true,
Test / baseDirectory := baseDirectory.value.getParentFile,
// Use CLDR provider for locales
// https://docs.oracle.com/javase/8/docs/technotes/guides/intl/enhancements.8.html#cldr
Test / javaOptions ++= Seq("-Duser.language=en",
"-Duser.country=US",
"-Djava.locale.providers=CLDR"
)
),
Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat
)
.jsSettings(
Test / parallelExecution := false,
Expand All @@ -281,7 +277,6 @@ lazy val scalajavatimeTests = crossProject(JVMPlatform, JSPlatform, NativePlatfo
)
)
.nativeSettings(
crossScalaVersions -= scala3Ver,
Test / parallelExecution := false,
Test / sourceGenerators += Def.task {
val srcDirs = (Test / sourceDirectories).value
Expand All @@ -292,22 +287,20 @@ lazy val scalajavatimeTests = crossProject(JVMPlatform, JSPlatform, NativePlatfo
"io.github.cquiroz" %%% "locales-full-db" % scalajavaLocalesVersion
)
)
.dependsOn(scalajavatime, scalajavatimeTZDB)
.dependsOn(core, tzdb)

val zonesFilterFn = (x: String) => x == "Europe/Helsinki" || x == "America/Santiago"

lazy val demo = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.in(file("demo"))
.dependsOn(scalajavatime)
.dependsOn(core)
.enablePlugins(TzdbPlugin)
.settings(
scalaVersion := scalaVer,
name := "demo",
publish := {},
publishLocal := {},
publishArtifact := false,
Keys.`package` := file(""),
zonesFilter := zonesFilterFn
scalaVersion := scalaVer,
name := "demo",
publish / skip := true,
Keys.`package` := file(""),
zonesFilter := zonesFilterFn
)
.jsSettings(
// scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) },
Expand All @@ -326,10 +319,6 @@ lazy val demo = crossProject(JSPlatform, JVMPlatform, NativePlatform)
Compile / scalacOptions -= "-Xfatal-warnings"
)

lazy val demoJS = demo.js
lazy val demoJVM = demo.jvm
lazy val demoNative = demo.native

// lazy val docs = project
// .in(file("docs"))
// .dependsOn(scalajavatime.jvm, scalajavatime.js)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ object Month {
* The singleton instance for the month of November with 30 days. This has the numeric value of
* {@code 11}.
*/
val NOVEMBER = new Month("NOVEMBER", 10)
lazy val NOVEMBER = new Month("NOVEMBER", 10)

/**
* The singleton instance for the month of December with 31 days. This has the numeric value of
Expand Down Expand Up @@ -492,6 +492,7 @@ final class Month private (name: String, ordinal: Int)
case OCTOBER => 274 + leap
case NOVEMBER => 305 + leap
case DECEMBER => 335 + leap
case _ => throw new IllegalArgumentException // should never happen
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,40 +252,40 @@ final class StandardZoneRules private (

def getOffset(localDateTime: LocalDateTime): ZoneOffset =
getOffsetInfo(localDateTime) match {
case transition: ZoneOffsetTransition => transition.getOffsetBefore
case offset: ZoneOffset => offset
case Left(transition) => transition.getOffsetBefore
case Right(offset) => offset
}

def getValidOffsets(localDateTime: LocalDateTime): java.util.List[ZoneOffset] =
getOffsetInfo(localDateTime) match {
case transition: ZoneOffsetTransition => transition.getValidOffsets
case offset: ZoneOffset => Collections.singletonList(offset)
case Left(transition) => transition.getValidOffsets
case Right(offset) => Collections.singletonList(offset)
}

def getTransition(localDateTime: LocalDateTime): ZoneOffsetTransition =
getOffsetInfo(localDateTime) match {
case transition: ZoneOffsetTransition => transition
case _ => null
case Left(transition) => transition
case _ => null
}

private def getOffsetInfo(dt: LocalDateTime): AnyRef = {
private def getOffsetInfo(dt: LocalDateTime): Either[ZoneOffsetTransition, ZoneOffset] = {
if (
lastRules.length > 0 && dt.isAfter(
savingsLocalTransitions(savingsLocalTransitions.length - 1)
)
) {
val transArray: Array[ZoneOffsetTransition] = findTransitionArray(dt.getYear)
var info: AnyRef = null
val transArray: Array[ZoneOffsetTransition] = findTransitionArray(dt.getYear)
var info: Either[ZoneOffsetTransition, ZoneOffset] = null
for (trans <- transArray) {
info = findOffsetInfo(dt, trans)
if (info.isInstanceOf[ZoneOffsetTransition] || (info == trans.getOffsetBefore))
if (info.isLeft || (info == Right(trans.getOffsetBefore)))
return info
}
return info
}
var index: Int = Arrays.binarySearch(savingsLocalTransitions.asInstanceOf[Array[AnyRef]], dt)
if (index == -1)
return wallOffsets(0)
return Right(wallOffsets(0))
if (index < 0)
index = -index - 2
else if (
Expand All @@ -302,11 +302,11 @@ final class StandardZoneRules private (
val offsetBefore: ZoneOffset = wallOffsets(index / 2)
val offsetAfter: ZoneOffset = wallOffsets(index / 2 + 1)
if (offsetAfter.getTotalSeconds > offsetBefore.getTotalSeconds)
new ZoneOffsetTransition(dtBefore, offsetBefore, offsetAfter)
Left(new ZoneOffsetTransition(dtBefore, offsetBefore, offsetAfter))
else
new ZoneOffsetTransition(dtAfter, offsetBefore, offsetAfter)
Left(new ZoneOffsetTransition(dtAfter, offsetBefore, offsetAfter))
} else
wallOffsets(index / 2 + 1)
Right(wallOffsets(index / 2 + 1))
}

/**
Expand All @@ -319,21 +319,24 @@ final class StandardZoneRules private (
* @return
* the offset info, not null
*/
private def findOffsetInfo(dt: LocalDateTime, trans: ZoneOffsetTransition): AnyRef = {
private def findOffsetInfo(
dt: LocalDateTime,
trans: ZoneOffsetTransition
): Either[ZoneOffsetTransition, ZoneOffset] = {
val localTransition: LocalDateTime = trans.getDateTimeBefore
if (trans.isGap)
if (dt.isBefore(localTransition))
trans.getOffsetBefore
Right(trans.getOffsetBefore)
else if (dt.isBefore(trans.getDateTimeAfter))
trans
Left(trans)
else
trans.getOffsetAfter
Right(trans.getOffsetAfter)
else if (!dt.isBefore(localTransition))
trans.getOffsetAfter
Right(trans.getOffsetAfter)
else if (dt.isBefore(trans.getDateTimeAfter))
trans.getOffsetBefore
Right(trans.getOffsetBefore)
else
trans
Left(trans)
}

def isValidOffset(localDateTime: LocalDateTime, offset: ZoneOffset): Boolean =
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.6.1
sbt.version=1.6.2
Loading