Some fixes for staticcheck (#2006)

* Implement some staticcheck fixes

* make fmt

* more

* more staticcheck
This commit is contained in:
John Kerl 2026-03-03 09:27:03 -05:00 committed by GitHub
parent 1efadc9ea8
commit 761b46219c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 86 additions and 50 deletions

View file

@ -4,6 +4,30 @@
Miller is a command-line data processing tool for working with CSV, TSV, JSON, and other data formats. It's written in Go (v1.18+) and provides SQL-like operations on data.
## Initial Setup
### Setting Up staticcheck
The `make staticcheck` target requires the staticcheck tool. To set it up:
```bash
go install honnef.co/go/tools/cmd/staticcheck@latest
```
This installs staticcheck to `~/go/bin/` (the default Go binaries directory). For `make staticcheck` to work, you need `~/go/bin` in your `PATH`.
**Add to your shell profile** (`.bashrc`, `.zshrc`, or equivalent):
```bash
export PATH="$PATH:$HOME/go/bin"
```
**Verify the installation:**
```bash
staticcheck -version
```
If this works, you can use `make staticcheck` without any further setup.
## Build & Test
### Building
@ -23,7 +47,7 @@ make bench # Run benchmarks
### Code Quality
```bash
make fmt # Format code with go fmt
make staticcheck # Run static analysis (requires: go install honnef.co/go/tools/cmd/staticcheck@latest)
make staticcheck # Run static analysis (see Initial Setup section above)
```
### Full Developer Workflow

View file

@ -307,32 +307,31 @@ func (r *Reader) readRecord(dst []string) ([]string, error) {
// Read line (automatically skipping past empty lines and any comments).
var line []byte
var errRead error
for errRead == nil {
line, errRead = r.readLine()
// MILLER-SPECIFIC UPDATE: DO NOT DO THIS
// if r.Comment != 0 && nextRune(line) == r.Comment {
// line = nil
// continue // Skip comment lines
// }
line, errRead = r.readLine()
// MILLER-SPECIFIC UPDATE: DO NOT DO THIS
// if errRead == nil && len(line) == lengthNL(line) {
// line = nil
// continue // Skip empty lines
// }
// MILLER-SPECIFIC UPDATE: DO NOT DO THIS
// if r.Comment != 0 && nextRune(line) == r.Comment {
// line = nil
// continue // Skip comment lines
// }
// MILLER-SPECIFIC UPDATE: If the line starts with the comment character,
// don't attempt to CSV-parse it -- just hand it back as a single field.
// This allows two things:
// * User comments get passed through as intended, without being reformatted;
// * Users can do things like `# a"b` in their comments without getting an
// imbalanced-double-quote error.
if r.Comment != 0 && nextRune(line) == r.Comment {
return []string{string(line)}, nil
}
break
// MILLER-SPECIFIC UPDATE: DO NOT DO THIS
// if errRead == nil && len(line) == lengthNL(line) {
// line = nil
// continue // Skip empty lines
// }
// MILLER-SPECIFIC UPDATE: If the line starts with the comment character,
// don't attempt to CSV-parse it -- just hand it back as a single field.
// This allows two things:
// * User comments get passed through as intended, without being reformatted;
// * Users can do things like `# a"b` in their comments without getting an
// imbalanced-double-quote error.
if r.Comment != 0 && nextRune(line) == r.Comment {
return []string{string(line)}, nil
}
if errRead == io.EOF {
return nil, errRead
}

View file

@ -41,7 +41,7 @@ func NewFixedWidthSplitter(spec, referenceRow string) (*fixedWidthSplitter, erro
} else if spec == "right-align-multi-word" {
indexes = parseRightAlign(referenceRow, true)
} else {
return nil, fmt.Errorf("Unknown spec: %v", spec)
return nil, fmt.Errorf("unknown spec: %v", spec)
}
return &fixedWidthSplitter{indexes: indexes}, nil

View file

@ -229,7 +229,7 @@ func (reader *RecordReaderPprintFixedSplit) getRecords(
} else {
if !reader.readerOptions.AllowRaggedCSVInput && len(reader.headerStrings) != len(fields) {
err := fmt.Errorf(
"Fixed-width header/data length mismatch %d != %d at filename %s line %d",
"fixed-width header/data length mismatch %d != %d at filename %s line %d",
len(reader.headerStrings), len(fields), filename, reader.inputLineNumber,
)
errorChannel <- err

View file

@ -151,7 +151,7 @@ func (mlrmap *Mlrmap) CopyUnflattened(
// Check for "" in any of the split pieces; treat the field as terminal if so.
legitDots := true
for i, _ := range arrayval {
for i := range arrayval {
piece := arrayval[i].String()
if piece == "" {
legitDots = false

View file

@ -338,7 +338,7 @@ func putIndexedOnArray(
return errors.New("zero indices are not supported. Indices are 1-up")
}
if mindex.intf.(int64) < 0 {
return errors.New("Cannot use negative indices to auto-lengthen arrays")
return errors.New("cannot use negative indices to auto-lengthen arrays")
}
// Array is [a,b,c] with mindices 1,2,3. Length is 3. Zindices are 0,1,2.
// Given mindex is 4.
@ -371,7 +371,7 @@ func putIndexedOnArray(
} else if mindex.intf.(int64) == 0 {
return errors.New("zero indices are not supported. Indices are 1-up")
} else if mindex.intf.(int64) < 0 {
return errors.New("Cannot use negative indices to auto-lengthen arrays")
return errors.New("cannot use negative indices to auto-lengthen arrays")
} else {
// Already allocated but needs to be longer
LengthenMlrvalArray(baseArray, int(mindex.intf.(int64)))

View file

@ -27,7 +27,7 @@ const (
JSON_MULTILINE = 2
)
var prematureEofError error = errors.New("JSON parser: unexpected premature EOF")
var errPrematureEOF = errors.New("JSON parser: unexpected premature EOF")
// The JSON decoder (https://golang.org/pkg/encoding/json/#Decoder) is quite
// nice. What we can have is:
@ -192,7 +192,7 @@ func MlrvalDecodeFromJSON(decoder *json.Decoder) (
for decoder.More() {
element, eof, err := MlrvalDecodeFromJSON(decoder)
if eof {
return nil, false, prematureEofError
return nil, false, errPrematureEOF
}
if err != nil {
return nil, false, err
@ -205,7 +205,7 @@ func MlrvalDecodeFromJSON(decoder *json.Decoder) (
for decoder.More() {
key, eof, err := MlrvalDecodeFromJSON(decoder)
if eof {
return nil, false, prematureEofError
return nil, false, errPrematureEOF
}
if err != nil {
return nil, false, err
@ -219,7 +219,7 @@ func MlrvalDecodeFromJSON(decoder *json.Decoder) (
value, eof, err := MlrvalDecodeFromJSON(decoder)
if eof {
return nil, false, prematureEofError
return nil, false, errPrematureEOF
}
if err != nil {
return nil, false, err
@ -296,7 +296,7 @@ func (mv *Mlrval) marshalJSONAux(
case MT_DIM: // MT_DIM is one past the last valid type
return "", fmt.Errorf("internal coding error detected")
}
return "", fmt.Errorf("Internal coding error detected")
return "", fmt.Errorf("internal coding error detected")
}
// TYPE-SPECIFIC MARSHALERS

View file

@ -69,7 +69,7 @@ type MultiOutputHandlerManager struct {
lruNodes map[string]*lruNode // filename -> node (file mode only)
lruHead *lruNode // MRU
lruTail *lruNode // LRU
evictedFilenames map[string]bool // filenames we closed; re-open with append
evictedFilenames map[string]bool // filenames we closed; re-open with append
}
func NewFileOutputHandlerManager(

View file

@ -52,7 +52,7 @@ func dcfValueString(mv *mlrval.Mlrval) string {
}
if mv.IsArray() {
arr := mv.GetArray()
if arr == nil || len(arr) == 0 {
if len(arr) == 0 {
return ""
}
parts := make([]string, 0, len(arr))

View file

@ -123,7 +123,7 @@ func (t *Token) Int64Value() (int64, error) {
func (t *Token) UTF8Rune() (rune, error) {
r, _ := utf8.DecodeRune(t.Lit)
if r == utf8.RuneError {
err := fmt.Errorf("Invalid rune")
err := fmt.Errorf("invalid rune")
return r, err
}
return r, nil

View file

@ -58,8 +58,9 @@ func transformerCheckParseCLI(
transformerCheckUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameCheck, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameCheck, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -54,8 +54,9 @@ func transformerGroupByParseCLI(
transformerGroupByUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameGroupBy, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameGroupBy, "option \"%s\" not recognized", opt)
}
// Get the group-by field names from the command line

View file

@ -54,8 +54,9 @@ func transformerGroupLikeParseCLI(
transformerGroupLikeUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameGroupLike, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameGroupLike, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -58,8 +58,9 @@ func transformerLabelParseCLI(
transformerLabelUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameLabel, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameLabel, "option \"%s\" not recognized", opt)
}
// Get the label field names from the command line

View file

@ -56,8 +56,9 @@ func transformerLatin1ToUTF8ParseCLI(
transformerLatin1ToUTF8Usage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameLatin1ToUTF8, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameLatin1ToUTF8, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -53,9 +53,10 @@ func transformerNothingParseCLI(
if opt == "-h" || opt == "--help" {
transformerNothingUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
transformerNothingUsage(os.Stderr)
return nil, fmt.Errorf("%s %s: option \"%s\" not recognized", "mlr", verbNameNothing, opt)
}
transformerNothingUsage(os.Stderr)
return nil, fmt.Errorf("%s %s: option \"%s\" not recognized", "mlr", verbNameNothing, opt)
}
*pargi = argi

View file

@ -55,8 +55,9 @@ func transformerRegularizeParseCLI(
transformerRegularizeUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameRegularize, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameRegularize, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -54,8 +54,9 @@ func transformerRemoveEmptyColumnsParseCLI(
transformerRemoveEmptyColumnsUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameRemoveEmptyColumns, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameRemoveEmptyColumns, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -57,8 +57,9 @@ func transformerSec2GMTDateParseCLI(
transformerSec2GMTDateUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameSec2GMTDate, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameSec2GMTDate, "option \"%s\" not recognized", opt)
}
if argi >= argc {

View file

@ -57,8 +57,9 @@ func transformerShuffleParseCLI(
transformerShuffleUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameShuffle, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameShuffle, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -54,8 +54,9 @@ func transformerSkipTrivialRecordsParseCLI(
transformerSkipTrivialRecordsUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameSkipTrivialRecords, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameSkipTrivialRecords, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -53,8 +53,9 @@ func transformerTacParseCLI(
transformerTacUsage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameTac, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameTac, "option \"%s\" not recognized", opt)
}
*pargi = argi

View file

@ -56,8 +56,9 @@ func transformerUTF8ToLatin1ParseCLI(
transformerUTF8ToLatin1Usage(os.Stdout)
return nil, cli.ErrHelpRequested
} else {
return nil, cli.VerbErrorf(verbNameUTF8ToLatin1, "option \"%s\" not recognized", opt)
}
return nil, cli.VerbErrorf(verbNameUTF8ToLatin1, "option \"%s\" not recognized", opt)
}
*pargi = argi