Add basic linter config, decrease moduled Go version

master 1.0.0
Vladimir Hodakov 2019-10-19 00:39:21 +04:00
parent 6adf5bc3b9
commit f7b8e36f03
Signed by: Vladimir Hodakov
GPG Key ID: 673980B6882F82C6
7 changed files with 108 additions and 74 deletions

24
.golangci.yaml Normal file
View File

@ -0,0 +1,24 @@
run:
deadline: 2m
linters:
enable-all: true
disable:
- gochecknoglobals
- gocritic
- funlen
linters-settings:
lll:
line-length: 180
issues:
exclude-rules:
- path: _test\.go
linters:
- dupl
- errcheck
- gocritic
- gocyclo
- gosec
- lll
- goconst
- unparam
- unused

View File

@ -15,32 +15,32 @@ type test struct {
}
var tests = []test{
test{`key selection`, `{"aKey":32}`, `$.aKey+`, []Result{newResult(`32`, JsonNumber, `aKey`)}},
test{`nested key selection`, `{"aKey":{"bKey":32}}`, `$.aKey+`, []Result{newResult(`{"bKey":32}`, JsonObject, `aKey`)}},
test{`empty array`, `{"aKey":[]}`, `$.aKey+`, []Result{newResult(`[]`, JsonArray, `aKey`)}},
test{`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`)}},
test{`array index selection`, `{"aKey":[123,456]}`, `$.aKey[1]+`, []Result{newResult(`456`, JsonNumber, `aKey`, 1)}},
test{`array wild index selection`, `{"aKey":[123,456]}`, `$.aKey[*]+`, []Result{newResult(`123`, JsonNumber, `aKey`, 0), newResult(`456`, JsonNumber, `aKey`, 1)}},
test{`array range index selection`, `{"aKey":[11,22,33,44]}`, `$.aKey[1:3]+`, []Result{newResult(`22`, JsonNumber, `aKey`, 1), newResult(`33`, JsonNumber, `aKey`, 2)}},
test{`array range (no index) selection`, `{"aKey":[11,22,33,44]}`, `$.aKey[1:1]+`, []Result{}},
test{`array range (no upper bound) selection`, `{"aKey":[11,22,33]}`, `$.aKey[1:]+`, []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)}},
test{`empty array - try selection`, `{"aKey":[]}`, `$.aKey[1]+`, []Result{}},
test{`null selection`, `{"aKey":[null]}`, `$.aKey[0]+`, []Result{newResult(`null`, JsonNull, `aKey`, 0)}},
test{`empty object`, `{"aKey":{}}`, `$.aKey+`, []Result{newResult(`{}`, JsonObject, `aKey`)}},
test{`object w/ height=2`, `{"aKey":{"bKey":32}}`, `$.aKey.bKey+`, []Result{newResult(`32`, JsonNumber, `aKey`, `bKey`)}},
test{`array of multiple types`, `{"aKey":[1,{"s":true},"asdf"]}`, `$.aKey[1]+`, []Result{newResult(`{"s":true}`, JsonObject, `aKey`, 1)}},
test{`nested array selection`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey+`, []Result{newResult(`[123,456]`, JsonArray, `aKey`, `bKey`)}},
test{`nested array`, `[[[[[]], [true, false, []]]]]`, `$[0][0][1][2]+`, []Result{newResult(`[]`, JsonArray, 0, 0, 1, 2)}},
test{`index of array selection`, `{"aKey":{"bKey":[123, 456, 789]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JsonNumber, `aKey`, `bKey`, 1)}},
test{`index of array selection (more than one)`, `{"aKey":{"bKey":[123,456]}}`, `$.aKey.bKey[1]+`, []Result{newResult(`456`, JsonNumber, `aKey`, `bKey`, 1)}},
test{`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)}},
test{`multi-level array`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*].michael[1]+`, []Result{newResult(`6`, JsonNumber, `aKey`, 3, `michael`, 1)}},
test{`multi-level array 2`, `{"aKey":[true,false,null,{"michael":[5,6,7]}, ["s", "3"] ]}`, `$.*[*][1]+`, []Result{newResult(`"3"`, JsonString, `aKey`, 4, 1)}},
{`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)}},
test{`evaluation literal equality`, `{"items":[ {"name":"alpha", "value":11}]}`, `$.items[*]?("bravo" == "bravo").value+`, []Result{newResult(`11`, JsonNumber, `items`, 0, `value`)}},
test{`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) {

2
go.mod
View File

@ -1,5 +1,5 @@
module source.wtfteam.pro/libraries/jsonpath
go 1.13
go 1.12
require github.com/stretchr/testify v1.4.0

View File

@ -46,16 +46,16 @@ func lexJsonRoot(l lexer, state *intStack) stateFn {
var next stateFn
switch cur {
case '{':
next = stateJsonObjectOpen
next = stateJSONObjectOpen
case '[':
next = stateJsonArrayOpen
next = stateJSONArrayOpen
default:
next = l.errorf("Expected '{' or '[' at root of JSON instead of %#U", cur)
}
return next
}
func stateJsonObjectOpen(l lexer, state *intStack) stateFn {
func stateJSONObjectOpen(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != '{' {
return l.errorf("Expected '{' as start of object instead of %#U", cur)
@ -63,10 +63,10 @@ func stateJsonObjectOpen(l lexer, state *intStack) stateFn {
l.emit(jsonBraceLeft)
state.push(jsonBraceLeft)
return stateJsonObject
return stateJSONObject
}
func stateJsonArrayOpen(l lexer, state *intStack) stateFn {
func stateJSONArrayOpen(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != '[' {
return l.errorf("Expected '[' as start of array instead of %#U", cur)
@ -74,10 +74,10 @@ func stateJsonArrayOpen(l lexer, state *intStack) stateFn {
l.emit(jsonBracketLeft)
state.push(jsonBracketLeft)
return stateJsonArray
return stateJSONArray
}
func stateJsonObject(l lexer, state *intStack) stateFn {
func stateJSONObject(l lexer, state *intStack) stateFn {
var next stateFn
cur := l.peek()
switch cur {
@ -89,16 +89,16 @@ func stateJsonObject(l lexer, state *intStack) stateFn {
l.take()
l.emit(jsonBraceRight)
state.pop()
next = stateJsonAfterValue
next = stateJSONAfterValue
case '"':
next = stateJsonKey
next = stateJSONKey
default:
next = l.errorf("Expected '}' or \" within an object instead of %#U", cur)
}
return next
}
func stateJsonArray(l lexer, state *intStack) stateFn {
func stateJSONArray(l lexer, state *intStack) stateFn {
var next stateFn
cur := l.peek()
switch cur {
@ -110,14 +110,14 @@ func stateJsonArray(l lexer, state *intStack) stateFn {
l.take()
l.emit(jsonBracketRight)
state.pop()
next = stateJsonAfterValue
next = stateJSONAfterValue
default:
next = stateJsonValue
next = stateJSONValue
}
return next
}
func stateJsonAfterValue(l lexer, state *intStack) stateFn {
func stateJSONAfterValue(l lexer, state *intStack) stateFn {
cur := l.take()
top, ok := state.peek()
topVal := noValue
@ -130,9 +130,9 @@ func stateJsonAfterValue(l lexer, state *intStack) stateFn {
l.emit(jsonComma)
switch topVal {
case jsonBraceLeft:
return stateJsonKey
return stateJSONKey
case jsonBracketLeft:
return stateJsonValue
return stateJSONValue
case noValue:
return l.errorf("Found %#U outside of array or object", cur)
default:
@ -143,11 +143,11 @@ func stateJsonAfterValue(l lexer, state *intStack) stateFn {
state.pop()
switch topVal {
case jsonBraceLeft:
return stateJsonAfterValue
return stateJSONAfterValue
case jsonBracketLeft:
return l.errorf("Unexpected %#U in array", cur)
case noValue:
return stateJsonAfterRoot
return stateJSONAfterRoot
}
case ']':
l.emit(jsonBracketRight)
@ -156,9 +156,9 @@ func stateJsonAfterValue(l lexer, state *intStack) stateFn {
case jsonBraceLeft:
return l.errorf("Unexpected %#U in object", cur)
case jsonBracketLeft:
return stateJsonAfterValue
return stateJSONAfterValue
case noValue:
return stateJsonAfterRoot
return stateJSONAfterRoot
}
case eof:
if state.len() == 0 {
@ -173,65 +173,65 @@ func stateJsonAfterValue(l lexer, state *intStack) stateFn {
return nil
}
func stateJsonKey(l lexer, state *intStack) stateFn {
func stateJSONKey(l lexer, state *intStack) stateFn {
if err := l.takeString(); err != nil {
return l.errorf(err.Error())
}
l.emit(jsonKey)
return stateJsonColon
return stateJSONColon
}
func stateJsonColon(l lexer, state *intStack) stateFn {
func stateJSONColon(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != ':' {
return l.errorf("Expected ':' after key string instead of %#U", cur)
}
l.emit(jsonColon)
return stateJsonValue
return stateJSONValue
}
func stateJsonValue(l lexer, state *intStack) stateFn {
func stateJSONValue(l lexer, state *intStack) stateFn {
cur := l.peek()
switch cur {
case eof:
return l.errorf("Unexpected EOF instead of value")
case '"':
return stateJsonString
return stateJSONString
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return stateJsonNumber
return stateJSONNumber
case 't', 'f':
return stateJsonBool
return stateJSONBool
case 'n':
return stateJsonNull
return stateJSONNull
case '{':
return stateJsonObjectOpen
return stateJSONObjectOpen
case '[':
return stateJsonArrayOpen
return stateJSONArrayOpen
default:
return l.errorf("Unexpected character as start of value: %#U", cur)
}
}
func stateJsonString(l lexer, state *intStack) stateFn {
func stateJSONString(l lexer, state *intStack) stateFn {
if err := l.takeString(); err != nil {
return l.errorf(err.Error())
}
l.emit(jsonString)
return stateJsonAfterValue
return stateJSONAfterValue
}
func stateJsonNumber(l lexer, state *intStack) stateFn {
func stateJSONNumber(l lexer, state *intStack) stateFn {
if err := takeJSONNumeric(l); err != nil {
return l.errorf(err.Error())
}
l.emit(jsonNumber)
return stateJsonAfterValue
return stateJSONAfterValue
}
func stateJsonBool(l lexer, state *intStack) stateFn {
func stateJSONBool(l lexer, state *intStack) stateFn {
cur := l.peek()
var match []byte
switch cur {
@ -245,18 +245,18 @@ func stateJsonBool(l lexer, state *intStack) stateFn {
return l.errorf("Could not parse value as 'true' or 'false'")
}
l.emit(jsonBool)
return stateJsonAfterValue
return stateJSONAfterValue
}
func stateJsonNull(l lexer, state *intStack) stateFn {
func stateJSONNull(l lexer, state *intStack) stateFn {
if !takeExactSequence(l, nullBytes) {
return l.errorf("Could not parse value as 'null'")
}
l.emit(jsonNull)
return stateJsonAfterValue
return stateJSONAfterValue
}
func stateJsonAfterRoot(l lexer, state *intStack) stateFn {
func stateJSONAfterRoot(l lexer, state *intStack) stateFn {
cur := l.take()
if cur != eof {
return l.errorf("Expected EOF instead of %#U", cur)

View File

@ -159,7 +159,7 @@ var examples = []string{
}`,
}
func TestMixedCaseJson(t *testing.T) {
func TestMixedCaseJSON(t *testing.T) {
as := assert.New(t)
for _, json := range examples {
lexer := NewSliceLexer([]byte(json), JSON)

14
path.go
View File

@ -93,7 +93,9 @@ func genIndexKey(tr tokenReader) (*operator, error) {
return nil, fmt.Errorf("Unexpected value within brackets after index: %q", t.val)
}
case pathKey:
k.keyStrings = map[string]struct{}{string(t.val[1 : len(t.val)-1]): struct{}{}}
k.keyStrings = map[string]struct{}{
string(t.val[1 : len(t.val)-1]): {},
}
k.typ = opTypeName
if t, ok = tr.next(); !ok || t.typ != pathBracketRight {
@ -185,7 +187,15 @@ func tokensToOperators(tr tokenReader) (*Path, error) {
if p.val[0] == '"' && p.val[len(p.val)-1] == '"' {
keyName = p.val[1 : len(p.val)-1]
}
q.operators = append(q.operators, &operator{typ: opTypeName, keyStrings: map[string]struct{}{string(keyName): struct{}{}}})
q.operators = append(
q.operators,
&operator{
typ: opTypeName,
keyStrings: map[string]struct{}{
string(keyName): {},
},
},
)
case pathWildcard:
q.operators = append(q.operators, &operator{typ: opTypeNameWild})
case pathValue:

View File

@ -13,15 +13,15 @@ type optest struct {
}
var optests = []optest{
optest{"single key (period) ", `$.aKey`, []int{opTypeName}},
optest{"single key (bracket)", `$["aKey"]`, []int{opTypeName}},
optest{"single key (period) ", `$.*`, []int{opTypeNameWild}},
optest{"single index", `$[12]`, []int{opTypeIndex}},
optest{"single key", `$[23:45]`, []int{opTypeIndexRange}},
optest{"single key", `$[*]`, []int{opTypeIndexWild}},
{"single key (period) ", `$.aKey`, []int{opTypeName}},
{"single key (bracket)", `$["aKey"]`, []int{opTypeName}},
{"single key (period) ", `$.*`, []int{opTypeNameWild}},
{"single index", `$[12]`, []int{opTypeIndex}},
{"single key", `$[23:45]`, []int{opTypeIndexRange}},
{"single key", `$[*]`, []int{opTypeIndexWild}},
optest{"double key", `$["aKey"]["bKey"]`, []int{opTypeName, opTypeName}},
optest{"double key", `$["aKey"].bKey`, []int{opTypeName, opTypeName}},
{"double key", `$["aKey"]["bKey"]`, []int{opTypeName, opTypeName}},
{"double key", `$["aKey"].bKey`, []int{opTypeName, opTypeName}},
}
func TestQueryOperators(t *testing.T) {