Add format APIs to C bindings

This commit is contained in:
Kohei Suzuki 2020-11-24 20:10:40 +09:00 committed by Stanisław Barzowski
parent 57e6137c93
commit 35acb29ff8
2 changed files with 223 additions and 2 deletions

View File

@ -209,6 +209,64 @@ lib.jsonnet_json_destroy.argtypes = [
]
lib.jsonnet_json_destroy.restype = None
# fmt declaration
lib.jsonnet_fmt_snippet.argtypes = [
ctypes.c_void_p,
ctypes.c_char_p,
ctypes.c_char_p,
ctypes.POINTER(ctypes.c_int),
]
lib.jsonnet_fmt_snippet.restype = ctypes.POINTER(ctypes.c_char)
lib.jsonnet_fmt_indent.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_indent.restype = None
lib.jsonnet_fmt_max_blank_lines.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_max_blank_lines.restype = None
lib.jsonnet_fmt_string.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_string.restype = None
lib.jsonnet_fmt_comment.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_comment.restype = None
lib.jsonnet_fmt_pad_arrays.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_pad_arrays.restype = None
lib.jsonnet_fmt_pad_objects.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_pad_objects.restype = None
lib.jsonnet_fmt_pretty_field_names.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_pretty_field_names.restype = None
lib.jsonnet_fmt_sort_imports.argtypes = [
ctypes.c_void_p,
ctypes.c_int,
]
lib.jsonnet_fmt_sort_imports.restype = None
# utils
def free_buffer(vm, buf):
@ -500,5 +558,68 @@ class TestJsonnetJsonValueBindings(unittest.TestCase):
def tearDown(self):
lib.jsonnet_destroy(self.vm)
class TestJsonnetFormatBindings(unittest.TestCase):
def setUp(self):
self.err = ctypes.c_int()
self.err_ref = ctypes.byref(self.err)
self.vm = lib.jsonnet_make()
def test_format(self):
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"local a = import 'z.libsonnet';\nlocal b = import 'y.libsonnet';\n{'n':1, s: \"y\", a: [1,2]}", self.err_ref)
self.assertEqual(b"local b = import 'y.libsonnet';\nlocal a = import 'z.libsonnet';\n{ n: 1, s: 'y', a: [1, 2] }\n", to_bytes(res))
free_buffer(self.vm, res)
def test_indent(self):
lib.jsonnet_fmt_indent(self.vm, 8)
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"{\nx:1,\ny:2\n}", self.err_ref)
self.assertEqual(b"{\n x: 1,\n y: 2,\n}\n", to_bytes(res))
free_buffer(self.vm, res)
def test_max_blank_lines(self):
lib.jsonnet_fmt_max_blank_lines(self.vm, 2)
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"{\nx:1,\n\n\n\n\ny:2\n}", self.err_ref)
self.assertEqual(b"{\n x: 1,\n\n\n y: 2,\n}\n", to_bytes(res))
free_buffer(self.vm, res)
def test_string(self):
lib.jsonnet_fmt_string(self.vm, ord('d'))
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"{x:'x'}", self.err_ref)
self.assertEqual(b"{ x: \"x\" }\n", to_bytes(res))
free_buffer(self.vm, res)
def test_comment(self):
lib.jsonnet_fmt_comment(self.vm, ord('h'))
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"// comment\n{}", self.err_ref)
self.assertEqual(b"# comment\n{}\n", to_bytes(res))
free_buffer(self.vm, res)
def test_pad_arrays(self):
lib.jsonnet_fmt_pad_arrays(self.vm, 1)
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"{x:[1,2,3]}", self.err_ref)
self.assertEqual(b"{ x: [ 1, 2, 3 ] }\n", to_bytes(res))
free_buffer(self.vm, res)
def test_pad_objects(self):
lib.jsonnet_fmt_pad_objects(self.vm, 0)
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"{ x: 1 }", self.err_ref)
self.assertEqual(b"{x: 1}\n", to_bytes(res))
free_buffer(self.vm, res)
def test_pretty_field_names(self):
lib.jsonnet_fmt_pretty_field_names(self.vm, 0)
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"{ 'x': 1 }", self.err_ref)
self.assertEqual(b"{ 'x': 1 }\n", to_bytes(res))
free_buffer(self.vm, res)
def test_sort_imports(self):
lib.jsonnet_fmt_sort_imports(self.vm, 0)
res = lib.jsonnet_fmt_snippet(self.vm, b"fmt", b"local a = import 'z.libsonnet';\nlocal b = import 'y.libsonnet';\na+b", self.err_ref)
self.assertEqual(b"local a = import 'z.libsonnet';\nlocal b = import 'y.libsonnet';\na + b\n", to_bytes(res))
free_buffer(self.vm, res)
def tearDown(self):
lib.jsonnet_destroy(self.vm)
if __name__ == '__main__':
unittest.main()

