Important
Requires Go 1.26 or later (raised from 1.25). Despite the patch version, this release changes linter behavior in ways that can turn a passing build red. Read the notes below before upgrading CI.
Two bugs fixed, both of which caused the linter to fail open — silently checking less than you thought it was.
Type aliases were silently skipped
derefNamed and isPointer type-switched on *types.Named / *types.Pointer with no types.Unalias. Since gotypesalias=1 became the default in Go 1.23, go/types returns a *types.Alias for any aliased type, so both fell straight through:
//enumstruct:decl
type Union struct { A *int; B *string; C *bool }
type ValueAlias = Union
func check(u ValueAlias) {
switch { // entire switch skipped — no diagnostic, ever
case u.A != nil:
case u.B != nil: // missing case C never reported
}
}A union reached through an alias lost all exhaustiveness checking, with no warning. Separately, a field declared with a pointer alias (type IntPtr = *int) was reported as "not a pointer type" and dropped from the exported fact.
Upgrade impact: switches over alias-typed values are now checked, so new diagnostics may appear in code that previously passed.
.enumstruct.yml was parsed by a stub, not a YAML library
vendor/github.com/goccy/go-yaml/ contained a single hand-written 212-line file rather than the library. go.mod declared the dependency and config.go imported it, but go.sum had no hashes — the module was never downloaded. The stub hardcoded the four config key names in a switch; it only looked generic.
Valid YAML that it silently got wrong — wrong value, no error:
| Input | Was | Now |
|---|---|---|
exclude_fields: at 4-space indent |
map[] — empty |
parsed correctly |
exclude_fields: {"p.T": ["A"]} (flow) |
map[] — empty |
parsed correctly |
anchor/alias *d |
literal "*d" |
resolved |
folded scalar default_mode: > |
">" |
folded text |
types: 42, unclosed [ |
accepted silently | error |
The indentation case is the likeliest to have bitten: the stub required the type key at exactly two-space indent, so ordinary 4-space YAML produced an empty map.
Upgrade impact: if your config used any of the above, it is now actually being applied. Diagnostics may move in either direction — a previously-ignored exclude_fields will now suppress, a previously-ignored types entry will now start checking.
Breaking: ignore-field directive spacing
Directives are now parsed with go/ast.ParseDirective. //enumstruct:ignore-field previously accepted a leading space (// enumstruct:ignore-field X) because it trimmed after stripping //, while :decl and :ignore did not.
All three now follow the standard directive syntax, which has no space. If you used the spaced form, that field is no longer excluded and will start being reported. Remove the space:
// enumstruct:ignore-field Legacy // no longer works
//enumstruct:ignore-field Legacy // correctAlso
- Config parsing has test coverage for the first time (
pkg/enumstruct/config_test.go) vendor/now matches canonicalgo mod vendoroutput- CI workflow added
Full changelog: v0.1.1...v0.1.2