Skip to content
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
1 change: 1 addition & 0 deletions .github/workflows/pr-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
env:
# Set LANG=C to simulate least-common-denominator target deployment environments:
LANG: C
SCALANATIVE_THREAD_STACK_SIZE: 10m
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: to prevent stackoverflow in native tests scala-native/scala-native#4253

name: Sjsonnet build for ${{ matrix.lang }} on JDK ${{ matrix.java }}
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ out/
.bloop
/project/.bloop
/project/project/
/project/metals.sbt
/project/metals.sbt
2 changes: 1 addition & 1 deletion bench/src/main/scala/sjsonnet/ParserBenchmark.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ParserBenchmark {
def main(bh: Blackhole): Unit = {
bh.consume(allFiles.foreach { case (p, s) =>
val res = fastparse.parse(s, new Parser(p, true, HashMap.empty, HashMap.empty).document(_))
bh.consume(res.asInstanceOf[Success[_]])
bh.consume(res.asInstanceOf[Success[?]])
})
}
}
4 changes: 2 additions & 2 deletions bench/src/main/scala/sjsonnet/ProfilingEvaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ class ProfilingEvaluator(resolver: CachedResolver,
case a: Array[Expr.Bind] => a.iterator.flatMap(getChildren).toSeq
case a: Array[Expr.Member.Field] => a.iterator.flatMap(getChildren).toSeq
case a: Array[Expr.Member.AssertStmt] => a.iterator.flatMap(getChildren).toSeq
case s: Seq[_] => s.collect { case e: Expr => e }
case s: Some[_] => s.collect { case e: Expr => e }
case s: Seq[?] => s.collect { case e: Expr => e }
case s: Some[?] => s.collect { case e: Expr => e }
case _ => Nil
}.filter(_ != null).toSeq
case _ => Nil
Expand Down
20 changes: 17 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
val sjsonnetVersion = "0.4.15.1"

scalaVersion in Global := "2.13.16"
val scala213 = "2.13.16"
val scala3 = "3.3.5"

cancelable in Global := true

val scala3Options = Seq()
val scala2Options = Seq("-opt:l:inline", "-opt-inline-from:sjsonnet.*,sjsonnet.**", "-Xsource:3")

lazy val commonSettings = Seq(
scalaVersion := scala3,
crossScalaVersions := Seq(scala213, scala3),
scalacOptions ++= {CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) => scala3Options
case _ => scala2Options
}}
)

lazy val main = (project in file("sjsonnet"))
.settings(commonSettings: _*)
.settings(
Compile / scalacOptions ++= Seq("-opt:l:inline", "-opt-inline-from:sjsonnet.*,sjsonnet.**"),
Test / fork := true,
Test / javaOptions += "-Xss100m",
Test / baseDirectory := (ThisBuild / baseDirectory).value,
Expand Down Expand Up @@ -56,6 +69,7 @@ lazy val main = (project in file("sjsonnet"))
lazy val bench = (project in file("bench"))
.dependsOn(main % "compile->test")
.enablePlugins(JmhPlugin)
.settings(commonSettings: _*)
.settings(
run / fork := true,
)
)
4 changes: 2 additions & 2 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.util.Base64

val sjsonnetVersion = "0.4.15.1"

val scalaVersions = Seq("2.12.20", "2.13.16")
val scalaVersions = Seq("2.12.20", "2.13.16", "3.3.5")