View File

@ -9,6 +9,7 @@ import (
"github.com/google/go-jsonnet"
"github.com/google/go-jsonnet/ast"
"github.com/google/go-jsonnet/formatter"
// #cgo CXXFLAGS: -std=c++11 -Wall -I../cpp-jsonnet/include
// #include "internal.h"
@ -22,7 +23,8 @@ import (
type vm struct {
*jsonnet.VM
importer *jsonnet.FileImporter
importer *jsonnet.FileImporter
formatOptions formatter.Options
}
type jsonValue struct {
@ -100,7 +102,7 @@ func jsonnet_version() *C.char {
//export jsonnet_make
func jsonnet_make() *C.struct_JsonnetVm {
newVM := &vm{jsonnet.MakeVM(), &jsonnet.FileImporter{}}
newVM := &vm{jsonnet.MakeVM(), &jsonnet.FileImporter{}, formatter.DefaultOptions()}
newVM.Importer(newVM.importer)
id, err := handles.make(newVM)
@ -539,5 +541,103 @@ func getJSONValue(jsonRef *C.struct_JsonnetJsonValue) *jsonValue {
return v
}
//export jsonnet_fmt_indent
func jsonnet_fmt_indent(vmRef *C.struct_JsonnetVm, n C.int) {
vm := getVM(vmRef)
vm.formatOptions.Indent = int(n)
}
//export jsonnet_fmt_max_blank_lines
func jsonnet_fmt_max_blank_lines(vmRef *C.struct_JsonnetVm, n C.int) {
vm := getVM(vmRef)
vm.formatOptions.MaxBlankLines = int(n)
}
//export jsonnet_fmt_string
func jsonnet_fmt_string(vmRef *C.struct_JsonnetVm, c C.int) {
vm := getVM(vmRef)
switch c {
case 'd':
vm.formatOptions.StringStyle = formatter.StringStyleDouble
case 's':
vm.formatOptions.StringStyle = formatter.StringStyleSingle
case 'l':
vm.formatOptions.StringStyle = formatter.StringStyleLeave
default:
vm.formatOptions.StringStyle = formatter.StringStyleLeave
}
}
//export jsonnet_fmt_comment
func jsonnet_fmt_comment(vmRef *C.struct_JsonnetVm, c C.int) {
vm := getVM(vmRef)
switch c {
case 'h':
vm.formatOptions.CommentStyle = formatter.CommentStyleHash
case 's':
vm.formatOptions.CommentStyle = formatter.CommentStyleSlash
case 'l':
vm.formatOptions.CommentStyle = formatter.CommentStyleLeave
default:
vm.formatOptions.CommentStyle = formatter.CommentStyleLeave
}
}
//export jsonnet_fmt_pad_arrays
func jsonnet_fmt_pad_arrays(vmRef *C.struct_JsonnetVm, v C.int) {
vm := getVM(vmRef)
vm.formatOptions.PadArrays = v != 0
}
//export jsonnet_fmt_pad_objects
func jsonnet_fmt_pad_objects(vmRef *C.struct_JsonnetVm, v C.int) {
vm := getVM(vmRef)
vm.formatOptions.PadObjects = v != 0
}
//export jsonnet_fmt_pretty_field_names
func jsonnet_fmt_pretty_field_names(vmRef *C.struct_JsonnetVm, v C.int) {
vm := getVM(vmRef)
vm.formatOptions.PrettyFieldNames = v != 0
}
//export jsonnet_fmt_sort_imports
func jsonnet_fmt_sort_imports(vmRef *C.struct_JsonnetVm, v C.int) {
vm := getVM(vmRef)
vm.formatOptions.SortImports = v != 0
}
//export jsonnet_fmt_snippet
func jsonnet_fmt_snippet(vmRef *C.struct_JsonnetVm, filename *C.char, code *C.char, e *C.int) *C.char {
f := C.GoString(filename)
s := C.GoString(code)
return formatSnippet(vmRef, f, s, e)
}
//export jsonnet_fmt_file
func jsonnet_fmt_file(vmRef *C.struct_JsonnetVm, filename *C.char, e *C.int) *C.char {
f := C.GoString(filename)
data, err := ioutil.ReadFile(f)
if err != nil {
*e = 1
return C.CString(fmt.Sprintf("Failed to read input file: %s: %s", f, err.Error()))
}
return formatSnippet(vmRef, f, string(data), e)
}
func formatSnippet(vmRef *C.struct_JsonnetVm, filename string, code string, e *C.int) *C.char {
vm := getVM(vmRef)
out, err := formatter.Format(filename, code, vm.formatOptions)
var result *C.char
if err != nil {
*e = 1
result = C.CString(err.Error())
} else {
*e = 0
result = C.CString(out)
}
return result
}
func main() {
}