Skip to content

Commit

Permalink
Move package to internal; minor refactoring; add tests
Browse files Browse the repository at this point in the history
Signed-off-by: Oliver Eikemeier <[email protected]>
  • Loading branch information
eikemeier committed Feb 9, 2025
1 parent b596aae commit 298450d
Show file tree
Hide file tree
Showing 37 changed files with 991 additions and 401 deletions.
16 changes: 10 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ name: Test
- main
jobs:
test:
name: Test on Go ${{ matrix.go }}
name: Test on Go ${{ matrix.go-version }}
permissions:
checks: write
contents: read
Expand All @@ -18,26 +18,30 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
go: ["1.23.3", "1.22.9"]
go-version: ["1.24.0-rc.3", "1.23.6", "1.22.12"]
include:
- go-version: "1.23.6"
update-coverage: true
env:
GOTOOLCHAIN: local
steps:
- name: ✔ Check out
uses: actions/checkout@v4
- name: 🐹 Set up Go ${{ matrix.go }}
- name: 🐹 Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
go-version: ${{ matrix.go-version }}
- name: 🧸 golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.62.0
version: v1.63.4
- name: 🔨 Test
run: |
go get -C ./pkg/analyzer/testdata golang.org/x/exp/errors
go test -coverprofile=cover.out ./...
- name: 🧑🏻‍💻 codecov
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
if: ${{ matrix.update-coverage }}
with:
files: ./cover.out
token: ${{ secrets.CODECOV_TOKEN }}
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module fillmore-labs.com/zerolint

go 1.22.9
go 1.22.0

toolchain go1.23.3
toolchain go1.23.6

require golang.org/x/tools v0.27.0
require golang.org/x/tools v0.29.0

