Skip to content

Commit ac0c679

Browse files
committed
chore(lint): reduced disabled linter, addressed some code quality issues
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
1 parent 8daf0a4 commit ac0c679

File tree

6 files changed

+257
-214
lines changed

6 files changed

+257
-214
lines changed

.golangci.yml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,23 @@ version: "2"
22
linters:
33
default: all
44
disable:
5-
- cyclop
65
- depguard
7-
- errchkjson
86
- errorlint
97
- exhaustruct
10-
- forcetypeassert
118
- funlen
12-
- gochecknoglobals
13-
- gochecknoinits
14-
- gocognit
9+
#- gochecknoglobals
1510
- godot
1611
- godox
1712
- gosmopolitan
18-
- inamedparam
1913
- ireturn
2014
- lll
21-
- musttag
22-
- nestif
2315
- nlreturn
2416
- nonamedreturns
2517
- noinlineerr
2618
- paralleltest
2719
- recvcheck
2820
- testpackage
29-
- thelper
3021
- tparallel
31-
- unparam
3222
- varnamelen
3323
- whitespace
3424
- wrapcheck
@@ -40,8 +30,10 @@ linters:
4030
goconst:
4131
min-len: 2
4232
min-occurrences: 3
33+
cyclop:
34+
max-complexity: 20
4335
gocyclo:
44-
min-complexity: 45
36+
min-complexity: 20
4537
exclusions:
4638
generated: lax
4739
presets:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# gojsonpointer
1+
# jsonpointer
22

33
<!-- Badges: status -->
44
[![Tests][test-badge]][test-url] [![Coverage][cov-badge]][cov-url] [![CI vuln scan][vuln-scan-badge]][vuln-scan-url] [![CodeQL][codeql-badge]][codeql-url]
@@ -14,7 +14,7 @@
1414

1515
---
1616

17-
An implementation of JSON Pointer - Go language
17+
An implementation of JSON Pointer for golang, which supports go `struct`.
1818

1919
## Status
2020

pointer.go

Lines changed: 69 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@ const (
2020
pointerSeparator = `/`
2121
)
2222

23-
var (
24-
jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem()
25-
jsonSetableType = reflect.TypeOf(new(JSONSetable)).Elem()
26-
)
27-
2823
// JSONPointable is an interface for structs to implement when they need to customize the
2924
// json pointer process
3025
type JSONPointable interface {
@@ -174,7 +169,7 @@ func (p *Pointer) set(node, data any, nameProvider *jsonname.NameProvider) error
174169
nameProvider = jsonname.DefaultJSONNameProvider
175170
}
176171

177-
// Full document when empty
172+
// full document when empty
178173
if len(p.referenceTokens) == 0 {
179174
return nil
180175
}
@@ -188,82 +183,76 @@ func (p *Pointer) set(node, data any, nameProvider *jsonname.NameProvider) error
188183
return setSingleImpl(node, data, decodedToken, nameProvider)
189184
}
190185

191-
// Check for nil during traversal
192-
if isNil(node) {
193-
return fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer)
186+
next, err := p.resolveNodeForToken(node, decodedToken, nameProvider)
187+
if err != nil {
188+
return err
194189
}
195190

196-
rValue := reflect.Indirect(reflect.ValueOf(node))
197-
kind := rValue.Kind()
191+
node = next
192+
}
198193

199-
if rValue.Type().Implements(jsonPointableType) {
200-
pointable, ok := node.(JSONPointable)
201-
if !ok {
202-
panic(fmt.Errorf("internal error: expected a JSONPointable but got %T: %w", node, ErrPointer))
203-
}
204-
r, err := pointable.JSONLookup(decodedToken)
205-
if err != nil {
206-
return err
207-
}
194+
return nil
195+
}
208196

209-
fld := reflect.ValueOf(r)
210-
if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer {
211-
node = fld.Addr().Interface()
212-
continue
213-
}
214-
node = r
215-
continue
197+
func (p *Pointer) resolveNodeForToken(node any, decodedToken string, nameProvider *jsonname.NameProvider) (next any, err error) {
198+
// check for nil during traversal
199+
if isNil(node) {
200+
return nil, fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer)
201+
}
202+
203+
pointable, ok := node.(JSONPointable)
204+
if ok {
205+
r, err := pointable.JSONLookup(decodedToken)
206+
if err != nil {
207+
return nil, err
216208
}
217209

218-
switch kind { //nolint:exhaustive
219-
case reflect.Struct:
220-
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
221-
if !ok {
222-
return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
223-
}
224-
fld := rValue.FieldByName(nm)
225-
if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer {
226-
node = fld.Addr().Interface()
227-
continue
228-
}
229-
node = fld.Interface()
210+
fld := reflect.ValueOf(r)
211+
if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer {
212+
return fld.Addr().Interface(), nil
213+
}
230214

231-
case reflect.Map:
232-
kv := reflect.ValueOf(decodedToken)
233-
mv := rValue.MapIndex(kv)
215+
return r, nil
216+
}
234217

235-
if !mv.IsValid() {
236-
return fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer)
237-
}
238-
if mv.CanAddr() && mv.Kind() != reflect.Interface && mv.Kind() != reflect.Map && mv.Kind() != reflect.Slice && mv.Kind() != reflect.Pointer {
239-
node = mv.Addr().Interface()
240-
continue
241-
}
242-
node = mv.Interface()
218+
rValue := reflect.Indirect(reflect.ValueOf(node))
219+
kind := rValue.Kind()
243220

