Skip to content

Latest commit

 

History

885 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gogenfilter

Detect and filter auto-generated Go code — fast, zero-config, table-driven.

Go Reference CI

License: MIT

Documentation · API Reference


A Go library for detecting and filtering auto-generated code files. Built for linters, static analysis tools, and CI pipelines that need to skip generated output — not fight it.

Why gogenfilter?

Your linter shouldn't waste time on files it didn't write. Generated code from sqlc, protobuf, templ, mockgen, and friends clutters golangci-lint output, slows down analysis, and creates false positives.

gogenfilter solves this with a three-phase detection engine that catches generated files fast — filename first (zero I/O), then config-aware parsing for sqlc (parses sqlc.yaml), content last (reads the file). No regex hacking. No .golangci.yml tuning. Just clean separation.

Supported Generators

Tool Detection
sqlc *.sql.go suffix + content
templ _templ.go suffix + content
go-enum _enum.go suffix + content
protobuf .pb.go, _grpc.pb.go suffix + content
oapi-codegen Content marker
deepcopy-gen zz_generated.* prefix + .go suffix + content
wire wire_gen.go suffix + content
moq _moq.go, _moq_test.go suffix + content
mockgen _mock.go suffix + content
stringer Content marker
mockery mock_ prefix + content
ent Content marker
gqlgen Content marker
easyjson _easyjson.go suffix + content
msgp Content marker
counterfeiter fake_ prefix + content
go-swagger Content marker
Generic fallback Any // Code generated by comment

Install

go get github.com/LarsArtmann/gogenfilter/v3

Quick Start

package main

import (
    "fmt"
    "log"

    "github.com/LarsArtmann/gogenfilter/v3"
)

func main() {
    opts, err := gogenfilter.WithFilterOptions(gogenfilter.FilterAll)
    if err != nil {
        log.Fatal(err)
    }

    f, err := gogenfilter.NewFilter(opts)
    if err != nil {
        log.Fatal(err)
    }

    // Batch filter multiple files
    paths := []string{"db/models.go", "api/user.pb.go", "handler.go"}
    results, err := f.FilterPaths(paths)
    if err != nil {
        log.Fatal(err)
    }

    for i, filtered := range results {
        if filtered {
            fmt.Println("skipping generated:", paths[i])
        }
    }
}

Configuration

NewFilter accepts functional options. Note that WithFilterOptions returns (FilterConfig, error) — check the error before passing to NewFilter:

// Filter all known generated code
opts, _ := gogenfilter.WithFilterOptions(gogenfilter.FilterAll)
f, _ := gogenfilter.NewFilter(opts)

// Filter specific generators only
opts, _ = gogenfilter.WithFilterOptions(gogenfilter.FilterSQLC, gogenfilter.FilterTempl)
f, _ = gogenfilter.NewFilter(opts)

// Include/exclude patterns with ** glob support
opts, _ = gogenfilter.WithFilterOptions(gogenfilter.FilterAll)
f, _ = gogenfilter.NewFilter(
    opts,
    gogenfilter.WithIncludePatterns("pkg/**", "internal/*.go"),
    gogenfilter.WithExcludePatterns("**/*.pb.go", "mocks/*"),
)

// Pluggable filesystem for testing
opts, _ = gogenfilter.WithFilterOptions(gogenfilter.FilterAll)
f, _ = gogenfilter.NewFilter(opts, gogenfilter.WithFS(myFS))

// Disabled — passes everything through
f, _ := gogenfilter.NewFilter()

Filter Options

Option Detection
FilterSQLC *.sql.go suffix + content
FilterTempl _templ.go suffix + content
FilterGoEnum _enum.go suffix + content
FilterProtobuf .pb.go, _grpc.pb.go suffix + content
FilterOapi Content marker
FilterDeepcopy zz_generated.* prefix + .go suffix + content
FilterWire wire_gen.go suffix + content
FilterMoq _moq.go, _moq_test.go suffix + content
FilterMockgen _mock.go suffix + content
FilterStringer Content marker
FilterMockery mock_ prefix + content
FilterEnt Content marker
FilterGqlgen Content marker
FilterEasyjson _easyjson.go suffix + content
FilterMsgp Content marker
FilterCounterfeiter fake_ prefix + content
FilterGoSwagger Content marker
FilterGeneric Any // Code generated by comment
FilterAll Enables all of the above

Pattern Matching

Include and exclude patterns support standard glob syntax:

Pattern Meaning
* Any sequence of non-separator characters (single segment)
** Zero or more complete path segments (crosses /)

Rules:

  • Include patterns restrict scope — only matching files are checked. If none are set, all files are considered.
  • Exclude patterns broaden scope — matching files are always skipped, regardless of detection.
  • Patterns without / match the filename only: *.pb.go matches any/path/user.pb.go
  • Patterns with / match the full path: internal/*.go matches internal/handler.go
f, _ := gogenfilter.NewFilter(
    gogenfilter.WithIncludePatterns("pkg/**"),
    gogenfilter.WithExcludePatterns("**/*.pb.go"),
)

Low-Level Detection API

Skip the Filter struct and call detection functions directly:

// Filename + content (two-phase)

