diff --git a/.golangci.yaml b/.golangci.yaml index fa28eb3bb..1faeae42c 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -7,6 +7,16 @@ linters-settings: - standard - default - prefix(github.com/spf13/viper) + gocritic: + # Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage. + enabled-tags: + - diagnostic + - experimental + - opinionated + - style + disabled-checks: + - importShadow + - unnamedResult golint: min-confidence: 0 goimports: @@ -22,6 +32,7 @@ linters: - exhaustive - exportloopref - gci + - gocritic - godot - gofmt - gofumpt @@ -63,7 +74,6 @@ linters: # - gochecknoinits # - gocognit # - goconst - # - gocritic # - gocyclo # - gosec # - gosimple diff --git a/internal/encoding/dotenv/map_utils.go b/internal/encoding/dotenv/map_utils.go index 4901d7c76..8bfe0a9de 100644 --- a/internal/encoding/dotenv/map_utils.go +++ b/internal/encoding/dotenv/map_utils.go @@ -9,7 +9,7 @@ import ( // flattenAndMergeMap recursively flattens the given map into a new map // Code is based on the function with the same name in the main package. // TODO: move it to a common place. -func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any { +func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { if shadow != nil && prefix != "" && shadow[prefix] != nil { // prefix is shadowed => nothing more to flatten return shadow diff --git a/internal/encoding/ini/map_utils.go b/internal/encoding/ini/map_utils.go index 06e703f97..490ab594e 100644 --- a/internal/encoding/ini/map_utils.go +++ b/internal/encoding/ini/map_utils.go @@ -42,7 +42,7 @@ func deepSearch(m map[string]any, path []string) map[string]any { // flattenAndMergeMap recursively flattens the given map into a new map // Code is based on the function with the same name in the main package. // TODO: move it to a common place. -func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any { +func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { if shadow != nil && prefix != "" && shadow[prefix] != nil { // prefix is shadowed => nothing more to flatten return shadow diff --git a/internal/encoding/javaproperties/map_utils.go b/internal/encoding/javaproperties/map_utils.go index 7c7e78a26..6e1aff223 100644 --- a/internal/encoding/javaproperties/map_utils.go +++ b/internal/encoding/javaproperties/map_utils.go @@ -42,7 +42,7 @@ func deepSearch(m map[string]any, path []string) map[string]any { // flattenAndMergeMap recursively flattens the given map into a new map // Code is based on the function with the same name in the main package. // TODO: move it to a common place. -func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any { +func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any { if shadow != nil && prefix != "" && shadow[prefix] != nil { // prefix is shadowed => nothing more to flatten return shadow diff --git a/overrides_test.go b/overrides_test.go index a8f4cc17e..42da3ba37 100644 --- a/overrides_test.go +++ b/overrides_test.go @@ -97,7 +97,7 @@ func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, fir v := New() firstKeys := strings.Split(firstPath, v.keyDelim) if assert == nil || - len(firstKeys) == 0 || len(firstKeys[0]) == 0 { + len(firstKeys) == 0 || firstKeys[0] == "" { return v } @@ -115,7 +115,7 @@ func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, fir // Override and check new value secondKeys := strings.Split(secondPath, v.keyDelim) - if len(secondKeys) == 0 || len(secondKeys[0]) == 0 { + if len(secondKeys) == 0 || secondKeys[0] == "" { return v } v.Set(secondPath, secondValue) @@ -129,7 +129,7 @@ func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, fir // configuration map of the given layer, and that the final value equals the one given. func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string, value any) { if assert == nil || v == nil || - len(keys) == 0 || len(keys[0]) == 0 { + len(keys) == 0 || keys[0] == "" { return } diff --git a/viper.go b/viper.go index 7de2e78e4..75f5fc4ba 100644 --- a/viper.go +++ b/viper.go @@ -957,7 +957,8 @@ func (v *Viper) Sub(key string) *Viper { } if reflect.TypeOf(data).Kind() == reflect.Map { - subv.parents = append(v.parents, strings.ToLower(key)) + subv.parents = append([]string(nil), v.parents...) + subv.parents = append(subv.parents, strings.ToLower(key)) subv.automaticEnvApplied = v.automaticEnvApplied subv.envPrefix = v.envPrefix subv.envKeyReplacer = v.envKeyReplacer @@ -1409,7 +1410,7 @@ func readAsCSV(val string) ([]string, error) { func stringToStringConv(val string) any { val = strings.Trim(val, "[]") // An empty string would cause an empty map - if len(val) == 0 { + if val == "" { return map[string]any{} } r := csv.NewReader(strings.NewReader(val)) @@ -1433,7 +1434,7 @@ func stringToStringConv(val string) any { func stringToIntConv(val string) any { val = strings.Trim(val, "[]") // An empty string would cause an empty map - if len(val) == 0 { + if val == "" { return map[string]any{} } ss := strings.Split(val, ",") @@ -1481,13 +1482,13 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) { // RegisterAlias creates an alias that provides another accessor for the same key. // This enables one to change a name without breaking the application. -func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) } +func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) } -func (v *Viper) RegisterAlias(alias string, key string) { +func (v *Viper) RegisterAlias(alias, key string) { v.registerAlias(alias, strings.ToLower(key)) } -func (v *Viper) registerAlias(alias string, key string) { +func (v *Viper) registerAlias(alias, key string) { alias = strings.ToLower(alias) if alias != key && alias != v.realKey(key) { _, exists := v.aliases[alias] diff --git a/viper_test.go b/viper_test.go index 0e416e7df..d8443835c 100644 --- a/viper_test.go +++ b/viper_test.go @@ -428,7 +428,7 @@ func TestReadInConfig(t *testing.T) { file, err := fs.Create(testutil.AbsFilePath(t, "/etc/viper/config.yaml")) require.NoError(t, err) - _, err = file.Write([]byte(`key: value`)) + _, err = file.WriteString(`key: value`) require.NoError(t, err) file.Close() @@ -453,7 +453,7 @@ func TestReadInConfig(t *testing.T) { file, err := fs.Create(testutil.AbsFilePath(t, "/etc/viper/config.yaml")) require.NoError(t, err) - _, err = file.Write([]byte(`key: value`)) + _, err = file.WriteString(`key: value`) require.NoError(t, err) file.Close() @@ -930,7 +930,8 @@ func TestUnmarshalWithDecoderOptions(t *testing.T) { if raw == "" { return m, nil } - return m, json.Unmarshal([]byte(raw), &m) + err := json.Unmarshal([]byte(raw), &m) + return m, err }, )) @@ -2506,6 +2507,8 @@ func BenchmarkGetBoolFromMap(b *testing.B) { } // Skip some tests on Windows that kept failing when Windows was added to the CI as a target. +// +//nolint:gocritic // sloppyTestFuncName func skipWindows(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("Skip test on Windows")