diff --git a/.gitignore b/.gitignore index a14e0375..553b22be 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ bin/ dist/ .DS_Store coverage/ -tests-report.json \ No newline at end of file +tests-report.json +linters-report.xml diff --git a/.golangci.pipe.yml b/.golangci.pipe.yml index 3c820d85..7fb45397 100644 --- a/.golangci.pipe.yml +++ b/.golangci.pipe.yml @@ -106,7 +106,11 @@ run: output: # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions # default is "colored-line-number" - formats: colored-line-number + formats: + - format: colored-line-number + path: stderr + - format: checkstyle + path: linters-report.xml # print lines of code with issue, default is true print-issued-lines: true diff --git a/.golangci.yml b/.golangci.yml index d9d3dbfe..33784656 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,7 +12,33 @@ linters-settings: lines: 100 statements: 50 gci: - local-prefixes: github.com/obalunenko/advent-of-code + # Section configuration to compare against. + # Section names are case-insensitive and may contain parameters in (). + # The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`, + # If `custom-order` is `true`, it follows the order of `sections` option. + # Default: ["standard", "default"] + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/obalunenko/advent-of-code) # Custom section: groups all imports with the specified Prefix. + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled. + - localmodule # Local module section: contains all local packages. This section is not present unless explicitly enabled. + + # Skip generated files. + # Default: true + skip-generated: false + + # Enable custom order of sections. + # If `true`, make the section order the same as the order of `sections`. + # Default: false + custom-order: true + + # Drops lexical ordering for custom sections. + # Default: false + no-lex-order: true + goconst: min-len: 2 min-occurrences: 2 @@ -33,13 +59,128 @@ linters-settings: min-complexity: 15 goimports: local-prefixes: github.com/obalunenko/advent-of-code - gomnd: - settings: - mnd: - # don't include the "operation" and "assign" - checks: [ argument,case,condition,return ] + mnd: + # List of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description. + # Default: ["argument", "case", "condition", "operation", "return", "assign"] + checks: + - argument + - case + - condition + - operation + - return + - assign + # List of numbers to exclude from analysis. + # The numbers should be written as string. + # Values always ignored: "1", "1.0", "0" and "0.0" + # Default: [] + ignored-numbers: [] + # List of file patterns to exclude from analysis. + # Values always ignored: `.+_test.go` + # Default: [] + ignored-files: [] + # List of function patterns to exclude from analysis. + # Following functions are always ignored: `time.Date`, + # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`, + # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`. + # Default: [] + ignored-functions: [] + govet: - check-shadowing: true + # Disable all analyzers. + # Default: false + disable-all: false + # Enable analyzers by name. + # (in addition to default: + # appends, asmdecl, assign, atomic, bools, buildtag, cgocall, composites, copylocks, defers, directive, errorsas, + # framepointer, httpresponse, ifaceassert, loopclosure, lostcancel, nilfunc, printf, shift, sigchanyzer, slog, + # stdmethods, stringintconv, structtag, testinggoroutine, tests, timeformat, unmarshal, unreachable, unsafeptr, + # unusedresult + # ). + # Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. + # Default: [] + disable: + - fieldalignment + enable: + # Check for missing values after append. + - appends + # Report mismatches between assembly files and Go declarations. + - asmdecl + # Check for useless assignments. + - assign + # Check for common mistakes using the sync/atomic package. + - atomic + # Check for non-64-bits-aligned arguments to sync/atomic functions. + - atomicalign + # Check for common mistakes involving boolean operators. + - bools + # Check //go:build and // +build directives. + - buildtag + # Detect some violations of the cgo pointer passing rules. + - cgocall + # Check for unkeyed composite literals. + - composites + # Check for locks erroneously passed by value. + - copylocks + # Check for calls of reflect.DeepEqual on error values. + - deepequalerrors + # Report common mistakes in defer statements. + - defers + # Check Go toolchain directives such as //go:debug. + - directive + # Report passing non-pointer or non-error values to errors.As. + - errorsas + # Find calls to a particular function. + - findcall + # Report assembly that clobbers the frame pointer before saving it. + - framepointer + # Check for mistakes using HTTP responses. + - httpresponse + # Detect impossible interface-to-interface type assertions. + - ifaceassert + # Check references to loop variables from within nested functions. + - loopclosure + # Check cancel func returned by context.WithCancel is called. + - lostcancel + # Check for useless comparisons between functions and nil. + - nilfunc + # Check for redundant or impossible nil comparisons. + - nilness + # Check consistency of Printf format strings and arguments. + - printf + # Check for comparing reflect.Value values with == or reflect.DeepEqual. + - reflectvaluecompare + # Check for possible unintended shadowing of variables. + - shadow + # Check for shifts that equal or exceed the width of the integer. + - shift + # Check for unbuffered channel of os.Signal. + - sigchanyzer + # Check for invalid structured logging calls. + - slog + # Check the argument type of sort.Slice. + - sortslice + # Check signature of methods of well-known interfaces. + - stdmethods + # Check for string(int) conversions. + - stringintconv + # Check that struct field tags conform to reflect.StructTag.Get. + - structtag + # Report calls to (*testing.T).Fatal from goroutines started by a test. + - testinggoroutine + # Check for common mistaken usages of tests and examples. + - tests + # Check for calls of (time.Time).Format or time.Parse with 2006-02-01. + - timeformat + # Report passing non-pointer or non-interface values to unmarshal. + - unmarshal + # Check for unreachable code. + - unreachable + # Check for invalid conversions of uintptr to unsafe.Pointer. + - unsafeptr + # Check for unused results of calls to some functions. + - unusedresult + # Checks for unused writes. + - unusedwrite lll: line-length: 140 misspell: @@ -58,7 +199,7 @@ linters: - dogsled - dupl - errcheck - - exportloopref + - copyloopvar - exhaustive - funlen - gochecknoinits @@ -67,7 +208,7 @@ linters: - gocyclo - gofmt - goimports - - gomnd + - mnd - goprintffuncname - gosec - gosimple @@ -104,6 +245,19 @@ linters: # - testpackage issues: + # Show only new issues: if there are unstaged changes or untracked files, + # only those changes are analyzed, else only changes in HEAD~ are analyzed. + # It's a super-useful option for integration of golangci-lint into existing + # large codebase. It's not practical to fix all existing issues at the moment + # of integration: much better don't allow issues in new code. + # Default is false. + new: false + # Fix found issues (if it's supported by the linter) + fix: false + exclude-files: + - \.pb\.go$ + exclude-dirs: + - vendor/ exclude-use-default: false exclude: # for "public interface + private struct implementation" cases only! @@ -137,55 +291,77 @@ issues: linters: - gochecknoinits - # Show only new issues: if there are unstaged changes or untracked files, - # only those changes are analyzed, else only changes in HEAD~ are analyzed. - # It's a super-useful option for integration of golangci-lint into existing - # large codebase. It's not practical to fix all existing issues at the moment - # of integration: much better don't allow issues in new code. - # Default is false. - new: true - - # Fix found issues (if it's supported by the linter) - fix: false - - severity: - # Default value is empty string. - # Set the default severity for issues. If severity rules are defined and the issues - # do not match or no severity is provided to the rule this will be the default - # severity applied. Severities should match the supported severity names of the - # selected out format. - # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity - # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity - # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message - default-severity: error - - # The default value is false. - # If set to true severity-rules regular expressions become case sensitive. - case-sensitive: false - - # Default value is empty list. - # When a list of severity rules are provided, severity information will be added to lint - # issues. Severity rules have the same filtering capability as exclude rules except you - # are allowed to specify one matcher per severity rule. - # Only affects out formats that support setting severity information. - rules: - - linters: - - dupl - severity: warning - run: issues-exit-code: 0 tests: true - skip-dirs: - - vendor/ - skip-files: - - \.pb\.go$ + +severity: + # Set the default severity for issues. + # + # If severity rules are defined and the issues do not match or no severity is provided to the rule + # this will be the default severity applied. + # Severities should match the supported severity names of the selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#SeverityLevel + # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + # - TeamCity: https://www.jetbrains.com/help/teamcity/service-messages.html#Inspection+Instance + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Default: "" + default-severity: error + + # If set to true `severity-rules` regular expressions become case-sensitive. + # Default: false + case-sensitive: true + + # When a list of severity rules are provided, severity information will be added to lint issues. + # Severity rules have the same filtering capability as exclude rules + # except you are allowed to specify one matcher per severity rule. + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Only affects out formats that support setting severity information. + # + # Default: [] + rules: + - linters: + - dupl + severity: info + # output configuration options output: # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions # default is "colored-line-number" - format: checkstyle + formats: + - format: colored-line-number + path: stderr + - format: checkstyle + path: linters-report.xml + + + # Order to use when sorting results. + # Require `sort-results` to `true`. + # Possible values: `file`, `linter`, and `severity`. + # + # If the severity values are inside the following list, they are ordered in this order: + # 1. error + # 2. warning + # 3. high + # 4. medium + # 5. low + # Either they are sorted alphabetically. + # + # Default: ["file"] + sort-order: + - linter + - severity + - file # filepath, line, and column. + + # Show statistics per linter. + # Default: false + show-stats: true # print lines of code with issue, default is true print-issued-lines: true diff --git a/cmd/aoc-cli/handlers.go b/cmd/aoc-cli/handlers.go index bcea700a..2e1fd6da 100644 --- a/cmd/aoc-cli/handlers.go +++ b/cmd/aoc-cli/handlers.go @@ -21,7 +21,7 @@ import ( ) func onExit(_ context.Context) cli.AfterFunc { - return func(c *cli.Context) error { + return func(_ *cli.Context) error { fmt.Println("Exit...") return nil diff --git a/internal/command/command_test.go b/internal/command/command_test.go index 4a9959da..bdebb60c 100644 --- a/internal/command/command_test.go +++ b/internal/command/command_test.go @@ -34,10 +34,10 @@ func newMockHTTPClient(p returnParams) *mockHTTPClient { return &http.Response{ Status: http.StatusText(p.status), StatusCode: p.status, - Proto: "HTTP/1.0", - ProtoMajor: 1, - ProtoMinor: 0, - Header: nil, + Proto: req.Proto, + ProtoMajor: req.ProtoMajor, + ProtoMinor: req.ProtoMinor, + Header: req.Header, Body: p.body, ContentLength: 0, TransferEncoding: nil, diff --git a/internal/puzzles/common/intcomputer/intcoumputer_test.go b/internal/puzzles/common/intcomputer/intcoumputer_test.go index 6480ed38..3e9ecf9f 100644 --- a/internal/puzzles/common/intcomputer/intcoumputer_test.go +++ b/internal/puzzles/common/intcomputer/intcoumputer_test.go @@ -47,8 +47,6 @@ func Test_New(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := New(tt.args.input) if tt.wantErr { @@ -116,8 +114,6 @@ func Test_computer_add(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { err := tt.c.add(tt.args.aPos, tt.args.bPos, tt.args.resPos) require.NoError(t, err) @@ -163,8 +159,6 @@ func Test_computer_mult(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { err := tt.c.mult(tt.args.aPos, tt.args.bPos, tt.args.resPos) require.NoError(t, err) @@ -195,8 +189,6 @@ func Test_computer_Execute(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { comp := tt.c got, err := comp.Execute() @@ -233,8 +225,6 @@ func Test_computer_Input(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { comp := tt.c comp.Input(tt.args.noun, tt.args.verb) diff --git a/internal/puzzles/input/content_test.go b/internal/puzzles/input/content_test.go index c16f58f0..a9cd2e07 100644 --- a/internal/puzzles/input/content_test.go +++ b/internal/puzzles/input/content_test.go @@ -34,10 +34,10 @@ func newMockHTTPClient(p returnParams) *mockHTTPClient { return &http.Response{ Status: http.StatusText(p.status), StatusCode: p.status, - Proto: "HTTP/1.0", + Proto: req.Proto, ProtoMajor: 1, - ProtoMinor: 0, - Header: nil, + ProtoMinor: req.ProtoMinor, + Header: req.Header, Body: p.body, ContentLength: 0, TransferEncoding: nil, @@ -173,7 +173,7 @@ func TestGet(t *testing.T) { name: "", client: client{ IHTTPClient: &mockHTTPClient{ - MockDo: func(req *http.Request) (*http.Response, error) { + MockDo: func(_ *http.Request) (*http.Response, error) { return &http.Response{}, errors.New("error in test") }, }, diff --git a/internal/puzzles/name_test.go b/internal/puzzles/name_test.go index d4e057c8..cd554e6c 100644 --- a/internal/puzzles/name_test.go +++ b/internal/puzzles/name_test.go @@ -49,8 +49,6 @@ func TestMakeName(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := MakeName(tt.args.year, tt.args.puzzle) if tt.wantErr { @@ -58,7 +56,9 @@ func TestMakeName(t *testing.T) { return } + assert.NoError(t, err) + assert.Equal(t, tt.want, got) }) } diff --git a/internal/puzzles/solutions/2015/day01/solution_test.go b/internal/puzzles/solutions/2015/day01/solution_test.go index c33d19e5..038ac55d 100644 --- a/internal/puzzles/solutions/2015/day01/solution_test.go +++ b/internal/puzzles/solutions/2015/day01/solution_test.go @@ -124,8 +124,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -180,8 +178,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2015/day02/solution_test.go b/internal/puzzles/solutions/2015/day02/solution_test.go index 2949470b..0793b9cd 100644 --- a/internal/puzzles/solutions/2015/day02/solution_test.go +++ b/internal/puzzles/solutions/2015/day02/solution_test.go @@ -68,8 +68,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -124,8 +122,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2016/day01/solution_test.go b/internal/puzzles/solutions/2016/day01/solution_test.go index 1c2d949d..ead14d37 100644 --- a/internal/puzzles/solutions/2016/day01/solution_test.go +++ b/internal/puzzles/solutions/2016/day01/solution_test.go @@ -76,8 +76,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -124,8 +122,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2016/day02/solution.go b/internal/puzzles/solutions/2016/day02/solution.go index a5b0e916..7dccf6bc 100644 --- a/internal/puzzles/solutions/2016/day02/solution.go +++ b/internal/puzzles/solutions/2016/day02/solution.go @@ -119,7 +119,7 @@ let's predict that this is a 2 dimension matrix and '5' is 0,2m func loadKeypadPart2() keypad { start := keypadPos{ x: 0, - y: 2, + y: 2, //nolint:mnd // False positive. } g := [][]string{ diff --git a/internal/puzzles/solutions/2017/day01/solution.go b/internal/puzzles/solutions/2017/day01/solution.go index 22761772..2ac9c01b 100644 --- a/internal/puzzles/solutions/2017/day01/solution.go +++ b/internal/puzzles/solutions/2017/day01/solution.go @@ -54,7 +54,7 @@ func part2(in io.Reader) (string, error) { return "", fmt.Errorf("make list: %w", err) } - shift := len(list) / 2 + shift := len(list) / 2 //nolint:mnd // False positive. itr := newIterator(list, shift, true) diff --git a/internal/puzzles/solutions/2017/day01/solution_test.go b/internal/puzzles/solutions/2017/day01/solution_test.go index 99057edd..33dfe23c 100644 --- a/internal/puzzles/solutions/2017/day01/solution_test.go +++ b/internal/puzzles/solutions/2017/day01/solution_test.go @@ -85,8 +85,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -174,8 +172,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2018/day01/solution_test.go b/internal/puzzles/solutions/2018/day01/solution_test.go index 407b86c3..39876c26 100644 --- a/internal/puzzles/solutions/2018/day01/solution_test.go +++ b/internal/puzzles/solutions/2018/day01/solution_test.go @@ -84,8 +84,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -164,8 +162,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2019/day01/solution.go b/internal/puzzles/solutions/2019/day01/solution.go index 285dbbb5..d5784051 100644 --- a/internal/puzzles/solutions/2019/day01/solution.go +++ b/internal/puzzles/solutions/2019/day01/solution.go @@ -81,6 +81,7 @@ func calc(input io.Reader, calcFn calcFunc) (string, error) { in <- module{ mass: mass, } + lines++ } diff --git a/internal/puzzles/solutions/2019/day01/solution_test.go b/internal/puzzles/solutions/2019/day01/solution_test.go index e9c43f7c..e199eaed 100644 --- a/internal/puzzles/solutions/2019/day01/solution_test.go +++ b/internal/puzzles/solutions/2019/day01/solution_test.go @@ -68,8 +68,6 @@ func Test_module_fuel(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { m := module{ mass: tt.fields.mass, @@ -116,8 +114,6 @@ func Test_calcPart1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { in <- module{mass: tt.input} @@ -175,8 +171,6 @@ func Test_calcPart2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { in <- module{mass: tt.input} @@ -232,8 +226,6 @@ func Test_calc(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { input := utils.ReaderFromFile(t, tt.args.inputPath) got, err := calc(input, tt.args.calcFn) diff --git a/internal/puzzles/solutions/2019/day02/solution_test.go b/internal/puzzles/solutions/2019/day02/solution_test.go index 3a4d3619..e330dc4d 100644 --- a/internal/puzzles/solutions/2019/day02/solution_test.go +++ b/internal/puzzles/solutions/2019/day02/solution_test.go @@ -50,8 +50,6 @@ func Test_nounVerb(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got := nounVerb(tt.args.noun, tt.args.verb) assert.Equal(t, tt.want, got) @@ -91,8 +89,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2019/day03/solution.go b/internal/puzzles/solutions/2019/day03/solution.go index 15f0d02f..22d6f9b5 100644 --- a/internal/puzzles/solutions/2019/day03/solution.go +++ b/internal/puzzles/solutions/2019/day03/solution.go @@ -185,8 +185,6 @@ func findCross(wm1, wm2 map[pos]int) []pos { res := make([]pos, 0, len(wm1)) for p := range wm1 { - p := p - if _, exist := wm2[p]; exist { res = append(res, p) } diff --git a/internal/puzzles/solutions/2019/day03/solution_test.go b/internal/puzzles/solutions/2019/day03/solution_test.go index 9acf1c85..2f4b253c 100644 --- a/internal/puzzles/solutions/2019/day03/solution_test.go +++ b/internal/puzzles/solutions/2019/day03/solution_test.go @@ -79,8 +79,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -131,8 +129,6 @@ func Test_findCross(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got := findCross(tt.args.wm1, tt.args.wm2) assert.ElementsMatch(t, tt.want, got) @@ -182,8 +178,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2019/day04/solution.go b/internal/puzzles/solutions/2019/day04/solution.go index ded564a6..ecf341e1 100644 --- a/internal/puzzles/solutions/2019/day04/solution.go +++ b/internal/puzzles/solutions/2019/day04/solution.go @@ -96,15 +96,13 @@ func isIncreasing(n int) bool { func hasRepeated(n int) bool { nmbs := intToSlice(n) - var hasRepeated bool - for i := 1; i <= len(nmbs)-1; i++ { if nmbs[i] == nmbs[i-1] { - hasRepeated = true + return true } } - return hasRepeated + return false } func hasRepeatedWithDouble(n int) bool { @@ -143,6 +141,7 @@ func isPasswordPart2(n int) bool { return isIncreasing(n) && hasRepeatedWithDouble(n) } +//nolint:mnd // False positive. func intToSlice(n int) [6]int { return [6]int{ (n % 1000000) / 100000, diff --git a/internal/puzzles/solutions/2019/day04/solution_test.go b/internal/puzzles/solutions/2019/day04/solution_test.go index 73572e06..55d29086 100644 --- a/internal/puzzles/solutions/2019/day04/solution_test.go +++ b/internal/puzzles/solutions/2019/day04/solution_test.go @@ -60,8 +60,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -100,8 +98,6 @@ func Test_findPasswords(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := findPasswords(tt.args.low, tt.args.high, isPasswordPart1) if tt.wantErr { @@ -150,8 +146,6 @@ func Test_isIncreasing(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got := isIncreasing(tt.args.n) assert.Equal(t, tt.want, got) @@ -179,8 +173,6 @@ func Test_intToSlice(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got := intToSlice(tt.args.n) assert.Equal(t, tt.want, got) @@ -215,8 +207,6 @@ func Test_hasRepeated(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got := hasRepeated(tt.args.n) assert.Equal(t, tt.want, got) @@ -258,8 +248,6 @@ func Test_isPassword(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got := isPasswordPart1(tt.args.n) assert.Equal(t, tt.want, got) @@ -302,8 +290,6 @@ func Test_isPasswordPart2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got := isPasswordPart2(tt.args.n) assert.Equal(t, tt.want, got) @@ -351,8 +337,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2020/day01/solution.go b/internal/puzzles/solutions/2020/day01/solution.go index 479ba44f..5bcff8d5 100644 --- a/internal/puzzles/solutions/2020/day01/solution.go +++ b/internal/puzzles/solutions/2020/day01/solution.go @@ -93,6 +93,7 @@ func (s solution) Part2(input io.Reader) (string, error) { return strconv.Itoa(res), nil } +//nolint:mnd // False positive due to magic numbers. func foundEntries(expensereport []int) (a, b, c int, err error) { const ( dest = 2020 diff --git a/internal/puzzles/solutions/2020/day01/solution_test.go b/internal/puzzles/solutions/2020/day01/solution_test.go index 7358c047..ca86e681 100644 --- a/internal/puzzles/solutions/2020/day01/solution_test.go +++ b/internal/puzzles/solutions/2020/day01/solution_test.go @@ -60,8 +60,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -108,8 +106,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2020/day02/solution_test.go b/internal/puzzles/solutions/2020/day02/solution_test.go index 595506b4..5c1db630 100644 --- a/internal/puzzles/solutions/2020/day02/solution_test.go +++ b/internal/puzzles/solutions/2020/day02/solution_test.go @@ -60,8 +60,6 @@ func Test_solution_Part1(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part1(tt.args.input) if tt.wantErr { @@ -108,8 +106,6 @@ func Test_solution_Part2(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := s.Part2(tt.args.input) if tt.wantErr { diff --git a/internal/puzzles/solutions/2021/day03/solution_test.go b/internal/puzzles/solutions/2021/day03/solution_test.go index 310a1873..160d18e7 100644 --- a/internal/puzzles/solutions/2021/day03/solution_test.go +++ b/internal/puzzles/solutions/2021/day03/solution_test.go @@ -185,6 +185,7 @@ func Test_bitrates_consumption(t *testing.T) { first: tt.fields.gamma, second: tt.fields.epsilon, } + got, err := b.consumption() if !tt.wantErr(t, err, "consumption()") { return diff --git a/internal/puzzles/solutions/2021/day04/solution.go b/internal/puzzles/solutions/2021/day04/solution.go index 06ff77a0..7dbbb051 100644 --- a/internal/puzzles/solutions/2021/day04/solution.go +++ b/internal/puzzles/solutions/2021/day04/solution.go @@ -60,7 +60,7 @@ func (s solution) Part2(input io.Reader) (string, error) { func rule(boardsNum int) winRule { var count int - return func(w winner) bool { + return func(_ winner) bool { count++ return count == boardsNum diff --git a/internal/puzzles/solutions/2021/day05/solution_test.go b/internal/puzzles/solutions/2021/day05/solution_test.go index 1dc56ce2..0c6bf15a 100644 --- a/internal/puzzles/solutions/2021/day05/solution_test.go +++ b/internal/puzzles/solutions/2021/day05/solution_test.go @@ -207,6 +207,7 @@ func Test_parseCoordinates(t *testing.T) { if !tt.wantErr(t, err, fmt.Sprintf("parseCoordinates(%v)", tt.args.s)) { return } + assert.Equalf(t, tt.want, got, "parseCoordinates(%v)", tt.args.s) }) } @@ -247,6 +248,7 @@ func Test_getLines(t *testing.T) { if !tt.wantErr(t, err, fmt.Sprintf("getLines(%v)", tt.args.input)) { return } + assert.Equalf(t, tt.want, got, "getLines(%v)", tt.args.input) }) } diff --git a/internal/puzzles/solutions/2021/day07/solution.go b/internal/puzzles/solutions/2021/day07/solution.go index f1f28f16..b1faed8a 100644 --- a/internal/puzzles/solutions/2021/day07/solution.go +++ b/internal/puzzles/solutions/2021/day07/solution.go @@ -77,19 +77,19 @@ func makeMatrix(crabs []int) [][]int { cnum := len(crabs) - max := crabs[cnum-1] + maxC := crabs[cnum-1] matrix := make([][]int, cnum+header) // matrix[i][j]. - // i - crabs; j - all positions from 0 to max + // i - crabs; j - all positions from 0 to maxC for i := 0; i < cnum+header; i++ { - matrix[i] = make([]int, max+header+1) + matrix[i] = make([]int, maxC+header+1) if i == 0 { matrix[i][0] = undef - for j := 1; j <= max+header; j++ { + for j := 1; j <= maxC+header; j++ { matrix[i][j] = j - 1 } @@ -136,6 +136,7 @@ func part1Cost(p int) int { return p } +//nolint:mnd // Formula is not a magic number. func part2Cost(p int) int { // formula a_{n}=a_{1}+(n-1)d an := 1 + 1*(p-1) @@ -164,7 +165,7 @@ func (s swarm) minDistanceCost() int { } func minDistanceCost(matrix [][]int) int { - var min int + var minC int ilen := len(matrix) jlen := len(matrix[0]) @@ -177,13 +178,13 @@ func minDistanceCost(matrix [][]int) int { } if j == 1 { - min = f + minC = f } - if f < min { - min = f + if f < minC { + minC = f } } - return min + return minC } diff --git a/internal/puzzles/solutions/2022/day01/solution.go b/internal/puzzles/solutions/2022/day01/solution.go index 20ae4fce..e14bb677 100644 --- a/internal/puzzles/solutions/2022/day01/solution.go +++ b/internal/puzzles/solutions/2022/day01/solution.go @@ -130,23 +130,23 @@ func (e elves) String() string { } func (e elves) maxTotalCalories() int { - var max int + var maxC int for _, el := range e { - if max == 0 { - max = el.totalCalories() + if maxC == 0 { + maxC = el.totalCalories() continue } c := el.totalCalories() - if c > max { - max = c + if c > maxC { + maxC = c } } - return max + return maxC } func (e elves) backupSnackCalc() int { diff --git a/internal/puzzles/solutions/2023/day01/solution.go b/internal/puzzles/solutions/2023/day01/solution.go index 52405f94..669e31c0 100644 --- a/internal/puzzles/solutions/2023/day01/solution.go +++ b/internal/puzzles/solutions/2023/day01/solution.go @@ -56,6 +56,7 @@ const ( nine = "nine" ) +//nolint:mnd // False positive. var digitsDict = map[string]int{ one: 1, two: 2, diff --git a/internal/puzzles/solver_test.go b/internal/puzzles/solver_test.go index 0f9b0db8..a02c9eb1 100644 --- a/internal/puzzles/solver_test.go +++ b/internal/puzzles/solver_test.go @@ -195,8 +195,6 @@ func TestRun(t *testing.T) { } for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { got, err := puzzles.Solve(tt.args.solver, tt.args.input) if tt.wantErr { diff --git a/scripts/linting/golangci-sonar.sh b/scripts/linting/golangci-sonar.sh index e756a3ac..a345acc1 100755 --- a/scripts/linting/golangci-sonar.sh +++ b/scripts/linting/golangci-sonar.sh @@ -15,6 +15,6 @@ checkInstalled golangci-lint echo "Linting..." -golangci-lint run --config .golangci.yml >linters.out +golangci-lint run --config .golangci.yml echo "${SCRIPT_NAME} done." diff --git a/sonar-project.properties b/sonar-project.properties index 9986baad..6257e477 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -28,6 +28,6 @@ sonar.links.issue=https://github.com/obalunenko/advent-of-code/issues # Properties specific to Go # ===================================================== -sonar.go.golangci-lint.reportPaths=linters.out +sonar.go.golangci-lint.reportPaths=linters-report.xml sonar.go.tests.reportPaths=tests-report.json sonar.go.coverage.reportPaths=coverage/full.cov