For compatability, emit the \n within the library, not the cmd (#137)

* For compatability, emit the \n within the library, not the commandline tool
* Also add manifestString to library
This commit is contained in:
Dave Cunningham 2017-10-29 21:41:01 -04:00 committed by GitHub
parent 3eaf189897
commit f965f9ee04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 15 deletions

View File

@ -17,6 +17,7 @@ limitations under the License.
package jsonnet package jsonnet
import ( import (
"bytes"
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
@ -240,11 +241,12 @@ func builtinToString(e *evaluator, xp potentialValue) (value, error) {
case *valueString: case *valueString:
return x, nil return x, nil
} }
s, err := e.i.manifestAndSerializeJSON(e.trace, x, false, "") var buf bytes.Buffer
err = e.i.manifestAndSerializeJSON(&buf, e.trace, x, false, "")
if err != nil { if err != nil {
return nil, err return nil, err
} }
return makeValueString(s), nil return makeValueString(buf.String()), nil
} }
func builtinMakeArray(e *evaluator, szp potentialValue, funcp potentialValue) (value, error) { func builtinMakeArray(e *evaluator, szp potentialValue, funcp potentialValue) (value, error) {

View File

@ -723,16 +723,28 @@ func serializeJSON(v interface{}, multiline bool, indent string, buf *bytes.Buff
} }
} }
func (i *interpreter) manifestAndSerializeJSON(trace *TraceElement, v value, multiline bool, indent string) (string, error) { func (i *interpreter) manifestAndSerializeJSON(
var buf bytes.Buffer buf *bytes.Buffer, trace *TraceElement, v value, multiline bool, indent string) error {
manifested, err := i.manifestJSON(trace, v) manifested, err := i.manifestJSON(trace, v)
if err != nil { if err != nil {
return "", err return err
} }
serializeJSON(manifested, multiline, indent, &buf) serializeJSON(manifested, multiline, indent, buf)
return buf.String(), nil return nil
} }
// manifestString expects the value to be a string and returns it.
func (i *interpreter) manifestString(buf *bytes.Buffer, trace *TraceElement, v value) error {
switch v := v.(type) {
case *valueString:
buf.WriteString(v.getString())
return nil
default:
return makeRuntimeError(fmt.Sprint("Expected string result, got: " + v.getType().name), i.getCurrentStackTrace(trace))
}
}
func jsonToValue(e *evaluator, v interface{}) (value, error) { func jsonToValue(e *evaluator, v interface{}) (value, error) {
switch v := v.(type) { switch v := v.(type) {
case nil: case nil:
@ -879,7 +891,8 @@ func makeInitialEnv(filename string, baseStd valueObject) environment {
} }
// TODO(sbarzowski) this function takes far too many arguments - build interpreter in vm instead // TODO(sbarzowski) this function takes far too many arguments - build interpreter in vm instead
func evaluate(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string]*NativeFunction, maxStack int, importer Importer) (string, error) { func evaluate(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string]*NativeFunction,
maxStack int, importer Importer, stringOutput bool) (string, error) {
i, err := buildInterpreter(ext, nativeFuncs, maxStack, importer) i, err := buildInterpreter(ext, nativeFuncs, maxStack, importer)
if err != nil { if err != nil {
return "", err return "", err
@ -915,9 +928,15 @@ func evaluate(node ast.Node, ext vmExtMap, tla vmExtMap, nativeFuncs map[string]
manifestationTrace := &TraceElement{ manifestationTrace := &TraceElement{
loc: &manifestationLoc, loc: &manifestationLoc,
} }
s, err := i.manifestAndSerializeJSON(manifestationTrace, result, true, "") var buf bytes.Buffer
if stringOutput {
err = i.manifestString(&buf, manifestationTrace, result)
} else {
err = i.manifestAndSerializeJSON(&buf, manifestationTrace, result, true, "")
}
if err != nil { if err != nil {
return "", err return "", err
} }
return s, nil buf.WriteString("\n")
return buf.String(), nil
} }

View File

@ -114,5 +114,5 @@ func main() {
fmt.Fprintf(os.Stderr, "%v\n", err.Error()) fmt.Fprintf(os.Stderr, "%v\n", err.Error())
os.Exit(2) os.Exit(2)
} }
fmt.Println(json) fmt.Print(json)
} }

View File

@ -127,8 +127,8 @@ func TestMain(t *testing.T) {
// TODO(sbarzowski) perhaps somehow mark that we are processing // TODO(sbarzowski) perhaps somehow mark that we are processing
// an error. But for now we can treat them the same. // an error. But for now we can treat them the same.
output = errFormatter.format(err) output = errFormatter.format(err)
}
output += "\n" output += "\n"
}
if *update { if *update {
err := ioutil.WriteFile(test.golden, []byte(output), 0666) err := ioutil.WriteFile(test.golden, []byte(output), 0666)
if err != nil { if err != nil {
@ -260,13 +260,13 @@ func TestCustomImporter(t *testing.T) {
}, },
}) })
input := `[import "a.jsonnet", importstr "b.jsonnet"]` input := `[import "a.jsonnet", importstr "b.jsonnet"]`
expected := `[ 4, "3 + 3" ]` expected := `[ 4, "3 + 3" ] `
actual, err := vm.EvaluateSnippet("custom_import.jsonnet", input) actual, err := vm.EvaluateSnippet("custom_import.jsonnet", input)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
actual = removeExcessiveWhitespace(actual) actual = removeExcessiveWhitespace(actual)
if actual != expected { if actual != expected {
t.Errorf("Expected %v, but got %v", expected, actual) t.Errorf("Expected %q, but got %q", expected, actual)
} }
} }

3
vm.go
View File

@ -38,6 +38,7 @@ type VM struct {
nativeFuncs map[string]*NativeFunction nativeFuncs map[string]*NativeFunction
importer Importer importer Importer
ef ErrorFormatter ef ErrorFormatter
StringOutput bool
} }
// External variable or top level argument provided before execution // External variable or top level argument provided before execution
@ -98,7 +99,7 @@ func (vm *VM) evaluateSnippet(filename string, snippet string) (output string, e
if err != nil { if err != nil {
return "", err return "", err
} }
output, err = evaluate(node, vm.ext, vm.tla, vm.nativeFuncs, vm.MaxStack, vm.importer) output, err = evaluate(node, vm.ext, vm.tla, vm.nativeFuncs, vm.MaxStack, vm.importer, vm.StringOutput)
if err != nil { if err != nil {
return "", err return "", err
} }