diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..9b43615 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,280 @@ +## Golden config for golangci-lint v1.46.2 +# +# This is the best config for golangci-lint based on my experience and opinion. +# It is very strict, but not extremely strict. +# Feel free to adopt and change it for your needs. + +run: + # Timeout for analysis, e.g. 30s, 5m. + # Default: 1m + timeout: 3m + + # Define the Go version limit. + # Mainly related to generics support in go1.18. + # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 + go: "1.19" # TODO: change to 1.18 when most linters support it, see https://github.com/golangci/golangci-lint/issues/2649 + + +# This file contains only configs which differ from defaults. +# All possible options can be found here https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml +linters-settings: + cyclop: + # The maximal code complexity to report. + # Default: 10 + max-complexity: 30 + # The maximal average package complexity. + # If it's higher than 0.0 (float) the check is enabled + # Default: 0.0 + package-average: 10.0 + + errcheck: + # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. + # Such cases aren't reported by default. + # Default: false + check-type-assertions: true + + funlen: + # Checks the number of lines in a function. + # If lower than 0, disable the check. + # Default: 60 + lines: 100 + # Checks the number of statements in a function. + # If lower than 0, disable the check. + # Default: 40 + statements: 50 + + gocognit: + # Minimal code complexity to report + # Default: 30 (but we recommend 10-20) + min-complexity: 20 + + gocritic: + # Settings passed to gocritic. + # The settings key is the name of a supported gocritic checker. + # The list of supported checkers can be find in https://go-critic.github.io/overview. + settings: + captLocal: + # Whether to restrict checker to params only. + # Default: true + paramsOnly: false + underef: + # Whether to skip (*x).method() calls where x is a pointer receiver. + # Default: true + skipRecvDeref: false + + gomnd: + # List of function patterns to exclude from analysis. + # Values always ignored: `time.Date` + # Default: [] + ignored-functions: + - os.Chmod + - os.Mkdir + - os.MkdirAll + - os.OpenFile + - os.WriteFile + - prometheus.ExponentialBuckets + - prometheus.ExponentialBucketsRange + - prometheus.LinearBuckets + - strconv.FormatFloat + - strconv.FormatInt + - strconv.FormatUint + - strconv.ParseFloat + - strconv.ParseInt + - strconv.ParseUint + + gomodguard: + blocked: + # List of blocked modules. + # Default: [] + modules: + - github.com/golang/protobuf: + recommendations: + - google.golang.org/protobuf + reason: "see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules" + - github.com/satori/go.uuid: + recommendations: + - github.com/google/uuid + reason: "satori's package is not maintained" + - github.com/gofrs/uuid: + recommendations: + - github.com/google/uuid + reason: "see recommendation from dev-infra team: https://confluence.gtforge.com/x/gQI6Aw" + + govet: + # Enable all analyzers. + # Default: false + enable-all: true + # Disable analyzers by name. + # Run `go tool vet help` to see all analyzers. + # Default: [] + disable: + - fieldalignment # too strict + # Settings per analyzer. + settings: + shadow: + # Whether to be strict about shadowing; can be noisy. + # Default: false + strict: true + + nakedret: + # Make an issue if func has more lines of code than this setting, and it has naked returns. + # Default: 30 + max-func-lines: 0 + + nolintlint: + # Exclude following linters from requiring an explanation. + # Default: [] + allow-no-explanation: [ funlen, gocognit, lll ] + # Enable to require an explanation of nonzero length after each nolint directive. + # Default: false + require-explanation: true + # Enable to require nolint directives to mention the specific linter being suppressed. + # Default: false + require-specific: true + + rowserrcheck: + # database/sql is always checked + # Default: [] + packages: + - github.com/jmoiron/sqlx + + tenv: + # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. + # Otherwise, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. + # Default: false + all: true + + varcheck: + # Check usage of exported fields and variables. + # Default: false + exported-fields: false # default false # TODO: enable after fixing false positives + + +linters: + disable-all: true + enable: + ## enabled by default + # - deadcode # Finds unused code + - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - gosimple # Linter for Go source code that specializes in simplifying a code + - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - ineffassign # Detects when assignments to existing variables are not used + - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks + # - structcheck # Finds unused struct fields + - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code + - unused # Checks Go code for unused constants, variables, functions and types + # - varcheck # Finds unused global variables and constants + ## disabled by default + + # - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers + # - bidichk # Checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - contextcheck # check the function whether use a non-inherited context + # - cyclop # checks function and package cyclomatic complexity + # - dupl # Tool for code clone detection + # - durationcheck # check for two durations multiplied together + # - errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error. + - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. + # - execinquery # execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds + # - exhaustive # check exhaustiveness of enum switch statements + # - exportloopref # checks for pointers to enclosing loop variables + # - forbidigo # Forbids identifiers + # - funlen # Tool for detection of long functions + # - gochecknoglobals # check that no global variables exist + # - gochecknoinits # Checks that no init functions are present in Go code + # - gocognit # Computes and checks the cognitive complexity of functions + # - goconst # Finds repeated strings that could be replaced by a constant + # - gocritic # Provides diagnostics that check for bugs, performance and style issues. + # - gocyclo # Computes and checks the cyclomatic complexity of functions + # - godot # Check if comments end in a period + - goimports # In addition to fixing imports, goimports also formats your code in the same style as gofmt. + # - gomnd # An analyzer to detect magic numbers. + # - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. + # - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + # - goprintffuncname # Checks that printf-like functions are named with f at the end + # - gosec # Inspects source code for security problems + # - lll # Reports long lines + # - makezero # Finds slice declarations with non-zero initial length + # - nakedret # Finds naked returns in functions greater than a specified function length + # - nestif # Reports deeply nested if statements + # - nilerr # Finds the code that returns nil even if it checks that the error is not nil. + # - nilnil # Checks that there is no simultaneous return of nil error and an invalid value. + # - noctx # noctx finds sending http request without context.Context + # - nolintlint # Reports ill-formed or insufficient nolint directives + # - nonamedreturns # Reports all named returns + # - nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL. + # - predeclared # find code that shadows one of Go's predeclared identifiers + # - promlinter # Check Prometheus metrics naming via promlint + - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. + # - rowserrcheck # checks whether Err of rows is checked successfully + # - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. + - stylecheck # Stylecheck is a replacement for golint + - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + # - testpackage # linter that makes you use a separate _test package + # - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - unconvert # Remove unnecessary type conversions + - unparam # Reports unused function parameters + # - wastedassign # wastedassign finds wasted assignment statements. + # - whitespace # Tool for detection of leading and trailing whitespace + + ## you may want to enable + #- decorder # check declaration order and count of types, constants, variables and functions + #- exhaustruct # Checks if all structure fields are initialized + #- goheader # Checks is file header matches to pattern + #- ireturn # Accept Interfaces, Return Concrete Types + #- prealloc # [premature optimization, but can be used in some cases] Finds slice declarations that could potentially be preallocated + #- varnamelen # [great idea, but too many false positives] checks that the length of a variable's name matches its scope + #- wrapcheck # Checks that errors returned from external packages are wrapped + ## disabled + #- containedctx # containedctx is a linter that detects struct contained context.Context field + #- depguard # [replaced by gomodguard] Go linter that checks if package imports are in a list of acceptable packages + #- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) + #- errchkjson # [don't see profit + I'm against of omitting errors like in the first example https://github.com/breml/errchkjson] Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted. + #- forcetypeassert # [replaced by errcheck] finds forced type assertions + #- gci # Gci controls golang package import order and makes it always deterministic. + #- godox # Tool for detection of FIXME, TODO and other comment keywords + #- goerr113 # [too strict] Golang linter to check the errors handling expressions + #- gofmt # [replaced by goimports] Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification + #- gofumpt # [replaced by goimports, gofumports is not available yet] Gofumpt checks whether code was gofumpt-ed. + #- grouper # An analyzer to analyze expression groups. + #- ifshort # Checks that your code uses short syntax for if-statements whenever possible + #- importas # Enforces consistent import aliases + #- maintidx # maintidx measures the maintainability index of each function. + #- misspell # [useless] Finds commonly misspelled English words in comments + #- nlreturn # [too strict and mostly code is not more readable] nlreturn checks for a new line before return and branch statements to increase code clarity + #- paralleltest # [too many false positives] paralleltest detects missing usage of t.Parallel() method in your Go test + #- tagliatelle # Checks the struct tags. + #- thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers + #- wsl # [too strict and mostly code is not more readable] Whitespace Linter - Forces you to use empty lines! + ## deprecated + #- exhaustivestruct # [deprecated, replaced by exhaustruct] Checks if all struct's fields are initialized + #- golint # [deprecated, replaced by revive] Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes + #- interfacer # [deprecated] Linter that suggests narrower interface types + #- maligned # [deprecated, replaced by govet fieldalignment] Tool to detect Go structs that would take less memory if their fields were sorted + #- scopelint # [deprecated, replaced by exportloopref] Scopelint checks for unpinned variables in go programs + + +issues: + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 50 + + exclude-rules: + - source: "^//\\s*go:generate\\s" + linters: [ lll ] + - source: "(noinspection|TODO)" + linters: [ godot ] + - source: "//noinspection" + linters: [ gocritic ] + - source: "^\\s+if _, ok := err\\.\\([^.]+\\.InternalError\\); ok {" + linters: [ errorlint ] + - path: "_test\\.go" + linters: + - bodyclose + - dupl + - funlen + - goconst + - gosec + - noctx + - wrapcheck diff --git a/Makefile b/Makefile index e007882..e9efe81 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ golangci: ifndef HAS_GOLANGCI curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.49.0 endif - golangci-lint run ./... + golangci-lint run cover: work go test $(TESTARGS) -tags=unit -cover -coverpkg=./ ./... diff --git a/pkg/api/api.go b/pkg/api/api.go index 17decd5..67362fe 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -144,7 +144,7 @@ func debugResponse(response *http.Response) { } func request(method string, url string, client *http.Client, body []byte, query string, debug bool) (*string, error) { - var requestBody io.Reader = nil + var requestBody io.Reader if len(body) > 0 { requestBody = bytes.NewBuffer(body) } @@ -178,9 +178,9 @@ func request(method string, url string, client *http.Client, body []byte, query debugResponse(resp) } defer func() { - err := resp.Body.Close() - if err != nil { - logger.Error(err) + dErr := resp.Body.Close() + if dErr != nil { + logger.Error(dErr) } }() responseBody, err := readBody(resp) @@ -190,7 +190,7 @@ func request(method string, url string, client *http.Client, body []byte, query } if resp.StatusCode != 200 { return nil, fmt.Errorf( - "Response status code: %d\nbody:\n%s", + "response status code: %d\nbody:\n%s", resp.StatusCode, *responseBody, ) diff --git a/pkg/api/items.go b/pkg/api/items.go index 1e4b516..e9a6ef0 100644 --- a/pkg/api/items.go +++ b/pkg/api/items.go @@ -95,7 +95,7 @@ func (result *TranslationResult) PrintTranslation() { printTranslation(result) } -// PrintAddedTranslation prints transcription diring adding operation +// PrintAddedTranslation prints transcription during adding operation func (result *TranslationResult) PrintAddedTranslation() { printAddedTranslation(result) } diff --git a/pkg/api/testing/translate_words_test.go b/pkg/api/testing/translate_words_test.go index 74099ed..0062a99 100644 --- a/pkg/api/testing/translate_words_test.go +++ b/pkg/api/testing/translate_words_test.go @@ -18,10 +18,10 @@ func TestTranslateWord(t *testing.T) { func TestTranslateWords(t *testing.T) { searchWords := []string{fakeapi.SearchWord} - fakeApi := fakeapi.FakeAPI{} + fakeAPI := fakeapi.FakeAPI{} ctx := context.Background() ch := channel.ToStringChannel(ctx, searchWords...) - out := fakeApi.TranslateWords(ctx, ch) + out := fakeAPI.TranslateWords(ctx, ch) res := (<-out).Result fakeapi.CheckResult(t, res, searchWords[0], fakeapi.Expected) } diff --git a/pkg/api/utils.go b/pkg/api/utils.go index 81b89d5..b46cfb6 100644 --- a/pkg/api/utils.go +++ b/pkg/api/utils.go @@ -35,8 +35,8 @@ func fromResponse(result Result, body string) error { err := getJSONFromString(body, result) if err != nil { res := NoResult{} - if err := getJSONFromString(body, res); err != nil { - return fmt.Errorf("cannot translate word: %s, %w", result.GetWord(), err) + if fErr := getJSONFromString(body, res); fErr != nil { + return fmt.Errorf("cannot translate word: %s, %w", result.GetWord(), fErr) } return err } diff --git a/pkg/files/download.go b/pkg/files/download.go index 4cdb833..d8f0295 100644 --- a/pkg/files/download.go +++ b/pkg/files/download.go @@ -66,9 +66,9 @@ func (f *FileDownloader) DownloadFile() (string, error) { return "", err } defer func() { - err := fd.Close() - if err != nil { - logger.Error(err) + cErr := fd.Close() + if cErr != nil { + logger.Error(cErr) } }() resp, err := http.Get(f.URL) @@ -76,9 +76,9 @@ func (f *FileDownloader) DownloadFile() (string, error) { return "", fmt.Errorf("cannot read url: %s, %w", f.URL, err) } defer func() { - err := resp.Body.Close() - if err != nil { - logger.Error(err) + cErr := resp.Body.Close() + if cErr != nil { + logger.Error(cErr) } }() if resp.StatusCode != http.StatusOK { diff --git a/pkg/heap/heap.go b/pkg/heap/heap.go index 3fd6b96..9d90ead 100644 --- a/pkg/heap/heap.go +++ b/pkg/heap/heap.go @@ -52,7 +52,7 @@ func (h *IndexedHeap) Pull() *IndexedItem { if h.Len() == 0 { return nil } - message := heap.Pop(h).(IndexedItem) + message, _ := heap.Pop(h).(IndexedItem) return &message } @@ -60,7 +60,7 @@ func (h *IndexedHeap) PullWithCondition(check func(*IndexedItem) bool) *IndexedI h.lock.Lock() defer h.lock.Unlock() if check(h.pick()) { - message := heap.Pop(h).(IndexedItem) + message, _ := heap.Pop(h).(IndexedItem) return &message } return nil diff --git a/pkg/translator/linguleo.go b/pkg/translator/linguleo.go index 8070f9c..8d4d373 100644 --- a/pkg/translator/linguleo.go +++ b/pkg/translator/linguleo.go @@ -56,11 +56,10 @@ func NewLingualeo(version string) (Lingualeo, error) { } logger.InitLogger(client.LogLevel, client.LogPrettyPrint) client.checkMediaPlayer() - a, err := api.NewAPI(client.Email, client.Password, client.Debug) + client.API, err = api.NewAPI(client.Email, client.Password, client.Debug) if err != nil { return client, err } - client.API = a return client, nil }