244-
case reflect.Slice:
245-
tokenIndex, err := strconv.Atoi(decodedToken)
246-
if err != nil {
247-
return err
248-
}
249-
sLength := rValue.Len()
250-
if tokenIndex < 0 || tokenIndex >= sLength {
251-
return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer)
252-
}
221+
switch kind { //nolint:exhaustive
222+
case reflect.Struct:
223+
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
224+
if !ok {
225+
return nil, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
226+
}
253227

254-
elem := rValue.Index(tokenIndex)
255-
if elem.CanAddr() && elem.Kind() != reflect.Interface && elem.Kind() != reflect.Map && elem.Kind() != reflect.Slice && elem.Kind() != reflect.Pointer {
256-
node = elem.Addr().Interface()
257-
continue
258-
}
259-
node = elem.Interface()
228+
return typeFromValue(rValue.FieldByName(nm)), nil
260229

261-
default:
262-
return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
230+
case reflect.Map:
231+
kv := reflect.ValueOf(decodedToken)
232+
mv := rValue.MapIndex(kv)
233+
234+
if !mv.IsValid() {
235+
return nil, fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer)
263236
}
264-
}
265237

266-
return nil
238+
return typeFromValue(mv), nil
239+
240+
case reflect.Slice:
241+
tokenIndex, err := strconv.Atoi(decodedToken)
242+
if err != nil {
243+
return nil, errors.Join(err, ErrPointer)
244+
}
245+
246+
sLength := rValue.Len()
247+
if tokenIndex < 0 || tokenIndex >= sLength {
248+
return nil, fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer)
249+
}
250+
251+
return typeFromValue(rValue.Index(tokenIndex)), nil
252+
253+
default:
254+
return nil, fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
255+
}
267256
}
268257

269258
func isNil(input any) bool {
@@ -280,6 +269,14 @@ func isNil(input any) bool {
280269
}
281270
}
282271

272+
func typeFromValue(v reflect.Value) any {
273+
if v.CanAddr() && v.Kind() != reflect.Interface && v.Kind() != reflect.Map && v.Kind() != reflect.Slice && v.Kind() != reflect.Pointer {
274+
return v.Addr().Interface()
275+
}
276+
277+
return v.Interface()
278+
}
279+
283280
// GetForToken gets a value for a json pointer token 1 level deep
284281
func GetForToken(document any, decodedToken string) (any, reflect.Kind, error) {
285282
return getSingleImpl(document, decodedToken, jsonname.DefaultJSONNameProvider)
@@ -352,19 +349,10 @@ func setSingleImpl(node, data any, decodedToken string, nameProvider *jsonname.N
352349
return fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer)
353350
}
354351

355-
if ns, ok := node.(JSONSetable); ok { // pointer impl
352+
if ns, ok := node.(JSONSetable); ok {
356353
return ns.JSONSet(decodedToken, data)
357354
}
358355

359-
if rValue.Type().Implements(jsonSetableType) {
360-
setable, ok := node.(JSONSetable)
361-
if !ok {
362-
panic(fmt.Errorf("internal error: expected a JSONPointable but got %T: %w", node, ErrPointer))
363-
}
364-
365-
return setable.JSONSet(decodedToken, data)
366-
}
367-
368356
switch rValue.Kind() { //nolint:exhaustive
369357
case reflect.Struct:
370358
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
@@ -508,8 +496,8 @@ const (
508496
)
509497

510498
var (
511-
encRefTokReplacer = strings.NewReplacer(encRefTok1, decRefTok1, encRefTok0, decRefTok0)
512-
decRefTokReplacer = strings.NewReplacer(decRefTok1, encRefTok1, decRefTok0, encRefTok0)
499+
encRefTokReplacer = strings.NewReplacer(encRefTok1, decRefTok1, encRefTok0, decRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global
500+
decRefTokReplacer = strings.NewReplacer(decRefTok1, encRefTok1, decRefTok0, encRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global
513501
)
514502

515503
// Unescape unescapes a json pointer reference token string to the original representation

0 commit comments

Comments
 (0)