trait SjsonnetCrossModule extends CrossScalaModule with PublishModule {
def crossValue: String
Expand Down Expand Up @@ -153,7 +153,7 @@ object sjsonnet extends Module {
ivy"org.yaml:snakeyaml::2.0",
ivy"com.google.re2j:re2j:1.8",
)
def scalacOptions = Seq("-opt:l:inline", "-opt-inline-from:sjsonnet.*,sjsonnet.**")
def scalacOptions = Seq("-opt:l:inline", "-opt-inline-from:sjsonnet.*,sjsonnet.**", "-Xsource:3")

object test extends ScalaTests with CrossTests {
def forkArgs = Seq("-Xss100m")
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.10.0
sbt.version=1.10.11
3 changes: 1 addition & 2 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
//addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.3.7")
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.3.3")
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")
7 changes: 5 additions & 2 deletions sjsonnet/server/src/sjsonnet/SjsonnetServerMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,9 @@ class Server[T](lockBase: String,

@volatile var done = false
@volatile var idle = false
val t = new Thread(() =>
try {
val t = new Thread(new Runnable{
override def run(): Unit = {
try {
val (result, newStateCache) = sm.main0(
args,
sm.stateCache,
Expand All @@ -173,6 +174,8 @@ class Server[T](lockBase: String,
} finally{
done = true
idle = true
}
}
},
"SjsonnetServerActionRunner"
)
Expand Down
10 changes: 5 additions & 5 deletions sjsonnet/src-jvm-native/sjsonnet/CachedResolvedFile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class CachedResolvedFile(val resolvedImportPath: OsPath, memoryLimitBytes: Long,
// Assert that the file is less than limit
assert(jFile.length() <= memoryLimitBytes, s"Resolved import path $resolvedImportPath is too large: ${jFile.length()} bytes > ${memoryLimitBytes} bytes")

private[this] val resolvedImportContent: ResolvedFile = {
private val resolvedImportContent: ResolvedFile = {
// TODO: Support caching binary data
if (jFile.length() > cacheThresholdBytes) {
// If the file is too large, then we will just read it from disk
Expand All @@ -38,11 +38,11 @@ class CachedResolvedFile(val resolvedImportPath: OsPath, memoryLimitBytes: Long,
}
}

private[this] def readString(jFile: File): String = {
private def readString(jFile: File): String = {
new String(Files.readAllBytes(jFile.toPath), StandardCharsets.UTF_8);
}

private[this] def readRawBytes(jFile: File): Array[Byte] = Files.readAllBytes(jFile.toPath)
private def readRawBytes(jFile: File): Array[Byte] = Files.readAllBytes(jFile.toPath)

/**
* A method that will return a reader for the resolved import. If the import is too large, then this will return
Expand All @@ -67,12 +67,12 @@ class CachedResolvedFile(val resolvedImportPath: OsPath, memoryLimitBytes: Long,
}


override lazy val contentHash: String = {
override def contentHash(): String = {
if (resolvedImportContent == null) {
// If the file is too large, then we will just read it from disk
Platform.hashFile(jFile)
} else {
resolvedImportContent.contentHash
resolvedImportContent.contentHash()
}
}

Expand Down
2 changes: 1 addition & 1 deletion sjsonnet/src-jvm-native/sjsonnet/OsPath.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ case class OsPath(p: os.Path) extends Path{
":" + Util.prettyIndex(lineStarts, offset)
}

p.relativeTo(os.pwd) + offsetStr
p.relativeTo(os.pwd).toString + offsetStr
}
}
12 changes: 6 additions & 6 deletions sjsonnet/src-jvm-native/sjsonnet/SjsonnetMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ object SjsonnetMain {
private def writeFile(config: Config, f: os.Path, contents: String): Either[String, Unit] =
handleWriteFile(os.write.over(f, contents, createFolders = config.createDirs.value))

private def writeToFile(config: Config, wd: os.Path)(materialize: Writer => Either[String, _]): Either[String, String] = {
private def writeToFile(config: Config, wd: os.Path)(materialize: Writer => Either[String, ?]): Either[String, String] = {
config.outputFile match{
case None =>
val sw = new StringWriter
Expand Down Expand Up @@ -199,12 +199,12 @@ object SjsonnetMain {
importer = importer match{
case Some(i) => new Importer {
def resolve(docBase: Path, importName: String): Option[Path] =
i(docBase, importName).map(OsPath)
i(docBase, importName).map(OsPath.apply)
def read(path: Path, binaryData: Boolean): Option[ResolvedFile] = {
readPath(path, binaryData)
}
}
case None => resolveImport(config.jpaths.map(os.Path(_, wd)).map(OsPath), allowedInputs)
case None => resolveImport(config.jpaths.map(os.Path(_, wd)).map(OsPath.apply), allowedInputs)
},
parseCache,
settings = new Settings(
Expand All @@ -217,7 +217,7 @@ object SjsonnetMain {
strictSetOperations = config.strictSetOperations.value,
throwErrorForInvalidSets = config.throwErrorForInvalidSets.value,
),
storePos = (position: Position) => if (config.yamlDebug.value) currentPos = position else null,
storePos = (position: Position) => if (config.yamlDebug.value) currentPos = position else (),
warnLogger = warnLogger,
std = std
)
Expand All @@ -242,7 +242,7 @@ object SjsonnetMain {
Right(writer.toString)
}
}
relPath = os.FilePath(multiPath) / os.RelPath(f)
relPath = (os.FilePath(multiPath) / os.RelPath(f)).asInstanceOf[os.FilePath]
_ <- writeFile(config, relPath.resolveFrom(wd), rendered)
} yield relPath
}
Expand Down Expand Up @@ -295,7 +295,7 @@ object SjsonnetMain {
* of caching on top of the underlying file system. Small files are read into memory, while large
* files are read from disk.
*/
private[this] def readPath(path: Path, binaryData: Boolean): Option[ResolvedFile] = {
private def readPath(path: Path, binaryData: Boolean): Option[ResolvedFile] = {
val osPath = path.asInstanceOf[OsPath].p
if (os.exists(osPath) && os.isFile(osPath)) {
Some(new CachedResolvedFile(path.asInstanceOf[OsPath], memoryLimitBytes = Int.MaxValue.toLong, binaryData = binaryData))
Expand Down
6 changes: 3 additions & 3 deletions sjsonnet/src-jvm/sjsonnet/Platform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ object Platform {
yaml.size match {
case 0 => "{}"
case 1 => yaml.head match {
case m: java.util.Map[_, _] => new JSONObject(m).toString()
case l: java.util.List[_] => new JSONArray(l).toString()
case m: java.util.Map[?, ?] => new JSONObject(m).toString()
case l: java.util.List[?] => new JSONArray(l).toString()
case _ => new JSONArray(yaml.asJava).get(0).toString
}
case _ => new JSONArray(yaml.asJava).toString()
Expand Down Expand Up @@ -89,7 +89,7 @@ object Platform {
// Same as go-jsonnet https://github.com/google/go-jsonnet/blob/2b4d7535f540f128e38830492e509a550eb86d57/builtins.go#L959
def sha3(s: String): String = computeHash("SHA3-512", s)

private[this] val xxHashFactory = XXHashFactory.fastestInstance()
private val xxHashFactory = XXHashFactory.fastestInstance()

def hashFile(file: File): String = {
val buffer = new Array[Byte](8192)
Expand Down
6 changes: 3 additions & 3 deletions sjsonnet/src/sjsonnet/BaseCharRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ class BaseCharRenderer[T <: upickle.core.CharOps.Output]

override def visitJsonableObject(length: Int, index: Int): ObjVisitor[T,T] = visitObject(length, index)

protected[this] val elemBuilder = new upickle.core.CharBuilder
protected val elemBuilder = new upickle.core.CharBuilder
def flushCharBuilder(): Unit = {
elemBuilder.writeOutToIfLongerThan(out, if (depth == 0) 0 else 1000)
}

protected[this] var depth: Int = 0
protected var depth: Int = 0


protected[this] var commaBuffered = false
protected var commaBuffered = false

def flushBuffer(): Unit = {
if (commaBuffered) {
Expand Down
33 changes: 17 additions & 16 deletions sjsonnet/src/sjsonnet/BaseRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,28 @@ class BaseRenderer[T <: java.io.Writer]
indent: Int = -1,
escapeUnicode: Boolean = false) extends ujson.JsVisitor[T, T]{

override def visitJsonableObject(length: Int, index: Int): ObjVisitor[T,T] = visitObject(length, index)

var depth: Int = 0
val colonSnippet = if (indent == -1) ":" else ": "
val colonSnippet: String = if (indent == -1) ":" else ": "

var commaBuffered = false

def flushBuffer() = {
def flushBuffer(): Unit = {
if (commaBuffered) {
commaBuffered = false
out.append(',')
renderIndent()
}
}
def visitArray(length: Int, index: Int) = new ArrVisitor[T, T] {

override def visitJsonableObject(length: Int, index: Int): ObjVisitor[T,T] = visitObject(length, index)

def visitArray(length: Int, index: Int): upickle.core.ArrVisitor[T,T]{def subVisitor: sjsonnet.BaseRenderer[T]} = new ArrVisitor[T, T] {
flushBuffer()
out.append('[')

depth += 1
renderIndent()
def subVisitor = BaseRenderer.this
def subVisitor: sjsonnet.BaseRenderer[T] = BaseRenderer.this
def visitValue(v: T, index: Int): Unit = {
flushBuffer()
commaBuffered = true
Expand All @@ -50,13 +51,13 @@ class BaseRenderer[T <: java.io.Writer]
}
}

def visitObject(length: Int, index: Int) = new ObjVisitor[T, T] {
def visitObject(length: Int, index: Int): ObjVisitor[T,T] = new ObjVisitor[T, T] {
flushBuffer()
out.append('{')
depth += 1
renderIndent()
def subVisitor = BaseRenderer.this
def visitKey(index: Int) = BaseRenderer.this
def subVisitor: sjsonnet.BaseRenderer[T] = BaseRenderer.this
def visitKey(index: Int): sjsonnet.BaseRenderer[T]= BaseRenderer.this
def visitKeyValue(s: Any): Unit = out.append(colonSnippet)
def visitValue(v: T, index: Int): Unit = {
commaBuffered = true
Expand All @@ -70,31 +71,31 @@ class BaseRenderer[T <: java.io.Writer]
}
}

def visitNull(index: Int) = {
def visitNull(index: Int): T = {
flushBuffer()
out.append("null")
out
}

def visitFalse(index: Int) = {
def visitFalse(index: Int): T = {
flushBuffer()
out.append("false")
out
}

def visitTrue(index: Int) = {
def visitTrue(index: Int): T = {
flushBuffer()
out.append("true")
out
}

def visitFloat64StringParts(s: CharSequence, decIndex: Int, expIndex: Int, index: Int) = {
def visitFloat64StringParts(s: CharSequence, decIndex: Int, expIndex: Int, index: Int): T = {
flushBuffer()
out.append(s)
out
}

override def visitFloat64(d: Double, index: Int) = {
override def visitFloat64(d: Double, index: Int): T = {
d match{
case Double.PositiveInfinity => visitString("Infinity", -1)
case Double.NegativeInfinity => visitString("-Infinity", -1)
Expand All @@ -109,15 +110,15 @@ class BaseRenderer[T <: java.io.Writer]
out
}

def visitString(s: CharSequence, index: Int) = {
def visitString(s: CharSequence, index: Int): T = {
flushBuffer()
if (s == null) out.append("null")
else BaseRenderer.escape(out, s, escapeUnicode)

out
}

final def renderIndent() = {
final def renderIndent(): Unit = {
if (indent == -1) ()
else {
out.append('\n')
Expand Down
4 changes: 2 additions & 2 deletions sjsonnet/src/sjsonnet/DecimalFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ package sjsonnet
*/
object DecimalFormat {

def trailingZeroes(n: Long) = {
def trailingZeroes(n: Long): Int = {
var count = 0
var current = n
var done = false
Expand All @@ -31,7 +31,7 @@ object DecimalFormat {
val n = (n0 / Math.pow(10, trailingZeroes(n0))).toInt
assert(n == math.abs(n))
val nWidth = if (n == 0) 1 else Math.log10(n).toInt + 1
(n + "0" * (minWidth - nWidth)).take(maxWidth)
("" + n + "0" * (minWidth - nWidth)).take(maxWidth)
}
}
def format(fracLengthOpt: Option[(Int, Int)], expLengthOpt: Option[Int], number: Double): String = {
Expand Down
Loading