Skip to content

Commit

Permalink
Add better error handling for format
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenamar-db committed Nov 5, 2024
1 parent 6939b1a commit 7e2b6a3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 10 deletions.
6 changes: 5 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,11 @@ to ensure the output bytecode remains compatible with users on older JVMs.

### 0.4.11
- Implement `std.isEmpty`, `std.xor`, `std.xnor`, `std.trim`,
`std.equalsIgnoreCase`, `std.sha1`, `std.sha256`, `std.sha512`, `std.sha3`
`std.equalsIgnoreCase`, `std.sha1`, `std.sha256`, `std.sha512`, `std.sha3` [#204](https://github.com/databricks/sjsonnet/pull/210)
- fix: std.manifestJsonMinified and empty arrays/objects [#207](https://github.com/databricks/sjsonnet/pull/207)
- fix: Use different chars for synthetic paths. [#208](https://github.com/databricks/sjsonnet/pull/208)
- Fix sorting algorithm to work for all array types [#211](https://github.com/databricks/sjsonnet/pull/211)
- Add better error handling for format [#212](https://github.com/databricks/sjsonnet/pull/212)

### 0.4.10

Expand Down
36 changes: 27 additions & 9 deletions sjsonnet/src/sjsonnet/Format.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ object Format{
val cooked0 = formatted.conversion match{
case '%' => widenRaw(formatted, "%")
case _ =>

if (values.isInstanceOf[Val.Arr] && i >= values.cast[Val.Arr].length) {
Error.fail("Too few values to format: %d, expected at least %d".format(values.cast[Val.Arr].length, i + 1))
}
val raw = formatted.label match{
case None => values.cast[Val.Arr].force(i)
case Some(key) =>
Expand All @@ -116,9 +118,12 @@ object Format{
}
i += 1
value match{
case ujson.Str(s) => widenRaw(formatted, s)
case ujson.Str(s) =>
if (formatted.conversion != 's' && formatted.conversion != 'c')
Error.fail("Format required a number at %d, got string".format(i))
widenRaw(formatted, s)
case ujson.Num(s) =>
formatted.conversion match{
formatted.conversion match {
case 'd' | 'i' | 'u' => formatInteger(formatted, s)
case 'o' => formatOctal(formatted, s)
case 'x' => formatHexadecimal(formatted, s)
Expand All @@ -132,20 +137,33 @@ object Format{
case 's' =>
if (s.toLong == s) widenRaw(formatted, s.toLong.toString)
else widenRaw(formatted, s.toString)
case _ => Error.fail("Format required a %s at %d, got string".format(raw.prettyName, i))
}
case ujson.Bool(s) =>
formatted.conversion match {
case 'd' | 'i' | 'u' => formatInteger(formatted, s.compareTo(false))
case 'o' => formatOctal(formatted, s.compareTo(false))
case 'x' => formatHexadecimal(formatted, s.compareTo(false))
case 'X' => formatHexadecimal(formatted, s.compareTo(false)).toUpperCase
case 'e' => formatExponent(formatted, s.compareTo(false)).toLowerCase
case 'E' => formatExponent(formatted, s.compareTo(false))
case 'f' | 'F' => formatFloat(formatted, s.compareTo(false))
case 'g' => formatGeneric(formatted, s.compareTo(false)).toLowerCase
case 'G' => formatGeneric(formatted, s.compareTo(false))
case 'c' => widenRaw(formatted, Character.forDigit(s.compareTo(false), 10).toString)
case 's' => widenRaw(formatted, s.toString)
case _ => Error.fail("Format required a %s at %d, got string".format(raw.prettyName, i))
}
case ujson.True => widenRaw(formatted, "true")
case ujson.False => widenRaw(formatted, "false")
case v => widenRaw(formatted, v.toString)
}

}

output.append(cooked0)
output.append(literal)


}

if (values.isInstanceOf[Val.Arr] && i < values.cast[Val.Arr].length) {
Error.fail("Too many values to format: %d, expected %d".format(values.cast[Val.Arr].length, i))
}
output.toString()
}

Expand Down
13 changes: 13 additions & 0 deletions sjsonnet/test/src/sjsonnet/FormatTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ object FormatTests extends TestSuite{
assert(formatted == expected)
}

def checkErr(fmt: String, jsonStr: String, expectedErr: String) = {
try {
check(fmt, jsonStr, "")
} catch {
case e: Error =>
assert(e.getMessage == expectedErr)
}
}

def tests = Tests{
test("hash"){
// #
Expand Down Expand Up @@ -290,6 +299,10 @@ object FormatTests extends TestSuite{

// apparently you can pass in positional parameters to named interpolations
check("XXX%(ignored_lols)sXXX %s", """[1.1, 2]""", "XXX1.1XXX 2")

checkErr("%s %s %s %s %s", """["foo"]""", "Too few values to format: 1, expected at least 2")
checkErr("%s %s", """["foo", "bar", "baz"]""", "Too many values to format: 3, expected 2")
checkErr("%d", """["foo"]""", "Format required a number at 1, got string")
}
}
}

0 comments on commit 7e2b6a3

Please sign in to comment.