gogenfilter.IsSQLCGenerated("db/models.go", content)
gogenfilter.IsTemplGenerated("page_templ.go", content)
gogenfilter.IsProtobufGenerated("user.pb.go", content)
gogenfilter.IsMockeryGenerated("mock_service.go", content)

// Combined detection with variadic options (no I/O — caller provides content)
reason := gogenfilter.DetectReason("file.go", content,
    gogenfilter.FilterSQLC,
    gogenfilter.FilterGeneric,
)
// reason == gogenfilter.ReasonSQLC or gogenfilter.ReasonNotFiltered

// Two-phase detection in one call (reads file from filesystem)
reason := gogenfilter.DetectReasonFile("file.go", gogenfilter.FilterSQLC)
reason, err := gogenfilter.DetectReasonFileFS(fsys, "file.go", gogenfilter.FilterAll)

// From an io.Reader
reason, err := gogenfilter.DetectReasonReader("file.go", reader,
    gogenfilter.FilterSQLC,
)

// Detailed result with trace info
opts, _ := gogenfilter.WithFilterOptions(gogenfilter.FilterAll)
f, _ := gogenfilter.NewFilter(opts, gogenfilter.WithFS(myFS))
result, err := f.FilterDetailed("db/models.go")
fmt.Printf("filtered=%v reason=%s trace=%s\n",
    result.Filtered, result.Reason, result.Trace)

// Filter with pre-read content — avoids double I/O
filtered, err := f.FilterWithContent("db/models.go", content)
result, err := f.FilterDetailedWithContent("db/models.go", content)

// Lazy content return — filter reads content only when needed, returns it for reuse
result, content, err := f.FilterDetailedAndContent("db/models.go")

Filter API Reference

opts, _ := gogenfilter.WithFilterOptions(gogenfilter.FilterAll)
f, _ := gogenfilter.NewFilter(opts)

filtered, err := f.Filter("db/models.go")           // (bool, error)
result, err  := f.FilterDetailed("db/models.go")    // (FilterResult, error)
results, err := f.FilterPaths(paths)                 // ([]bool, error)
detailed, err := f.FilterPathsDetailed(paths)        // ([]FilterResult, error)
filtered, err = f.FilterWithContent("file.go", data) // (bool, error) — avoids double I/O
result, err   = f.FilterDetailedWithContent("file.go", data) // (FilterResult, error)
result, content, err = f.FilterDetailedAndContent("file.go") // (FilterResult, []byte, error) — lazy read + content return

f.IsEnabled()           // bool
f.FilterReasons()       // []FilterReason
f.String()              // human-readable debug state

Error Handling

All errors carry structured codes and support errors.Is matching:

root, err := gogenfilter.FindProjectRoot(
    "/some/path",
    []string{"go.mod"},
)
if err != nil {
    // Check by sentinel error
    if errors.Is(err, gogenfilter.ErrProjectRootNotFound) {
        // handle not found
    }

    // Get the structured error code
    fmt.Println(err.ErrorCode()) // project_root_not_found
}

SQLC Config Discovery

Find sqlc configuration files and extract output directories:

// Find sqlc.yaml files in the project
configs, err := gogenfilter.FindSQLCConfigs([]string{"."})       // map[string]string
configs, err = gogenfilter.FindSQLCConfigsFS(fsys, []string{"."})

// Extract output directories from configs
dirs, err := gogenfilter.GetSQLOutputDirs([]string{"."})          // []string
dirs, err = gogenfilter.GetSQLOutputDirsFS(fsys, []string{"."})

// Find the project root by walking up for marker files
root, err := gogenfilter.FindProjectRoot(
    ".",
    []string{"go.mod", "sqlc.yaml"},
)

Project Scanning

Scan an entire project for generated files:

result, err := gogenfilter.ScanProject(os.DirFS("."))
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Scanned %d files, found %d generated\n", result.ScannedFiles, len(result.Files))
for _, gen := range result.Generators {
    fmt.Printf("  %s: %d files\n", gen, len(result.ByGenerator[gen]))
}

// Get exclusion patterns for linter configs
for _, excl := range result.Exclusions {
    fmt.Printf("Pattern: %s (%s)\n", excl.Pattern, excl.Reason)
}

Design Decisions

  • Three-phase detection — Filename checks are free. Config-aware sqlc parsing (one-time walk, cached). Content checks only run when earlier phases don't match. Fast by default.
  • Table-driven detectors — All 18 generators are defined in a single []detector table. Adding a new generator is one struct literal.
  • Immutable Filter — NewFilter returns a fully constructed, thread-safe Filter. No mutating methods.
  • fs.FS abstraction — Test with fstest.MapFS, run with os.DirFS. No filesystem coupling.
  • Derived constants — AllFilterOptions(), AllFilterReasons(), AllGeneratorOptions() are all derived from the detector table. Nothing to forget.

API Stability

This library is at v3 and follows Go module versioning. Standard Go compatibility guarantees apply — no breaking changes without a major version bump. The core Filter / DetectReason API is stable.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. See RELEASING.md for the release process if you need to cut a release.

License

MIT © Lars Artmann

About

Detect and filter auto-generated Go code — fast, zero-config, table-driven. Supports sqlc, protobuf, templ, mockgen, wire, stringer, and more.

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages