Fix stylecheck warnings

master
Vladimir Hodakov 2019-10-19 01:41:57 +04:00
parent ca047193ee
commit 3697f12c5c
Signed by: Vladimir Hodakov
GPG Key ID: 673980B6882F82C6
10 changed files with 101 additions and 78 deletions

View File

@ -6,6 +6,7 @@ linters:
- gochecknoglobals
- gocritic
- funlen
- godox
linters-settings:
lll:
line-length: 180
@ -21,4 +22,6 @@ issues:
- lll
- goconst
- unparam
- unused
- unused
max-issues-per-linter: 0
max-same-issues: 0

14
eval.go
View File

@ -259,17 +259,17 @@ func pathEndValue(q *query, e *Eval, i *Item) queryStateFn {
switch q.firstType {
case jsonBraceLeft:
r.Type = JsonObject
r.Type = JSONObject
case jsonString:
r.Type = JsonString
r.Type = JSONString
case jsonBracketLeft:
r.Type = JsonArray
r.Type = JSONArray
case jsonNull:
r.Type = JsonNull
r.Type = JSONNull
case jsonBool:
r.Type = JsonBool
r.Type = JSONBool
case jsonNumber:
r.Type = JsonNumber
r.Type = JSONNumber
default:
r.Type = -1
}
@ -297,7 +297,7 @@ func (b *exprBucket) evaluate() (bool, error) {
for _, q := range b.queries {
result := q.resultQueue.Pop()
if result != nil {
t, err := getJsonTokenType(result.Value)
t, err := getJSONTokenType(result.Value)
if err != nil {
return false, err
}

View File

@ -15,32 +15,32 @@ type test struct {
}
var tests = []test{
{`key selection`, `{"aKey":32}`, `$.aKey+`, []Result{newResult(`32`, JsonNumber, `aKey`)}},
{`nested key selection`, `{"aKey":{"bKey":32}}`, `$.aKey+`, []Result{newResult(`{"bKey":32}`, JsonObject, `aKey`)}},
{`empty array`, `{"aKey":[]}`, `$.aKey+`, []Result{newResult(`[]`, JsonArray, `aKey`)}},
{`multiple same-level keys, weird spacing`, `{ "aKey" : true , "bKey": [ 1 , 2 ], "cKey" : true } `, `$.bKey+`, []Result{newResult(`[1,2]`, JsonArray, `bKey`)}},
{`key selection`, `{"aKey":32}`, `$.aKey+`, []Result{newResult(`32`, JSONNumber, `aKey`)}},
{`nested key selection`, `{"aKey":{"bKey":32}}`, `$.aKey+`, []Result{newResult(`{"bKey":32}`, JSONObject, `aKey`)}},
{`empty array`, `{"aKey":[]}`, `$.aKey+`, []Result{newResult(`[]`, JSONArray, `aKey`)}},
{`multiple same-level keys, weird spacing`, `{ "aKey" : true , "bKey": [ 1 , 2 ], "cKey" : true } `, `$.bKey+`, []Result{newResult(`[1,2]`, JSONArray, `bKey`)}},
{`array index selection`, `{"aKey":[123,456]}`, `$.aKey[1]+`, []Result{newResult(`456`, JsonNumber, `aKey`, 1)}},
{`array wild index selection`, `{"aKey":[123,456]}`, `$.aKey[*]+`, []Result{newResult(`123`, JsonNumber, `aKey`, 0), newResult(`456`, JsonNumber, `aKey`, 1)}},
{`array range index selection`, `{"aKey":[11,22,33,44]}`, `$.aKey[1:3]+`, []Result{newResult(`22`, JsonNumber, `aKey`, 1), newResult(`33`, JsonNumber, `aKey`, 2)}},
{`array index selection`, `{"aKey":[123,456]}`, `$.aKey[1]+`, []Result{newResult(`456`, JSONNumber, `aKey`, 1)}},
{`array wild index selection`, `{"aKey":[123,456]}`, `$.aKey[*]+`, []Result{newResult(`123`, JSONNumber, `aKey`, 0), newResult(`456`, JSONNumber, `aKey`, 1)}},
{`array range index selection`, `{"aKey":[11,22,33,44]}`, `$.aKey[1:3]+`, []Result{newResult(`22`, JSONNumber, `aKey`, 1), newResult(`33`, JSONNumber, `aKey`, 2)}},
{`array range (no index) selection`, `{"aKey":[11,22,33,44]}`, `$.aKey[1:1]+`, []Result{}},
{`array range (no upper bound) selection`, `{"aKey":[11,22,33]}`, `$.aKey[1:]+`, []Result{newResult(`22`, JsonNumber, `aKey`, 1), newResult(`33`, JsonNumber, `aKey`, 2)}},
{`array range (no upper bound) selection`, `{"aKey":[11,22,33]}`, `$.aKey[1:]+`, []Result{newResult(`22`, JSONNumber, `aKey`, 1), newResult(`33`, JSONNumber, `aKey`, 2)}},
{`empty array - try selection`, `{"aKey":[]}`, `$.aKey[1]+`, []Result{}},
{`null selection`, `{"aKey":[null]}`, `$.aKey[0]+`, []Result{newResult(`null`, JsonNull, `aKey`, 0)}},
{`empty object`, `{"aKey":{}}`, `$.aKey+`, []Result{newResult(`{}`, JsonObject, `aKey`)}},
{`object w/ height=2`, `{"aKey":{"bKey":32}}`, `$.aKey.bKey+`, []Result{newResult(`32`, JsonNumber, `aKey`, `bKey`)}},
{`array of multiple types`, `{"aKey":[1,{"s":true},"asdf"]}`, `$.aKey[1]+`, []Result{newResult(`{"s":true}`, JsonObject, `aKey`, 1)}},
{`nested array selection`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey+`, []Result{newResult(`[123,456]`, JsonArray, `aKey`, `bKey`)}},
{`nested array`, `[[[[[]], [true, false, []]]]]`, `$[0][0][1][2]+`, []Result{newResult(`[]`, JsonArray, 0, 0, 1, 2)}},
{`index of array selection`, `{"aKey":{"bKey":[123, 456, 789]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JsonNumber, `aKey`, `bKey`, 1)}},
{`index of array selection (more than one)`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JsonNumber, `aKey`, `bKey`, 1)}},
{`multi-level object/array`, `{"1Key":{"aKey": null, "bKey":{"trash":[1,2]}, "cKey":[123,456] }, "2Key":false}`, `$.1Key.bKey.trash[0]+`, []Result{newResult(`1`, JsonNumber, `1Key`, `bKey`, `trash`, 0)}},
{`multi-level array`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*].michael[1]+`, []Result{newResult(`6`, JsonNumber, `aKey`, 3, `michael`, 1)}},
{`multi-level array 2`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*][1]+`, []Result{newResult(`"3"`, JsonString, `aKey`, 4, 1)}},
{`null selection`, `{"aKey":[null]}`, `$.aKey[0]+`, []Result{newResult(`null`, JSONNull, `aKey`, 0)}},
{`empty object`, `{"aKey":{}}`, `$.aKey+`, []Result{newResult(`{}`, JSONObject, `aKey`)}},
{`object w/ height=2`, `{"aKey":{"bKey":32}}`, `$.aKey.bKey+`, []Result{newResult(`32`, JSONNumber, `aKey`, `bKey`)}},
{`array of multiple types`, `{"aKey":[1,{"s":true},"asdf"]}`, `$.aKey[1]+`, []Result{newResult(`{"s":true}`, JSONObject, `aKey`, 1)}},
{`nested array selection`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey+`, []Result{newResult(`[123,456]`, JSONArray, `aKey`, `bKey`)}},
{`nested array`, `[[[[[]], [true, false, []]]]]`, `$[0][0][1][2]+`, []Result{newResult(`[]`, JSONArray, 0, 0, 1, 2)}},
{`index of array selection`, `{"aKey":{"bKey":[123, 456, 789]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JSONNumber, `aKey`, `bKey`, 1)}},
{`index of array selection (more than one)`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JSONNumber, `aKey`, `bKey`, 1)}},
{`multi-level object/array`, `{"1Key":{"aKey": null, "bKey":{"trash":[1,2]}, "cKey":[123,456] }, "2Key":false}`, `$.1Key.bKey.trash[0]+`, []Result{newResult(`1`, JSONNumber, `1Key`, `bKey`, `trash`, 0)}},
{`multi-level array`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*].michael[1]+`, []Result{newResult(`6`, JSONNumber, `aKey`, 3, `michael`, 1)}},
{`multi-level array 2`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*][1]+`, []Result{newResult(`"3"`, JSONString, `aKey`, 4, 1)}},
{`evaluation literal equality`, `{"items":[ {"name":"alpha", "value":11}]}`, `$.items[*]?("bravo" == "bravo").value+`, []Result{newResult(`11`, JsonNumber, `items`, 0, `value`)}},
{`evaluation based on string equal to path value`, `{"items":[ {"name":"alpha", "value":11}, {"name":"bravo", "value":22}, {"name":"charlie", "value":33} ]}`, `$.items[*]?(@.name == "bravo").value+`, []Result{newResult(`22`, JsonNumber, `items`, 1, `value`)}},
{`evaluation literal equality`, `{"items":[ {"name":"alpha", "value":11}]}`, `$.items[*]?("bravo" == "bravo").value+`, []Result{newResult(`11`, JSONNumber, `items`, 0, `value`)}},
{`evaluation based on string equal to path value`, `{"items":[ {"name":"alpha", "value":11}, {"name":"bravo", "value":22}, {"name":"charlie", "value":33} ]}`, `$.items[*]?(@.name == "bravo").value+`, []Result{newResult(`22`, JSONNumber, `items`, 1, `value`)}},
}
func TestPathQuery(t *testing.T) {
@ -52,14 +52,16 @@ func TestPathQuery(t *testing.T) {
eval, err := EvalPathsInBytes([]byte(t.json), paths)
if as.NoError(err, "Testing: %s", t.name) {
res := toResultArray(eval)
if as.NoError(eval.Error) {
as.EqualValues(t.expected, res, "Testing of %q", t.name)
}
}
eval_reader, err := EvalPathsInReader(strings.NewReader(t.json), paths)
evalReader, err := EvalPathsInReader(strings.NewReader(t.json), paths)
if as.NoError(err, "Testing: %s", t.name) {
res := toResultArray(eval_reader)
res := toResultArray(evalReader)
if as.NoError(eval.Error) {
as.EqualValues(t.expected, res, "Testing of %q", t.name)
}

View File

@ -64,11 +64,11 @@ func infixToPostFix(items []Item) (out []Item, err error) {
found := false
for {
// pop item ("(" or operator) from stack
op_interface, ok := stack.pop()
opInterface, ok := stack.pop()
if !ok {
return nil, errors.New(exprErrorMismatchedParens)
}
op := op_interface.(Item)
op := opInterface.(Item)
if op.typ == exprParenLeft {
found = true
break // discard "("
@ -83,8 +83,8 @@ func infixToPostFix(items []Item) (out []Item, err error) {
// token is an operator
for stack.len() > 0 {
// consider top item on stack
op_int, _ := stack.peek()
op := op_int.(Item)
opInt, _ := stack.peek()
op := opInt.(Item)
if o2, isOp := opa[op.typ]; !isOp || o1.prec > o2.prec ||
o1.prec == o2.prec && o1.rAssoc {
break
@ -102,8 +102,8 @@ func infixToPostFix(items []Item) (out []Item, err error) {
}
// drain stack to result
for stack.len() > 0 {
op_int, _ := stack.pop()
op := op_int.(Item)
opInt, _ := stack.pop()
op := opInt.(Item)
if op.typ == exprParenLeft {
return nil, errors.New(exprErrorMismatchedParens)
}
@ -308,7 +308,7 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
}
if a == 0.0 {
return false, errors.New("Cannot divide by zero")
return false, errors.New("cannot divide by zero")
}
s.push(b / a)
case exprOpStar:
@ -340,15 +340,16 @@ func evaluatePostFix(postFixItems []Item, pathValues map[string]Item) (interface
s.push(!a)
// Other
default:
return false, fmt.Errorf("Token not supported in evaluator: %v", exprTokenNames[item.typ])
return false, fmt.Errorf("token not supported in evaluator: %v", exprTokenNames[item.typ])
}
}
if s.len() != 1 {
return false, fmt.Errorf(exprErrorBadExpression)
}
end_int, _ := s.pop()
return end_int, nil
endInt, _ := s.pop()
return endInt, nil
}
func take1Bool(s *stack, op int) (bool, error) {

View File

@ -38,12 +38,14 @@ var jsonTokenNames = map[int]string{
jsonBool: "BOOL",
}
var JSON = lexJsonRoot
var JSON = lexJSONRoot
func lexJsonRoot(l lexer, state *intStack) stateFn {
func lexJSONRoot(l lexer, state *intStack) stateFn {
ignoreSpaceRun(l)
cur := l.peek()
var next stateFn
switch cur {
case '{':
next = stateJSONObjectOpen

View File

@ -33,7 +33,7 @@ func TestValidJson(t *testing.T) {
}
}
var errorJsonTests = []lexTest{
var errorJSONTests = []lexTest{
{"Missing end brace", `{`, []int{jsonBraceLeft, jsonError}},
{"Missing start brace", `}`, []int{jsonError}},
{"Missing key start quote", `{key":true}`, []int{jsonBraceLeft, jsonError}},
@ -50,7 +50,7 @@ var errorJsonTests = []lexTest{
func TestMalformedJson(t *testing.T) {
as := assert.New(t)
for _, test := range errorJsonTests {
for _, test := range errorJSONTests {
lexer := NewSliceLexer([]byte(test.input), JSON)
types := itemsToTypes(readerToArray(lexer))

View File

@ -34,14 +34,14 @@ func (l *SliceLexer) takeString() error {
inputLen := len(l.input)
if int(curPos) >= inputLen {
return errors.New("End of file where string expected")
return errors.New("end of file where string expected")
}
cur := int(l.input[curPos])
curPos++
if cur != '"' {
l.pos = curPos
return fmt.Errorf("Expected \" as start of string instead of %#U", cur)
return fmt.Errorf("expected \" as start of string instead of %#U", cur)
}
var previous int
@ -49,7 +49,7 @@ looper:
for {
if int(curPos) >= inputLen {
l.pos = curPos
return errors.New("End of file where string expected")
return errors.New("end of file where string expected")
}
cur := int(l.input[curPos])
curPos++

17
misc.go
View File

@ -16,13 +16,13 @@ func takeExponent(l lexer) error {
case '+', '-':
// Check digit immediately follows sign
if d := l.peek(); !(d >= '0' && d <= '9') {
return fmt.Errorf("Expected digit after numeric sign instead of %#U", d)
return fmt.Errorf("expected digit after numeric sign instead of %#U", d)
}
takeDigits(l)
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
takeDigits(l)
default:
return fmt.Errorf("Expected digit after 'e' instead of %#U", r)
return fmt.Errorf("expected digit after 'e' instead of %#U", r)
}
return nil
}
@ -33,13 +33,13 @@ func takeJSONNumeric(l lexer) error {
case '-':
// Check digit immediately follows sign
if d := l.peek(); !(d >= '0' && d <= '9') {
return fmt.Errorf("Expected digit after dash instead of %#U", d)
return fmt.Errorf("expected digit after dash instead of %#U", d)
}
takeDigits(l)
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
takeDigits(l)
default:
return fmt.Errorf("Expected digit or dash instead of %#U", cur)
return fmt.Errorf("expected digit or dash instead of %#U", cur)
}
// fraction or exponent
@ -49,7 +49,7 @@ func takeJSONNumeric(l lexer) error {
l.take()
// Check digit immediately follows period
if d := l.peek(); !(d >= '0' && d <= '9') {
return fmt.Errorf("Expected digit after '.' instead of %#U", d)
return fmt.Errorf("expected digit after '.' instead of %#U", d)
}
takeDigits(l)
if err := takeExponent(l); err != nil {
@ -158,10 +158,11 @@ func abs(x int) int {
}
//TODO: Kill the need for this
func getJsonTokenType(val []byte) (int, error) {
func getJSONTokenType(val []byte) (int, error) {
if len(val) == 0 {
return -1, errors.New("No Value")
return -1, errors.New("no value")
}
switch val[0] {
case '{':
return jsonBraceLeft, nil
@ -176,6 +177,6 @@ func getJsonTokenType(val []byte) (int, error) {
case '-', '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return jsonNumber, nil
default:
return -1, errors.New("Unrecognized Json Value")
return -1, errors.New("unrecognized JSON value")
}
}

46
path.go
View File

@ -36,10 +36,13 @@ type operator struct {
// nolint:gocognit
func genIndexKey(tr tokenReader) (*operator, error) {
k := &operator{}
var t *Item
var ok bool
if t, ok = tr.next(); !ok {
return nil, errors.New("Expected number, key, or *, but got none")
return nil, errors.New("expected number, key, or *, but got none")
}
switch t.typ {
@ -47,22 +50,23 @@ func genIndexKey(tr tokenReader) (*operator, error) {
k.typ = opTypeIndexWild
k.indexStart = 0
if t, ok = tr.next(); !ok {
return nil, errors.New("Expected ] after *, but got none")
return nil, errors.New("expected ] after *, but got none")
}
if t.typ != pathBracketRight {
return nil, fmt.Errorf("Expected ] after * instead of %q", t.val)
return nil, fmt.Errorf("expected ] after * instead of %q", t.val)
}
case pathIndex:
v, err := strconv.Atoi(string(t.val))
if err != nil {
return nil, fmt.Errorf("Could not parse %q into int64", t.val)
return nil, fmt.Errorf("could not parse %q into int64", t.val)
}
k.indexStart = v
k.indexEnd = v
k.hasIndexEnd = true
if t, ok = tr.next(); !ok {
return nil, errors.New("Expected number or *, but got none")
return nil, errors.New("expected number or *, but got none")
}
switch t.typ {
@ -77,6 +81,7 @@ func genIndexKey(tr tokenReader) (*operator, error) {
if err != nil {
return nil, fmt.Errorf("could not parse %q into int64", t.val)
}
k.indexEnd = v - 1
k.hasIndexEnd = true
@ -113,6 +118,7 @@ func genIndexKey(tr tokenReader) (*operator, error) {
func parsePath(pathString string) (*Path, error) {
lexer := NewSliceLexer([]byte(pathString), PATH)
p, err := tokensToOperators(lexer)
if err != nil {
return nil, err
@ -124,9 +130,11 @@ func parsePath(pathString string) (*Path, error) {
for _, op := range p.operators {
if len(op.whereClauseBytes) > 0 {
var err error
trimmed := op.whereClauseBytes[1 : len(op.whereClauseBytes)-1]
whereLexer := NewSliceLexer(trimmed, EXPRESSION)
items := readerToArray(whereLexer)
if errItem, found := findErrors(items); found {
return nil, errors.New(string(errItem.val))
}
@ -136,6 +144,7 @@ func parsePath(pathString string) (*Path, error) {
if err != nil {
return nil, err
}
op.dependentPaths = make([]*Path, 0)
// parse all paths in expression
for _, item := range op.whereClause {
@ -144,11 +153,13 @@ func parsePath(pathString string) (*Path, error) {
if err != nil {
return nil, err
}
op.dependentPaths = append(op.dependentPaths, p)
}
}
}
}
return p, nil
}
@ -158,27 +169,28 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
captureEndValue: false,
operators: make([]*operator, 0),
}
for {
p, ok := tr.next()
if !ok {
break
}
switch p.typ {
case pathRoot:
if len(q.operators) != 0 {
return nil, errors.New("Unexpected root node after start")
return nil, errors.New("unexpected root node after start")
}
continue
continue
case pathCurrent:
if len(q.operators) != 0 {
return nil, errors.New("Unexpected current node after start")
return nil, errors.New("unexpected current node after start")
}
continue
continue
case pathPeriod:
continue
case pathBracketLeft:
k, err := genIndexKey(tr)
if err != nil {
@ -190,11 +202,13 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
keyName := p.val
if len(p.val) == 0 {
return nil, fmt.Errorf("Key length is zero at %d", p.pos)
return nil, fmt.Errorf("key length is zero at %d", p.pos)
}
if p.val[0] == '"' && p.val[len(p.val)-1] == '"' {
keyName = p.val[1 : len(p.val)-1]
}
q.operators = append(
q.operators,
&operator{
@ -204,28 +218,28 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
},
},
)
case pathWildcard:
q.operators = append(q.operators, &operator{typ: opTypeNameWild})
case pathValue:
q.captureEndValue = true
case pathWhere:
case pathExpression:
if len(q.operators) == 0 {
return nil, errors.New("Cannot add where clause on last key")
return nil, errors.New("cannot add where clause on last key")
}
last := q.operators[len(q.operators)-1]
if last.whereClauseBytes != nil {
return nil, errors.New("Expression on last key already set")
return nil, errors.New("expression on last key already set")
}
last.whereClauseBytes = p.val
last.whereClauseBytes = p.val
case pathError:
return q, errors.New(string(p.val))
}
}
return q, nil
}

View File

@ -6,12 +6,12 @@ import (
)
const (
JsonObject = iota
JsonArray
JsonString
JsonNumber
JsonNull
JsonBool
JSONObject = iota
JSONArray
JSONString
JSONNumber
JSONNull
JSONBool
)
type Result struct {