Make golangci-lint happy

Some of the suggestions are minor bug fixes (missing error handling).
This commit is contained in:
Stanisław Barzowski 2020-03-01 20:19:23 +01:00
parent 803ad646cb
commit 9ada769ce4
22 changed files with 290 additions and 426 deletions

View File

@ -429,7 +429,8 @@ type Index struct {
// When Index is being used, this is the fodder before the ']'.
// When Id is being used, this is always empty.
RightBracketFodder Fodder
Id *Identifier
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id *Identifier
}
// Slice represents an array slice a[begin:end:step].
@ -576,9 +577,10 @@ type ObjectField struct {
// If Method is set then Expr2 == Method.Body.
// There is no base fodder in Method because there was no `function`
// keyword.
Method *Function
Fodder1 Fodder
Expr1 Node // Not in scope of the object
Method *Function
Fodder1 Fodder
Expr1 Node // Not in scope of the object
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id *Identifier
Fodder2 Fodder
OpFodder Fodder
@ -676,7 +678,8 @@ type SuperIndex struct {
// If super.f, the fodder before the 'f'
// If super[e], the fodder before the ']'.
IDFodder Fodder
Id *Identifier
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id *Identifier
}
// InSuper represents the e in super construct.
@ -734,6 +737,7 @@ type Unary struct {
// Var represents variables.
type Var struct {
NodeBase
//nolint: golint,stylecheck // keeping Id instead of ID for now to avoid breaking 3rd parties
Id Identifier
}

View File

@ -87,7 +87,7 @@ func MakeFodderElement(kind FodderKind, blanks int, indent int, comment []string
panic(fmt.Sprintf("FodderInterstitial but comment == %v.", comment))
}
if kind == FodderParagraph && len(comment) == 0 {
panic(fmt.Sprintf("FodderParagraph but comment was empty"))
panic("FodderParagraph but comment was empty")
}
return FodderElement{Kind: kind, Blanks: blanks, Indent: indent, Comment: comment}
}

View File

@ -45,7 +45,10 @@ func (l *Location) String() string {
return fmt.Sprintf("%v:%v", l.Line, l.Column)
}
func locationBefore(a Location, b Location) bool {
// LocationBefore returns whether one code location
// refers to the location closer to the beginning
// of the file than the other one.
func LocationBefore(a Location, b Location) bool {
if a.Line != b.Line {
return a.Line < b.Line
}

View File

@ -182,7 +182,7 @@ func builtinLength(i *interpreter, trace traceElement, x value) (value, error) {
case valueString:
num = x.length()
case *valueFunction:
for _, param := range x.Parameters() {
for _, param := range x.parameters() {
if param.defaultArg == nil {
num++
}
@ -275,9 +275,7 @@ func builtinFlatMap(i *interpreter, trace traceElement, funcv, arrv value) (valu
if err != nil {
return nil, err
}
for _, elem := range returned.elements {
elems = append(elems, elem)
}
elems = append(elems, returned.elements...)
}
return makeValueArray(elems), nil
}
@ -295,13 +293,9 @@ func joinArrays(i *interpreter, trace traceElement, sep *valueArray, arr *valueA
continue
case *valueArray:
if !first {
for _, subElem := range sep.elements {
result = append(result, subElem)
}
}
for _, subElem := range v.elements {
result = append(result, subElem)
result = append(result, sep.elements...)
}
result = append(result, v.elements...)
default:
return nil, i.typeErrorSpecific(elemValue, &valueArray{}, trace)
}
@ -435,14 +429,6 @@ func (d *sortData) Sort() (err error) {
return
}
func arrayFromThunks(vs []value) *valueArray {
thunks := make([]*cachedThunk, len(vs))
for i := range vs {
thunks[i] = readyThunk(vs[i])
}
return makeValueArray(thunks)
}
func builtinSort(i *interpreter, trace traceElement, arguments []value) (value, error) {
arrv := arguments[0]
keyFv := arguments[1]
@ -468,7 +454,10 @@ func builtinSort(i *interpreter, trace traceElement, arguments []value) (value,
}
}
data.Sort()
err = data.Sort()
if err != nil {
return nil, err
}
return makeValueArray(data.thunks), nil
}
@ -705,8 +694,8 @@ func builtinBase64(i *interpreter, trace traceElement, input value) (value, erro
return nil, err
}
runes := []rune(vStr.getGoString())
for _, r := range runes {
str := vStr.getGoString()
for _, r := range str {
n := int(r)
msg, ok := sanityCheck(n)
if !ok {
@ -714,7 +703,7 @@ func builtinBase64(i *interpreter, trace traceElement, input value) (value, erro
}
}
byteArr = []byte(string(vStr.getGoString()))
byteArr = []byte(str)
case *valueArray:
vArr, err := i.getArray(input, trace)
if err != nil {
@ -1227,9 +1216,9 @@ func flattenArgs(args callArguments, params []namedParameter, defaults []value)
type unaryBuiltinFunc func(*interpreter, traceElement, value) (value, error)
type unaryBuiltin struct {
name ast.Identifier
function unaryBuiltinFunc
parameters ast.Identifiers
name ast.Identifier
function unaryBuiltinFunc
params ast.Identifiers
}
func getBuiltinTrace(trace traceElement, name ast.Identifier) traceElement {
@ -1238,7 +1227,7 @@ func getBuiltinTrace(trace traceElement, name ast.Identifier) traceElement {
}
func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
flatArgs := flattenArgs(args, b.Parameters(), []value{})
flatArgs := flattenArgs(args, b.parameters(), []value{})
builtinTrace := getBuiltinTrace(trace, b.name)
x, err := flatArgs[0].getValue(i, trace)
if err != nil {
@ -1247,10 +1236,10 @@ func (b *unaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceE
return b.function(i, builtinTrace, x)
}
func (b *unaryBuiltin) Parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters))
func (b *unaryBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.params))
for i := range ret {
ret[i].name = b.parameters[i]
ret[i].name = b.params[i]
}
return ret
}
@ -1262,13 +1251,13 @@ func (b *unaryBuiltin) Name() ast.Identifier {
type binaryBuiltinFunc func(*interpreter, traceElement, value, value) (value, error)
type binaryBuiltin struct {
name ast.Identifier
function binaryBuiltinFunc
parameters ast.Identifiers
name ast.Identifier
function binaryBuiltinFunc
params ast.Identifiers
}
func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
flatArgs := flattenArgs(args, b.Parameters(), []value{})
flatArgs := flattenArgs(args, b.parameters(), []value{})
builtinTrace := getBuiltinTrace(trace, b.name)
x, err := flatArgs[0].getValue(i, trace)
if err != nil {
@ -1281,10 +1270,10 @@ func (b *binaryBuiltin) evalCall(args callArguments, i *interpreter, trace trace
return b.function(i, builtinTrace, x, y)
}
func (b *binaryBuiltin) Parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters))
func (b *binaryBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.params))
for i := range ret {
ret[i].name = b.parameters[i]
ret[i].name = b.params[i]
}
return ret
}
@ -1296,13 +1285,13 @@ func (b *binaryBuiltin) Name() ast.Identifier {
type ternaryBuiltinFunc func(*interpreter, traceElement, value, value, value) (value, error)
type ternaryBuiltin struct {
name ast.Identifier
function ternaryBuiltinFunc
parameters ast.Identifiers
name ast.Identifier
function ternaryBuiltinFunc
params ast.Identifiers
}
func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
flatArgs := flattenArgs(args, b.Parameters(), []value{})
flatArgs := flattenArgs(args, b.parameters(), []value{})
builtinTrace := getBuiltinTrace(trace, b.name)
x, err := flatArgs[0].getValue(i, trace)
if err != nil {
@ -1319,10 +1308,10 @@ func (b *ternaryBuiltin) evalCall(args callArguments, i *interpreter, trace trac
return b.function(i, builtinTrace, x, y, z)
}
func (b *ternaryBuiltin) Parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters))
func (b *ternaryBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.params))
for i := range ret {
ret[i].name = b.parameters[i]
ret[i].name = b.params[i]
}
return ret
}
@ -1345,16 +1334,16 @@ type generalBuiltinParameter struct {
// have optional parameters. The optional ones have non-nil defaultValues
// at the same index.
type generalBuiltin struct {
name ast.Identifier
parameters []generalBuiltinParameter
function generalBuiltinFunc
name ast.Identifier
params []generalBuiltinParameter
function generalBuiltinFunc
}
func (b *generalBuiltin) Parameters() []namedParameter {
ret := make([]namedParameter, len(b.parameters))
func (b *generalBuiltin) parameters() []namedParameter {
ret := make([]namedParameter, len(b.params))
for i := range ret {
ret[i].name = b.parameters[i].name
if b.parameters[i].defaultValue != nil {
ret[i].name = b.params[i].name
if b.params[i].defaultValue != nil {
// This is not actually used because the defaultValue is used instead.
// The only reason we don't leave it nil is because the checkArguments
// function uses the non-nil status to indicate that the parameter
@ -1366,9 +1355,9 @@ func (b *generalBuiltin) Parameters() []namedParameter {
}
func (b *generalBuiltin) defaultValues() []value {
ret := make([]value, len(b.parameters))
ret := make([]value, len(b.params))
for i := range ret {
ret[i] = b.parameters[i].defaultValue
ret[i] = b.params[i].defaultValue
}
return ret
}
@ -1378,7 +1367,7 @@ func (b *generalBuiltin) Name() ast.Identifier {
}
func (b *generalBuiltin) evalCall(args callArguments, i *interpreter, trace traceElement) (value, error) {
flatArgs := flattenArgs(args, b.Parameters(), b.defaultValues())
flatArgs := flattenArgs(args, b.parameters(), b.defaultValues())
builtinTrace := getBuiltinTrace(trace, b.name)
values := make([]value, len(flatArgs))
for j := 0; j < len(values); j++ {
@ -1393,38 +1382,38 @@ func (b *generalBuiltin) evalCall(args callArguments, i *interpreter, trace trac
// End of builtin utils
var builtinID = &unaryBuiltin{name: "id", function: builtinIdentity, parameters: ast.Identifiers{"x"}}
var builtinID = &unaryBuiltin{name: "id", function: builtinIdentity, params: ast.Identifiers{"x"}}
var functionID = &valueFunction{ec: builtinID}
var bopBuiltins = []*binaryBuiltin{
// Note that % and `in` are desugared instead of being handled here
ast.BopMult: &binaryBuiltin{name: "operator*", function: builtinMult, parameters: ast.Identifiers{"x", "y"}},
ast.BopDiv: &binaryBuiltin{name: "operator/", function: builtinDiv, parameters: ast.Identifiers{"x", "y"}},
ast.BopMult: &binaryBuiltin{name: "operator*", function: builtinMult, params: ast.Identifiers{"x", "y"}},
ast.BopDiv: &binaryBuiltin{name: "operator/", function: builtinDiv, params: ast.Identifiers{"x", "y"}},
ast.BopPlus: &binaryBuiltin{name: "operator+", function: builtinPlus, parameters: ast.Identifiers{"x", "y"}},
ast.BopMinus: &binaryBuiltin{name: "operator-", function: builtinMinus, parameters: ast.Identifiers{"x", "y"}},
ast.BopPlus: &binaryBuiltin{name: "operator+", function: builtinPlus, params: ast.Identifiers{"x", "y"}},
ast.BopMinus: &binaryBuiltin{name: "operator-", function: builtinMinus, params: ast.Identifiers{"x", "y"}},
ast.BopShiftL: &binaryBuiltin{name: "operator<<", function: builtinShiftL, parameters: ast.Identifiers{"x", "y"}},
ast.BopShiftR: &binaryBuiltin{name: "operator>>", function: builtinShiftR, parameters: ast.Identifiers{"x", "y"}},
ast.BopShiftL: &binaryBuiltin{name: "operator<<", function: builtinShiftL, params: ast.Identifiers{"x", "y"}},
ast.BopShiftR: &binaryBuiltin{name: "operator>>", function: builtinShiftR, params: ast.Identifiers{"x", "y"}},
ast.BopGreater: &binaryBuiltin{name: "operator>", function: builtinGreater, parameters: ast.Identifiers{"x", "y"}},
ast.BopGreaterEq: &binaryBuiltin{name: "operator>=", function: builtinGreaterEq, parameters: ast.Identifiers{"x", "y"}},
ast.BopLess: &binaryBuiltin{name: "operator<,", function: builtinLess, parameters: ast.Identifiers{"x", "y"}},
ast.BopLessEq: &binaryBuiltin{name: "operator<=", function: builtinLessEq, parameters: ast.Identifiers{"x", "y"}},
ast.BopGreater: &binaryBuiltin{name: "operator>", function: builtinGreater, params: ast.Identifiers{"x", "y"}},
ast.BopGreaterEq: &binaryBuiltin{name: "operator>=", function: builtinGreaterEq, params: ast.Identifiers{"x", "y"}},
ast.BopLess: &binaryBuiltin{name: "operator<,", function: builtinLess, params: ast.Identifiers{"x", "y"}},
ast.BopLessEq: &binaryBuiltin{name: "operator<=", function: builtinLessEq, params: ast.Identifiers{"x", "y"}},
ast.BopManifestEqual: &binaryBuiltin{name: "operator==", function: builtinEquals, parameters: ast.Identifiers{"x", "y"}},
ast.BopManifestUnequal: &binaryBuiltin{name: "operator!=", function: builtinNotEquals, parameters: ast.Identifiers{"x", "y"}}, // Special case
ast.BopManifestEqual: &binaryBuiltin{name: "operator==", function: builtinEquals, params: ast.Identifiers{"x", "y"}},
ast.BopManifestUnequal: &binaryBuiltin{name: "operator!=", function: builtinNotEquals, params: ast.Identifiers{"x", "y"}}, // Special case
ast.BopBitwiseAnd: &binaryBuiltin{name: "operator&", function: builtinBitwiseAnd, parameters: ast.Identifiers{"x", "y"}},
ast.BopBitwiseXor: &binaryBuiltin{name: "operator^", function: builtinBitwiseXor, parameters: ast.Identifiers{"x", "y"}},
ast.BopBitwiseOr: &binaryBuiltin{name: "operator|", function: builtinBitwiseOr, parameters: ast.Identifiers{"x", "y"}},
ast.BopBitwiseAnd: &binaryBuiltin{name: "operator&", function: builtinBitwiseAnd, params: ast.Identifiers{"x", "y"}},
ast.BopBitwiseXor: &binaryBuiltin{name: "operator^", function: builtinBitwiseXor, params: ast.Identifiers{"x", "y"}},
ast.BopBitwiseOr: &binaryBuiltin{name: "operator|", function: builtinBitwiseOr, params: ast.Identifiers{"x", "y"}},
}
var uopBuiltins = []*unaryBuiltin{
ast.UopNot: &unaryBuiltin{name: "operator!", function: builtinNegation, parameters: ast.Identifiers{"x"}},
ast.UopBitwiseNot: &unaryBuiltin{name: "operator~", function: builtinBitNeg, parameters: ast.Identifiers{"x"}},
ast.UopPlus: &unaryBuiltin{name: "operator+ (unary)", function: builtinUnaryPlus, parameters: ast.Identifiers{"x"}},
ast.UopMinus: &unaryBuiltin{name: "operator- (unary)", function: builtinUnaryMinus, parameters: ast.Identifiers{"x"}},
ast.UopNot: &unaryBuiltin{name: "operator!", function: builtinNegation, params: ast.Identifiers{"x"}},
ast.UopBitwiseNot: &unaryBuiltin{name: "operator~", function: builtinBitNeg, params: ast.Identifiers{"x"}},
ast.UopPlus: &unaryBuiltin{name: "operator+ (unary)", function: builtinUnaryPlus, params: ast.Identifiers{"x"}},
ast.UopMinus: &unaryBuiltin{name: "operator- (unary)", function: builtinUnaryMinus, params: ast.Identifiers{"x"}},
}
func buildBuiltinMap(builtins []builtin) map[string]evalCallable {
@ -1437,51 +1426,51 @@ func buildBuiltinMap(builtins []builtin) map[string]evalCallable {
var funcBuiltins = buildBuiltinMap([]builtin{
builtinID,
&unaryBuiltin{name: "extVar", function: builtinExtVar, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "length", function: builtinLength, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "toString", function: builtinToString, parameters: ast.Identifiers{"a"}},
&binaryBuiltin{name: "trace", function: builtinTrace, parameters: ast.Identifiers{"str", "rest"}},
&binaryBuiltin{name: "makeArray", function: builtinMakeArray, parameters: ast.Identifiers{"sz", "func"}},
&binaryBuiltin{name: "flatMap", function: builtinFlatMap, parameters: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "join", function: builtinJoin, parameters: ast.Identifiers{"sep", "arr"}},
&unaryBuiltin{name: "reverse", function: builtinReverse, parameters: ast.Identifiers{"arr"}},
&binaryBuiltin{name: "filter", function: builtinFilter, parameters: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "range", function: builtinRange, parameters: ast.Identifiers{"from", "to"}},
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, parameters: ast.Identifiers{"x", "y"}},
&binaryBuiltin{name: "equals", function: builtinEquals, parameters: ast.Identifiers{"x", "y"}},
&binaryBuiltin{name: "objectFieldsEx", function: builtinObjectFieldsEx, parameters: ast.Identifiers{"obj", "hidden"}},
&ternaryBuiltin{name: "objectHasEx", function: builtinObjectHasEx, parameters: ast.Identifiers{"obj", "fname", "hidden"}},
&unaryBuiltin{name: "type", function: builtinType, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "char", function: builtinChar, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "codepoint", function: builtinCodepoint, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "ceil", function: builtinCeil, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "floor", function: builtinFloor, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "sqrt", function: builtinSqrt, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "sin", function: builtinSin, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "cos", function: builtinCos, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "tan", function: builtinTan, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "asin", function: builtinAsin, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "acos", function: builtinAcos, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "atan", function: builtinAtan, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "log", function: builtinLog, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "exp", function: builtinExp, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "mantissa", function: builtinMantissa, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "exponent", function: builtinExponent, parameters: ast.Identifiers{"x"}},
&binaryBuiltin{name: "pow", function: builtinPow, parameters: ast.Identifiers{"base", "exp"}},
&binaryBuiltin{name: "modulo", function: builtinModulo, parameters: ast.Identifiers{"x", "y"}},
&unaryBuiltin{name: "md5", function: builtinMd5, parameters: ast.Identifiers{"x"}},
&ternaryBuiltin{name: "substr", function: builtinSubstr, parameters: ast.Identifiers{"str", "from", "len"}},
&ternaryBuiltin{name: "splitLimit", function: builtinSplitLimit, parameters: ast.Identifiers{"str", "c", "maxsplits"}},
&ternaryBuiltin{name: "strReplace", function: builtinStrReplace, parameters: ast.Identifiers{"str", "from", "to"}},
&unaryBuiltin{name: "base64Decode", function: builtinBase64Decode, parameters: ast.Identifiers{"str"}},
&unaryBuiltin{name: "base64DecodeBytes", function: builtinBase64DecodeBytes, parameters: ast.Identifiers{"str"}},
&unaryBuiltin{name: "parseJson", function: builtinParseJSON, parameters: ast.Identifiers{"str"}},
&unaryBuiltin{name: "base64", function: builtinBase64, parameters: ast.Identifiers{"input"}},
&unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, parameters: ast.Identifiers{"str"}},
&unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, parameters: ast.Identifiers{"arr"}},
&generalBuiltin{name: "sort", function: builtinSort, parameters: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
&unaryBuiltin{name: "native", function: builtinNative, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "extVar", function: builtinExtVar, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "length", function: builtinLength, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "toString", function: builtinToString, params: ast.Identifiers{"a"}},
&binaryBuiltin{name: "trace", function: builtinTrace, params: ast.Identifiers{"str", "rest"}},
&binaryBuiltin{name: "makeArray", function: builtinMakeArray, params: ast.Identifiers{"sz", "func"}},
&binaryBuiltin{name: "flatMap", function: builtinFlatMap, params: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "join", function: builtinJoin, params: ast.Identifiers{"sep", "arr"}},
&unaryBuiltin{name: "reverse", function: builtinReverse, params: ast.Identifiers{"arr"}},
&binaryBuiltin{name: "filter", function: builtinFilter, params: ast.Identifiers{"func", "arr"}},
&binaryBuiltin{name: "range", function: builtinRange, params: ast.Identifiers{"from", "to"}},
&binaryBuiltin{name: "primitiveEquals", function: primitiveEquals, params: ast.Identifiers{"x", "y"}},
&binaryBuiltin{name: "equals", function: builtinEquals, params: ast.Identifiers{"x", "y"}},
&binaryBuiltin{name: "objectFieldsEx", function: builtinObjectFieldsEx, params: ast.Identifiers{"obj", "hidden"}},
&ternaryBuiltin{name: "objectHasEx", function: builtinObjectHasEx, params: ast.Identifiers{"obj", "fname", "hidden"}},
&unaryBuiltin{name: "type", function: builtinType, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "char", function: builtinChar, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "codepoint", function: builtinCodepoint, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "ceil", function: builtinCeil, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "floor", function: builtinFloor, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "sqrt", function: builtinSqrt, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "sin", function: builtinSin, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "cos", function: builtinCos, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "tan", function: builtinTan, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "asin", function: builtinAsin, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "acos", function: builtinAcos, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "atan", function: builtinAtan, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "log", function: builtinLog, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "exp", function: builtinExp, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "mantissa", function: builtinMantissa, params: ast.Identifiers{"x"}},
&unaryBuiltin{name: "exponent", function: builtinExponent, params: ast.Identifiers{"x"}},
&binaryBuiltin{name: "pow", function: builtinPow, params: ast.Identifiers{"base", "exp"}},
&binaryBuiltin{name: "modulo", function: builtinModulo, params: ast.Identifiers{"x", "y"}},
&unaryBuiltin{name: "md5", function: builtinMd5, params: ast.Identifiers{"x"}},
&ternaryBuiltin{name: "substr", function: builtinSubstr, params: ast.Identifiers{"str", "from", "len"}},
&ternaryBuiltin{name: "splitLimit", function: builtinSplitLimit, params: ast.Identifiers{"str", "c", "maxsplits"}},
&ternaryBuiltin{name: "strReplace", function: builtinStrReplace, params: ast.Identifiers{"str", "from", "to"}},
&unaryBuiltin{name: "base64Decode", function: builtinBase64Decode, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "base64DecodeBytes", function: builtinBase64DecodeBytes, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "parseJson", function: builtinParseJSON, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "base64", function: builtinBase64, params: ast.Identifiers{"input"}},
&unaryBuiltin{name: "encodeUTF8", function: builtinEncodeUTF8, params: ast.Identifiers{"str"}},
&unaryBuiltin{name: "decodeUTF8", function: builtinDecodeUTF8, params: ast.Identifiers{"arr"}},
&generalBuiltin{name: "sort", function: builtinSort, params: []generalBuiltinParameter{{name: "arr"}, {name: "keyF", defaultValue: functionID}}},
&unaryBuiltin{name: "native", function: builtinNative, params: ast.Identifiers{"x"}},
// internal
&unaryBuiltin{name: "$objectFlatMerge", function: builtinUglyObjectFlatMerge, parameters: ast.Identifiers{"x"}},
&unaryBuiltin{name: "$objectFlatMerge", function: builtinUglyObjectFlatMerge, params: ast.Identifiers{"x"}},
})

View File

@ -8,18 +8,15 @@ import (
"testing"
)
var jsonnetPath string
var outputPassthru bool
func init() {
flag.StringVar(&jsonnetPath, "jsonnetPath", "./jsonnet", "Path to jsonnet binary")
flag.BoolVar(&outputPassthru, "outputPassthru", false, "Pass stdout/err from jsonnet")
}
var (
jsonnetPath = flag.String("jsonnetPath", "./jsonnet", "Path to jsonnet binary")
outputPassthru = flag.Bool("outputPassthru", false, "Pass stdout/err from jsonnet")
)
func RunBenchmark(b *testing.B, name string) {
for n := 0; n < b.N; n++ {
cmd := exec.Command(jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name))
if outputPassthru {
cmd := exec.Command(*jsonnetPath, fmt.Sprintf("./builtin-benchmarks/%s.jsonnet", name))
if *outputPassthru {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}

View File

@ -103,7 +103,7 @@ func jsonnet_make() *C.struct_JsonnetVm {
id, err := handles.make(newVM)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
@ -113,7 +113,7 @@ func jsonnet_make() *C.struct_JsonnetVm {
//export jsonnet_destroy
func jsonnet_destroy(vmRef *C.struct_JsonnetVm) {
if err := handles.free(uint32(vmRef.id)); err != nil {
fmt.Fprintf(os.Stderr, err.Error())
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
@ -124,14 +124,14 @@ func getVM(vmRef *C.struct_JsonnetVm) *vm {
ref, err := handles.get(uint32(vmRef.id))
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
v, ok := ref.(*vm)
if !ok {
fmt.Fprintf(os.Stderr, "provided handle has a different type")
fmt.Fprintln(os.Stderr, "provided handle has a different type")
os.Exit(1)
}
@ -413,7 +413,7 @@ func jsonnet_json_destroy(vmRef *C.struct_JsonnetVm, v *C.struct_JsonnetJsonValu
}
if err := handles.free(uint32(v.id)); err != nil {
fmt.Fprintf(os.Stderr, err.Error())
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
@ -424,7 +424,7 @@ func createJSONValue(vmRef *C.struct_JsonnetVm, val interface{}) *C.struct_Jsonn
id, err := handles.make(&jsonValue{val: val})
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
@ -435,7 +435,7 @@ func getJSONValue(jsonRef *C.struct_JsonnetJsonValue) *jsonValue {
ref, err := handles.get(uint32(jsonRef.id))
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}

View File

@ -44,8 +44,14 @@ func main() {
ast := dump.Sdump(node)
dst := os.Stdout
dst.WriteString(header)
dst.WriteString(ast)
_, err = dst.WriteString(header)
if err != nil {
panic(err)
}
_, err = dst.WriteString(ast)
if err != nil {
panic(err)
}
}
var header = `

View File

@ -341,7 +341,7 @@ func readInput(config config, filename *string) (input string, err error) {
return
}
func writeMultiOutputFiles(output map[string]string, outputDir, outputFile string, createDirs bool) error {
func writeMultiOutputFiles(output map[string]string, outputDir, outputFile string, createDirs bool) (err error) {
// If multiple file output is used, then iterate over each string from
// the sequence of strings returned by jsonnet_evaluate_snippet_multi,
// construct pairs of filename and content, and write each output file.
@ -351,12 +351,15 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
if outputFile == "" {
manifest = os.Stdout
} else {
var err error
manifest, err = os.Create(outputFile)
if err != nil {
return err
}
defer manifest.Close()
defer func() {
if ferr := manifest.Close(); err != nil {
err = ferr
}
}()
}
// Iterate through the map in order.
@ -401,7 +404,11 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
if err != nil {
return err
}
defer f.Close()
defer func() {
if ferr := f.Close(); err != nil {
err = ferr
}
}()
_, err = f.WriteString(newContent)
if err != nil {
@ -413,18 +420,21 @@ func writeMultiOutputFiles(output map[string]string, outputDir, outputFile strin
}
// writeOutputStream writes the output as a YAML stream.
func writeOutputStream(output []string, outputFile string) error {
func writeOutputStream(output []string, outputFile string) (err error) {
var f *os.File
if outputFile == "" {
f = os.Stdout
} else {
var err error
f, err = os.Create(outputFile)
if err != nil {
return err
}
defer f.Close()
defer func() {
if ferr := f.Close(); err != nil {
err = ferr
}
}()
}
for _, doc := range output {
@ -448,7 +458,7 @@ func writeOutputStream(output []string, outputFile string) error {
return nil
}
func writeOutputFile(output string, outputFile string, createDirs bool) error {
func writeOutputFile(output string, outputFile string, createDirs bool) (err error) {
if outputFile == "" {
fmt.Print(output)
return nil
@ -460,11 +470,15 @@ func writeOutputFile(output string, outputFile string, createDirs bool) error {
}
}
f, err := os.Create(outputFile)
if err != nil {
f, createErr := os.Create(outputFile)
if createErr != nil {
return err
}
defer f.Close()
defer func() {
if ferr := f.Close(); err != nil {
err = ferr
}
}()
_, err = f.WriteString(output)
return err
@ -478,7 +492,10 @@ func main() {
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
err = pprof.StartCPUProfile(f)
if err != nil {
log.Fatal(err)
}
defer pprof.StopCPUProfile()
}
@ -519,7 +536,7 @@ func main() {
if len(config.inputFiles) != 1 {
// Should already have been caught by processArgs.
panic(fmt.Sprintf("Internal error: expected a single input file."))
panic("Internal error: expected a single input file.")
}
filename := config.inputFiles[0]
input, err := readInput(config, &filename)
@ -560,7 +577,11 @@ func main() {
if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatal("could not write memory profile: ", err)
}
f.Close()
defer func() {
if err := f.Close(); err != nil {
log.Fatal("Failed to close the memprofile: ", err)
}
}()
}
if err != nil {

View File

@ -105,7 +105,7 @@ func (ef *termErrorFormatter) showCode(buf *bytes.Buffer, loc ast.LocationRange)
beginning := ast.LineBeginning(&loc)
ending := ast.LineEnding(&loc)
fmt.Fprintf(buf, "%v", ef.sp.GetSnippet(beginning))
errFprintf(buf, "%v", ef.sp.GetSnippet(loc))
errFprintf(buf, "%v", ef.sp.GetSnippet(loc)) //nolint:errcheck
fmt.Fprintf(buf, "%v", ef.sp.GetSnippet(ending))
buf.WriteByte('\n')
}

View File

@ -29,7 +29,7 @@ import (
"strconv"
)
var packageNameStripperRegexp = regexp.MustCompile("\\b[a-zA-Z_]+[a-zA-Z_0-9]+\\.")
var packageNameStripperRegexp = regexp.MustCompile(`\b[a-zA-Z_]+[a-zA-Z_0-9]+\.`)
// Options represents configuration option
type Options struct {
@ -59,16 +59,22 @@ type dumpState struct {
reusedPointers []uintptr
primitivePointers []uintptr
currentPointerName string
homePackageRegexp *regexp.Regexp
homePackageRegexp *regexp.Regexp
}
func mustWrite(w io.Writer, data []byte) {
_, err := w.Write(data)
if err != nil {
panic(err)
}
}
func (s *dumpState) indent() {
s.w.Write(bytes.Repeat([]byte("\t"), s.depth))
mustWrite(s.w, bytes.Repeat([]byte("\t"), s.depth))
}
func (s *dumpState) newline() {
s.w.Write([]byte("\n"))
mustWrite(s.w, []byte("\n"))
}
func (s *dumpState) dumpType(v reflect.Value) {
@ -78,34 +84,34 @@ func (s *dumpState) dumpType(v reflect.Value) {
} else if s.homePackageRegexp != nil {
typeName = s.homePackageRegexp.ReplaceAllLiteralString(typeName, "")
}
s.w.Write([]byte(typeName))
mustWrite(s.w, []byte(typeName))
}
func (s *dumpState) dumpSlice(v reflect.Value) {
s.dumpType(v)
numEntries := v.Len()
if numEntries == 0 {
s.w.Write([]byte("{}"))
mustWrite(s.w, []byte("{}"))
return
}
s.w.Write([]byte("{"))
mustWrite(s.w, []byte("{"))
s.newline()
s.depth++
for i := 0; i < numEntries; i++ {
s.indent()
s.dumpVal(v.Index(i))
s.w.Write([]byte(","))
mustWrite(s.w, []byte(","))
s.newline()
}
s.depth--
s.indent()
s.w.Write([]byte("}"))
mustWrite(s.w, []byte("}"))
}
func (s *dumpState) dumpStruct(v reflect.Value) {
dumpPreamble := func() {
s.dumpType(v)
s.w.Write([]byte("{"))
mustWrite(s.w, []byte("{"))
s.newline()
s.depth++
}
@ -122,26 +128,26 @@ func (s *dumpState) dumpStruct(v reflect.Value) {
preambleDumped = true
}
s.indent()
s.w.Write([]byte(vtf.Name))
s.w.Write([]byte(": "))
mustWrite(s.w, []byte(vtf.Name))
mustWrite(s.w, []byte(": "))
s.dumpVal(v.Field(i))
s.w.Write([]byte(","))
mustWrite(s.w, []byte(","))
s.newline()
}
if preambleDumped {
s.depth--
s.indent()
s.w.Write([]byte("}"))
mustWrite(s.w, []byte("}"))
} else {
// There were no fields dumped
s.dumpType(v)
s.w.Write([]byte("{}"))
mustWrite(s.w, []byte("{}"))
}
}
func (s *dumpState) dumpMap(v reflect.Value) {
s.dumpType(v)
s.w.Write([]byte("{"))
mustWrite(s.w, []byte("{"))
s.newline()
s.depth++
keys := v.MapKeys()
@ -149,14 +155,14 @@ func (s *dumpState) dumpMap(v reflect.Value) {
for _, key := range keys {
s.indent()
s.dumpVal(key)
s.w.Write([]byte(": "))
mustWrite(s.w, []byte(": "))
s.dumpVal(v.MapIndex(key))
s.w.Write([]byte(","))
mustWrite(s.w, []byte(","))
s.newline()
}
s.depth--
s.indent()
s.w.Write([]byte("}"))
mustWrite(s.w, []byte("}"))
}
func (s *dumpState) dump(value interface{}) {
@ -164,7 +170,7 @@ func (s *dumpState) dump(value interface{}) {
if s.config.VariableDescription != "" {
fmt.Fprintf(s.w, "\n// %s\n", s.config.VariableDescription)
}
s.w.Write([]byte("var " + s.config.VariableName + " = "))
mustWrite(s.w, []byte("var "+s.config.VariableName+" = "))
}
if value == nil {
@ -194,11 +200,11 @@ func (s *dumpState) dump(value interface{}) {
s.dumpVal(v)
s.w = oldWriter
if buf.Len() > 100 {
s.w.Write([]byte("_" + s.config.VariableName))
mustWrite(s.w, []byte("_"+s.config.VariableName))
s.newline()
s.w.Write([]byte("var _" + s.config.VariableName + " = "))
mustWrite(s.w, []byte("var _"+s.config.VariableName+" = "))
}
s.w.Write(buf.Bytes())
mustWrite(s.w, buf.Bytes())
}
s.newline()
}
@ -206,7 +212,7 @@ func (s *dumpState) dump(value interface{}) {
func (s *dumpState) printPrimitivePointer(value reflect.Value, pointerName string) {
v := deInterface(value)
s.w.Write([]byte("var " + pointerName + "Var" + " = "))
mustWrite(s.w, []byte("var "+pointerName+"Var"+" = "))
switch v.Kind() {
case reflect.Bool:
printBool(s.w, v.Bool())
@ -244,11 +250,11 @@ func (s *dumpState) printPrimitivePointer(value reflect.Value, pointerName strin
printComplex(s.w, v.Complex(), 64)
case reflect.String:
s.w.Write([]byte(strconv.Quote(v.String())))
mustWrite(s.w, []byte(strconv.Quote(v.String())))
}
s.newline()
s.w.Write([]byte("var " + pointerName + " = &" + pointerName + "Var"))
mustWrite(s.w, []byte("var "+pointerName+" = &"+pointerName+"Var"))
s.newline()
}
@ -263,7 +269,7 @@ func (s *dumpState) dumpPrimitivePointerVal(value reflect.Value) {
case reflect.Invalid:
// Do nothing. We should never get here since invalid has already
// been handled above.
s.w.Write([]byte("<invalid>"))
mustWrite(s.w, []byte("<invalid>"))
case reflect.Slice:
if v.IsNil() {
@ -310,7 +316,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
case reflect.Invalid:
// Do nothing. We should never get here since invalid has already
// been handled above.
s.w.Write([]byte("<invalid>"))
mustWrite(s.w, []byte("<invalid>"))
case reflect.Slice:
if v.IsNil() {
@ -338,7 +344,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
case reflect.Ptr:
pointerName, isReused, isPrimitive, isFirstVisit := s.nameForPointer(v), s.isReusedPointer(v), s.isPrimitivePointer(v), s.visitPointerAndCheckIfFirstTime(v)
if isReused && !isPrimitive && isFirstVisit {
s.w.Write([]byte("var " + pointerName + " = &"))
mustWrite(s.w, []byte("var "+pointerName+" = &"))
s.dumpVal(v.Elem())
s.newline()
} else {
@ -349,7 +355,7 @@ func (s *dumpState) dumpReusedPointerVal(value reflect.Value) {
func (s *dumpState) dumpVal(value reflect.Value) {
if value.Kind() == reflect.Ptr && value.IsNil() {
s.w.Write([]byte("nil"))
mustWrite(s.w, []byte("nil"))
return
}
@ -359,7 +365,7 @@ func (s *dumpState) dumpVal(value reflect.Value) {
case reflect.Invalid:
// Do nothing. We should never get here since invalid has already
// been handled above.
s.w.Write([]byte("<invalid>"))
mustWrite(s.w, []byte("<invalid>"))
case reflect.Bool:
printBool(s.w, v.Bool())
@ -397,7 +403,7 @@ func (s *dumpState) dumpVal(value reflect.Value) {
printComplex(s.w, v.Complex(), 64)
case reflect.String:
s.w.Write([]byte(strconv.Quote(v.String())))
mustWrite(s.w, []byte(strconv.Quote(v.String())))
case reflect.Slice:
if v.IsNil() {
@ -419,9 +425,9 @@ func (s *dumpState) dumpVal(value reflect.Value) {
case reflect.Ptr:
pointerName, isPrimitive, isReused := s.nameForPointer(v), s.isPrimitivePointer(v), s.isReusedPointer(v)
if isPrimitive || isReused {
s.w.Write([]byte(pointerName))
mustWrite(s.w, []byte(pointerName))
} else {
s.w.Write([]byte("&"))
mustWrite(s.w, []byte("&"))
s.dumpVal(v.Elem())
}
@ -440,19 +446,6 @@ func (s *dumpState) dumpVal(value reflect.Value) {
}
}
// call to signal that the pointer is being visited, returns true if this is the
// first visit to that pointer. Used to detect when to output the entire contents
// behind a pointer (the first time), and when to just emit a name (all other times)
func (s *dumpState) visitPointerAndCheckIfItIsTheFirstTime(ptr uintptr) bool {
for _, addr := range s.visitedPointers {
if addr == ptr {
return false
}
}
s.visitedPointers = append(s.visitedPointers, ptr)
return true
}
func (s *dumpState) nameForPointer(v reflect.Value) string {
if isPointerValue(v) {
ptr := v.Pointer()

View File

@ -25,42 +25,42 @@ import (
)
func printBool(w io.Writer, value bool) {
w.Write([]byte(strconv.FormatBool(value)))
mustWrite(w, []byte(strconv.FormatBool(value)))
}
func printInt(w io.Writer, val reflect.Value, stripPackageName bool) {
typeName := fmt.Sprintf("%s", val.Type())
typeName := val.Type().String()
if stripPackageName && strings.HasPrefix(typeName, "ast.") {
typeName = typeName[4:]
}
w.Write([]byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatInt(val.Int(), 10))))
mustWrite(w, []byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatInt(val.Int(), 10))))
}
func printUint(w io.Writer, val reflect.Value) {
typeName := fmt.Sprintf("%s", val.Type())
w.Write([]byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatUint(val.Uint(), 10))))
typeName := val.Type().String()
mustWrite(w, []byte(fmt.Sprintf("%s(%s)", typeName, strconv.FormatUint(val.Uint(), 10))))
}
func printFloat(w io.Writer, val float64, precision int, floatType string) {
w.Write([]byte(fmt.Sprintf("%s(%s)", floatType, strconv.FormatFloat(val, 'g', -1, precision))))
mustWrite(w, []byte(fmt.Sprintf("%s(%s)", floatType, strconv.FormatFloat(val, 'g', -1, precision))))
}
func printComplex(w io.Writer, c complex128, floatPrecision int) {
w.Write([]byte("complex"))
w.Write([]byte(fmt.Sprintf("%d", floatPrecision*2)))
mustWrite(w, []byte("complex"))
mustWrite(w, []byte(fmt.Sprintf("%d", floatPrecision*2)))
r := real(c)
w.Write([]byte("("))
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
mustWrite(w, []byte("("))
mustWrite(w, []byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
i := imag(c)
if i >= 0 {
w.Write([]byte("+"))
mustWrite(w, []byte("+"))
}
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
w.Write([]byte("i)"))
mustWrite(w, []byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
mustWrite(w, []byte("i)"))
}
func printNil(w io.Writer) {
w.Write([]byte("nil"))
mustWrite(w, []byte("nil"))
}
// deInterface returns values inside of non-nil interfaces when possible.

View File

@ -412,16 +412,13 @@ func (l *lexer) lexWhitespace() (int, int) {
switch r {
case '\r':
// Ignore.
break
case '\n':
indent = 0
newLines++
break
case ' ':
indent++
break
// This only works for \t at the beginning of lines, but we strip it everywhere else
// anyway. The only case where this will cause a problem is spaces followed by \t
@ -429,7 +426,6 @@ func (l *lexer) lexWhitespace() (int, int) {
// is enabled it will be fixed later.
case '\t':
indent += 8
break
}
}
l.backup()
@ -489,7 +485,7 @@ func (l *lexer) lexNumber() error {
state := numBegin
outerLoop:
for true {
for {
r := l.next()
switch state {
case numBegin:
@ -654,6 +650,7 @@ func (l *lexer) lexSymbol() error {
margin := l.pos.byteNo - l.pos.lineStart
commentStartLoc := l.tokenStartLoc
//nolint:ineffassign,staticcheck
r := l.next() // consume the initial '*'
for r = l.next(); r != '*' || l.peek() != '/'; r = l.next() {
if r == lexEOF {
@ -687,9 +684,9 @@ func (l *lexer) lexSymbol() error {
}
}
if allStar {
for _, l := range lines {
if l[0] == '*' {
l = " " + l
for i := range lines {
if lines[i][0] == '*' {
lines[i] = " " + lines[i]
}
}
}
@ -813,7 +810,7 @@ func Lex(fn string, input string) (Tokens, error) {
l := makeLexer(fn, input)
var err error
for true {
for {
newLines, indent := l.lexWhitespace()
// If it's the end of the file, discard final whitespace.
if l.peek() == lexEOF {
@ -855,7 +852,8 @@ func Lex(fn string, input string) (Tokens, error) {
return nil, err
}
// String literals
// String literals
case '"':
stringStartLoc := l.prevLocation()
for r = l.next(); ; r = l.next() {
@ -869,6 +867,7 @@ func Lex(fn string, input string) (Tokens, error) {
break
}
if r == '\\' && l.peek() != lexEOF {
//nolint:ineffassign,staticcheck
r = l.next()
}
}
@ -885,6 +884,7 @@ func Lex(fn string, input string) (Tokens, error) {
break
}
if r == '\\' && l.peek() != lexEOF {
//nolint:ineffassign,staticcheck
r = l.next()
}
}

View File

@ -21,127 +21,10 @@ import (
"github.com/google/go-jsonnet/ast"
)
type lexTest struct {
name string
input string
tokens Tokens
errString string
}
var (
tEOF = token{kind: tokenEndOfFile}
)
var lexTests = []lexTest{
{
"block string spaces",
`|||
test
more
|||
foo
|||`,
Tokens{
{
kind: tokenStringBlock,
data: "test\n more\n|||\n foo\n",
stringBlockIndent: " ",
stringBlockTermIndent: "",
},
},
"",
},
{
"block string tabs",
`|||
test
more
|||
foo
|||`,
Tokens{
{
kind: tokenStringBlock,
data: "test\n more\n|||\n foo\n",
stringBlockIndent: "\t",
stringBlockTermIndent: "",
},
},
"",
},
{
"block string mixed",
`|||
test
more
|||
foo
|||`,
Tokens{
{
kind: tokenStringBlock,
data: "test\n more\n|||\n foo\n",
stringBlockIndent: "\t \t",
stringBlockTermIndent: "",
},
},
"",
},
{
"block string blanks",
`|||
test
more
|||
foo
|||`,
Tokens{
{
kind: tokenStringBlock,
data: "\ntest\n\n\n more\n|||\n foo\n",
stringBlockIndent: " ",
stringBlockTermIndent: "",
},
},
"",
},
{
"block string bad indent",
`|||
test
foo
|||`,
Tokens{},
"block string bad indent:1:1 Text block not terminated with |||",
},
{
"block string eof",
`|||
test`,
Tokens{},
"block string eof:1:1 Unexpected EOF",
},
{
"block string not term",
`|||
test
`,
Tokens{},
"block string not term:1:1 Text block not terminated with |||",
},
{
"block string no ws",
`|||
test
|||`,
Tokens{},
"block string no ws:1:1 Text block's first line must start with whitespace",
},
}
func fodderEqual(f1 ast.Fodder, f2 ast.Fodder) bool {
if len(f1) != len(f2) {
return false

View File

@ -120,16 +120,6 @@ func (p *parser) doublePeek() *token {
return &p.t[p.currT+1]
}
// in some cases it's convenient to parse something as an expression, and later
// decide that it should be just an identifer
func astVarToIdentifier(node ast.Node) (ast.Fodder, *ast.Identifier, bool) {
v, ok := node.(*ast.Var)
if ok {
return v.NodeBase.Fodder, &v.Id, true
}
return nil, nil, false
}
// parseArgument parses either <f1> id <f2> = expr or just expr.
// It returns either (<f1>, id, <f2>, expr) or (nil, nil, nil, expr)
// respectively.

View File

@ -167,7 +167,10 @@ func desugarFields(nodeBase ast.NodeBase, fields *ast.ObjectFields, objLevel int
return nil, err
}
}
desugarLocalBinds(locals, objLevel+1)
err := desugarLocalBinds(locals, objLevel+1)
if err != nil {
return nil, err
}
for i := range desugaredFields {
field := &(desugaredFields[i])
if field.Name != nil {

View File

@ -205,14 +205,6 @@ func (s *callStack) getCurrentEnv(ast ast.Node) environment {
)
}
func (s *callStack) getTopEnv() environment {
top := s.stack[len(s.stack)-1]
if !top.isCall {
panic("getTopEnv is allowed only for artifical nodes which are called in new environment")
}
return top.env
}
// Build a binding frame containing specified variables.
func (s *callStack) capture(freeVars ast.Identifiers) bindingFrame {
env := make(bindingFrame)
@ -482,7 +474,7 @@ func (i *interpreter) evaluate(a ast.Node, tc tailCallStatus) (value, error) {
// too large to fit in a double.
num, err := strconv.ParseFloat(node.OriginalString, 64)
if err != nil {
return nil, i.Error(fmt.Sprintf("overflow"), trace)
return nil, i.Error("overflow", trace)
}
return makeValueNumber(num), nil
@ -968,6 +960,7 @@ func (i *interpreter) getNumber(val value, trace traceElement) (*valueNumber, er
}
}
//nolint:unused
func (i *interpreter) evaluateNumber(pv potentialValue, trace traceElement) (*valueNumber, error) {
v, err := i.evaluatePV(pv, trace)
if err != nil {
@ -998,6 +991,7 @@ func (i *interpreter) evaluateInt(pv potentialValue, trace traceElement) (int, e
return i.getInt(v, trace)
}
//nolint:unused
func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) {
num, err := i.getNumber(val, trace)
if err != nil {
@ -1010,6 +1004,7 @@ func (i *interpreter) getInt64(val value, trace traceElement) (int64, error) {
return intNum, nil
}
//nolint:unused
func (i *interpreter) evaluateInt64(pv potentialValue, trace traceElement) (int64, error) {
v, err := i.evaluatePV(pv, trace)
if err != nil {
@ -1027,6 +1022,7 @@ func (i *interpreter) getString(val value, trace traceElement) (valueString, err
}
}
//nolint:unused
func (i *interpreter) evaluateString(pv potentialValue, trace traceElement) (valueString, error) {
v, err := i.evaluatePV(pv, trace)
if err != nil {
@ -1044,6 +1040,7 @@ func (i *interpreter) getBoolean(val value, trace traceElement) (*valueBoolean,
}
}
//nolint:unused
func (i *interpreter) evaluateBoolean(pv potentialValue, trace traceElement) (*valueBoolean, error) {
v, err := i.evaluatePV(pv, trace)
if err != nil {
@ -1061,6 +1058,7 @@ func (i *interpreter) getArray(val value, trace traceElement) (*valueArray, erro
}
}
//nolint:unused
func (i *interpreter) evaluateArray(pv potentialValue, trace traceElement) (*valueArray, error) {
v, err := i.evaluatePV(pv, trace)
if err != nil {
@ -1078,6 +1076,7 @@ func (i *interpreter) getFunction(val value, trace traceElement) (*valueFunction
}
}
//nolint:unused
func (i *interpreter) evaluateFunction(pv potentialValue, trace traceElement) (*valueFunction, error) {
v, err := i.evaluatePV(pv, trace)
if err != nil {

View File

@ -39,7 +39,10 @@ func main() {
if err != nil {
die(err)
}
inputFile.Close()
err = inputFile.Close()
if err != nil {
die(err)
}
node, err := jsonnet.SnippetToAST(p, string(data))
if err != nil {
die(err)

View File

@ -17,7 +17,10 @@ type ErrorWriter struct {
func (e *ErrorWriter) writeError(err errors.StaticError) {
e.ErrorsFound = true
e.Writer.Write([]byte(err.Error() + "\n"))
_, writeErr := e.Writer.Write([]byte(err.Error() + "\n"))
if writeErr != nil {
panic(writeErr)
}
}
type variable struct {

View File

@ -398,7 +398,7 @@ func TestEval(t *testing.T) {
}
}
func withinWorkingDirectory(t *testing.T, dir string) func() error {
func withinWorkingDirectory(t *testing.T, dir string) func() {
t.Helper()
cwd, err := os.Getwd()
if err != nil {
@ -407,8 +407,11 @@ func withinWorkingDirectory(t *testing.T, dir string) func() error {
if err := os.Chdir(dir); err != nil {
t.Fatal(err)
}
return func() error {
return os.Chdir(cwd)
return func() {
err := os.Chdir(cwd)
if err != nil {
t.Fatal(err)
}
}
}
@ -426,7 +429,12 @@ func TestEvalUnusualFilenames(t *testing.T) {
if dir, err = ioutil.TempDir("", "jsonnet"); err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
defer func() {
err := os.RemoveAll(dir)
if err != nil {
panic(err)
}
}()
}
copySmallFile := func(t *testing.T, dst, src string) {

View File

@ -1,10 +1,10 @@
RUNTIME ERROR: foo
RUNTIME ERROR: Unexpected type array
-------------------------------------------------
testdata/std.sort4:1:15-26 thunk from <thunk from <thunk from <$>>>
testdata/std.sort4:1:1-29 builtin function <sort>
std.sort([1, [error "foo"]])
-------------------------------------------------
During manifestation
During evaluation

View File

@ -36,19 +36,9 @@ func (rv *readyValue) evaluate(i *interpreter, trace traceElement, sb selfBindin
return rv.content, nil
}
func (rv *readyValue) aPotentialValue() {}
// potentialValues
// -------------------------------------
// evaluable is something that can be evaluated and the result is always the same
// It may require computation every time evaluation is requested (in contrast with
// potentialValue which guarantees that computation happens at most once).
type evaluable interface {
// fromWhere keeps the information from where the evaluation was requested.
getValue(i *interpreter, fromWhere traceElement) (value, error)
}
// cachedThunk is a wrapper that caches the value of a potentialValue after
// the first evaluation.
// Note: All potentialValues are required to provide the same value every time,
@ -110,8 +100,7 @@ type bindingsUnboundField struct {
}
func (f *bindingsUnboundField) evaluate(i *interpreter, trace traceElement, sb selfBinding, origBindings bindingFrame, fieldName string) (value, error) {
var upValues bindingFrame
upValues = make(bindingFrame)
upValues := make(bindingFrame)
for variable, pvalue := range origBindings {
upValues[variable] = pvalue
}
@ -164,7 +153,7 @@ func forceThunks(i *interpreter, trace traceElement, args *bindingFrame) error {
func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace traceElement) (value, error) {
argThunks := make(bindingFrame)
parameters := closure.Parameters()
parameters := closure.parameters()
for i, arg := range arguments.positional {
argThunks[parameters[i].name] = arg
}
@ -199,7 +188,7 @@ func (closure *closure) evalCall(arguments callArguments, i *interpreter, trace
return i.EvalInCleanEnv(trace, &calledEnvironment, closure.function.Body, arguments.tailstrict)
}
func (closure *closure) Parameters() []namedParameter {
func (closure *closure) parameters() []namedParameter {
return closure.params
}
@ -232,7 +221,7 @@ type NativeFunction struct {
// evalCall evaluates a call to a NativeFunction and returns the result.
func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter, trace traceElement) (value, error) {
flatArgs := flattenArgs(arguments, native.Parameters(), []value{})
flatArgs := flattenArgs(arguments, native.parameters(), []value{})
nativeArgs := make([]interface{}, 0, len(flatArgs))
for _, arg := range flatArgs {
v, err := i.evaluatePV(arg, trace)
@ -253,20 +242,10 @@ func (native *NativeFunction) evalCall(arguments callArguments, i *interpreter,
}
// Parameters returns a NativeFunction's parameters.
func (native *NativeFunction) Parameters() []namedParameter {
func (native *NativeFunction) parameters() []namedParameter {
ret := make([]namedParameter, len(native.Params))
for i := range ret {
ret[i].name = native.Params[i]
}
return ret
}
// -------------------------------------
type defaultArgument struct {
body ast.Node
}
func (da *defaultArgument) inEnv(env *environment) potentialValue {
return &cachedThunk{env: env, body: da.body}
}

View File

@ -313,9 +313,7 @@ func makeValueArray(elements []*cachedThunk) *valueArray {
arrayElems = elements
} else {
arrayElems = make([]*cachedThunk, len(elements))
for i := range elements {
arrayElems[i] = elements[i]
}
copy(arrayElems, elements)
}
return &valueArray{
elements: arrayElems,
@ -324,12 +322,8 @@ func makeValueArray(elements []*cachedThunk) *valueArray {
func concatArrays(a, b *valueArray) *valueArray {
result := make([]*cachedThunk, 0, len(a.elements)+len(b.elements))
for _, r := range a.elements {
result = append(result, r)
}
for _, r := range b.elements {
result = append(result, r)
}
result = append(result, a.elements...)
result = append(result, b.elements...)
return &valueArray{elements: result}
}
@ -348,19 +342,19 @@ type valueFunction struct {
// TODO(sbarzowski) better name?
type evalCallable interface {
evalCall(args callArguments, i *interpreter, trace traceElement) (value, error)
Parameters() []namedParameter
parameters() []namedParameter
}
func (f *valueFunction) call(i *interpreter, trace traceElement, args callArguments) (value, error) {
err := checkArguments(i, trace, args, f.Parameters())
err := checkArguments(i, trace, args, f.parameters())
if err != nil {
return nil, err
}
return f.ec.evalCall(args, i, trace)
}
func (f *valueFunction) Parameters() []namedParameter {
return f.ec.Parameters()
func (f *valueFunction) parameters() []namedParameter {
return f.ec.parameters()
}
func checkArguments(i *interpreter, trace traceElement, args callArguments, params []namedParameter) error {
@ -406,22 +400,11 @@ func (f *valueFunction) getType() *valueType {
return functionType
}
// parameters represents required position and optional named parameters for a
// function definition.
type parameters struct {
required ast.Identifiers
optional []namedParameter
}
type namedParameter struct {
name ast.Identifier
defaultArg ast.Node
}
type potentialValueInEnv interface {
inEnv(env *environment) *cachedThunk
}
type callArguments struct {
positional []*cachedThunk
named []namedCallArgument