require (
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/sync v0.11.0 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
24 changes: 9 additions & 15 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package analyzer

import (
"fillmore-labs.com/zerolint/pkg/visitor"
"fillmore-labs.com/zerolint/pkg/internal/excludes"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
)
Expand Down Expand Up @@ -59,24 +59,18 @@ var (
Generated bool //nolint:gochecknoglobals
)

// Run applies the analyzer to a package.
// run applies the analyzer to a package.
func run(pass *analysis.Pass) (any, error) {
// Read the list of excluded types from the file specified by the "excluded" flag.
excludes, err := ReadExcludes(Excludes)
ex, err := excludes.ReadExcludes(osFS{}, Excludes)
if err != nil {
return nil, err
}

v := visitor.Run{
Visitor: visitor.Visitor{
Pass: pass,
Excludes: excludes,
},
ZeroTrace: ZeroTrace,
Basic: Basic,
Generated: Generated,
}
v.Run()

return any(nil), nil
return NewRun(
WithExcludes(ex),
WithZeroTrace(ZeroTrace),
WithBasic(Basic),
WithGenerated(Generated),
)(pass)
}
14 changes: 11 additions & 3 deletions pkg/analyzer/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,18 @@ func TestAnalyzer(t *testing.T) { //nolint:paralleltest
dir := analysistest.TestData()
a := analyzer.Analyzer

analyzer.Basic = true
analysistest.RunWithSuggestedFixes(t, dir, a, "go.test/basic")

analyzer.Basic = false
analyzer.Excludes = dir + "/excluded.txt"

analysistest.RunWithSuggestedFixes(t, dir, a, "go.test/a")
}

func TestAnalyzerBasic(t *testing.T) { //nolint:paralleltest
dir := analysistest.TestData()
a := analyzer.Analyzer

analyzer.Basic = true
analyzer.Excludes = ""

analysistest.RunWithSuggestedFixes(t, dir, a, "go.test/basic")
}
30 changes: 30 additions & 0 deletions pkg/analyzer/osfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2024 Oliver Eikemeier. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

package analyzer

import (
"io/fs"
"os"
)

type osFS struct{}

var _ fs.FS = osFS{}

func (osFS) Open(name string) (fs.File, error) {
return os.Open(name)
}
134 changes: 134 additions & 0 deletions pkg/analyzer/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright 2024 Oliver Eikemeier. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

package analyzer

import (
"log"

"fillmore-labs.com/zerolint/pkg/internal/set"
"fillmore-labs.com/zerolint/pkg/internal/visitor"
"golang.org/x/tools/go/analysis"
)

// NewRun returns a configurable function for the Run field of [Analyzer].
func NewRun(opts ...Option) func(*analysis.Pass) (any, error) {
option := options{
logger: log.Default(),
}
for _, opt := range opts {
opt.apply(&option)
}

return func(pass *analysis.Pass) (any, error) {
visitor.Run(
option.logger,
visitor.Visitor{
Pass: pass,
Excludes: option.excludes,
},
option.zeroTrace,
option.basic,
option.generated,
)

return any(nil), nil
}
}

// options defines configurable parameters for the linter.
type options struct {
logger *log.Logger
excludes set.Set[string]
zeroTrace bool
basic bool
generated bool
}

// Option defines configurations for [NewRun].
type Option interface {
apply(opts *options)
}

// WithLogger is an [Option] to configure the used logger.
func WithLogger(logger *log.Logger) Option { //nolint:ireturn
return loggerOption{logger: logger}
}

type loggerOption struct {
logger *log.Logger
}

func (o loggerOption) apply(opts *options) {
opts.logger = o.logger
}

// WithExcludes is an [Option] to configure the excluded types.
func WithExcludes(excludes []string) Option { //nolint:ireturn
return excludesOption{excludes: excludes}
}

type excludesOption struct {
excludes []string
}

func (o excludesOption) apply(opts *options) {
if opts.excludes == nil {
opts.excludes = set.New[string]()
}
for _, exclude := range o.excludes {
opts.excludes.Insert(exclude)
}
}

// WithZeroTrace is an [Option] to configure tracing of zero sized types.
func WithZeroTrace(zeroTrace bool) Option { //nolint:ireturn
return zeroTraceOption{zeroTrace: zeroTrace}
}

type zeroTraceOption struct {
zeroTrace bool
}

func (o zeroTraceOption) apply(opts *options) {
opts.zeroTrace = o.zeroTrace
}

// WithBasic is an [Option] to configure only basic linting.
func WithBasic(basic bool) Option { //nolint:ireturn
return basicOption{basic: basic}
}

type basicOption struct {
basic bool
}

func (o basicOption) apply(opts *options) {
opts.basic = o.basic
}

// WithGenerated is an [Option] to configure linting of generated files.
func WithGenerated(generated bool) Option { //nolint:ireturn
return generatedOption{generated: generated}
}

type generatedOption struct {
generated bool
}

func (o generatedOption) apply(opts *options) {
opts.generated = o.generated
}
61 changes: 61 additions & 0 deletions pkg/analyzer/testdata/a/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2024 Oliver Eikemeier. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

package a

import (
"errors"
"fmt"

xerrors "golang.org/x/exp/errors"
)

type empty struct{}

type myErrors struct{}

func (myErrors) Is(_, _ error) bool {
return false
}

var myErrs = myErrors{}

func IgnoreErrors() {
if errors.Is(ErrOne, nil) {
fmt.Println("nil")
}

var oneErr *typedError[int] // want "pointer to zero-sized type"
if errors.As(ErrOne, &oneErr) {
fmt.Println("ErrOne is typedError[int]")
}

func() {
errors := myErrs
if errors.Is(ErrOne, ErrTwo) {
fmt.Println("one is two")
}
}()

if xerrors.Is(func() error { // want "comparison of pointer to zero-size variable"
return ErrOne
}(), ErrTwo) {
fmt.Println("equal")
}

var err *typedError[int] // want "pointer to zero-sized type"
_ = errors.As(ErrOne, &err)
}
Loading

0 comments on commit 298450d

Please sign in to comment.