Skip to content

Commit 9ba40fd

Browse files
jcrussellclaude
andcommitted
Fix all golangci-lint errors (17 issues resolved)
Resolved 9 errcheck, 3 staticcheck, and 5 unused code issues: - Add proper error handling for all file/resource close operations - Use defer functions with slog.Warn/Debug for cleanup errors - Remove deprecated lipgloss Copy() method calls - Remove unused TUI message types and color constants - Refactor generate loop to use closure for proper defer scoping - Replace if-else with switch in parser test for code clarity - Add explicit error ignoring for best-effort cleanup operations All tests pass and build succeeds. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent de7003d commit 9ba40fd

File tree

8 files changed

+70
-57
lines changed

8 files changed

+70
-57
lines changed

pkg/analysis/history.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@ func calculateDistances(cfg *config.Config, data *ccda.Data, encounters []ccda.E
210210
slog.Debug("added final return trip home", "distance_km", returnDistance)
211211
}
212212

213-
geocoder.SaveCache()
213+
if err := geocoder.SaveCache(); err != nil {
214+
slog.Debug("failed to save geocoding cache", "error", err)
215+
}
214216
return totalDistance
215217
}
216218

pkg/ccda/parser.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ func ExtractAndParse(zipPath string) (*Data, error) {
7676
if err != nil {
7777
return nil, fmt.Errorf("failed to open zip: %w", err)
7878
}
79-
defer r.Close()
79+
defer func() {
80+
if err := r.Close(); err != nil {
81+
slog.Warn("failed to close zip reader", "error", err)
82+
}
83+
}()
8084

8185
data := &Data{
8286
Encounters: []Encounter{},
@@ -110,7 +114,9 @@ func ExtractAndParse(zipPath string) (*Data, error) {
110114
}
111115

112116
fileBytes, err := io.ReadAll(rc)
113-
rc.Close()
117+
if closeErr := rc.Close(); closeErr != nil {
118+
slog.Warn("failed to close METADATA.xml", "error", closeErr)
119+
}
114120
if err != nil {
115121
slog.Error("error reading METADATA.xml", "error", err)
116122
continue
@@ -144,7 +150,9 @@ func ExtractAndParse(zipPath string) (*Data, error) {
144150

145151
// Read entire file content first to help with decryption issues
146152
fileBytes, err := io.ReadAll(rc)
147-
rc.Close()
153+
if closeErr := rc.Close(); closeErr != nil {
154+
slog.Warn("failed to close XML file", "name", f.Name, "error", closeErr)
155+
}
148156
if err != nil {
149157
slog.Error("error reading file", "name", f.Name, "error", err)
150158
continue

pkg/ccda/parser_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,9 +399,10 @@ func TestParseSingleFile_Vitals(t *testing.T) {
399399
// Find BP and weight
400400
var bp, weight *Vital
401401
for i := range data.Vitals {
402-
if data.Vitals[i].LOINCCode == "8480-6" {
402+
switch data.Vitals[i].LOINCCode {
403+
case "8480-6":
403404
bp = &data.Vitals[i]
404-
} else if data.Vitals[i].LOINCCode == "29463-7" {
405+
case "29463-7":
405406
weight = &data.Vitals[i]
406407
}
407408
}

pkg/cmd/generate/generate.go

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -181,33 +181,40 @@ func runGenerate(opts *GenerateOptions) error {
181181
filename := p.Filename()
182182
fmt.Printf("📝 Generating %s...\n", filename)
183183

184-
f, err := os.Create(filepath.Join(opts.OutputDir, filename))
185-
if err != nil {
186-
return err
187-
}
188-
defer f.Close()
184+
// Wrap in closure to ensure proper defer scoping in loop
185+
if err := func() error {
186+
f, err := os.Create(filepath.Join(opts.OutputDir, filename))
187+
if err != nil {
188+
return err
189+
}
190+
defer func() {
191+
if err := f.Close(); err != nil {
192+
slog.Warn("failed to close output file", "filename", filename, "error", err)
193+
}
194+
}()
189195

190-
// Clone the main layout and parse the specific page content
191-
pageTmpl, err := mainTmpl.Clone()
192-
if err != nil {
193-
return fmt.Errorf("failed to clone template: %w", err)
194-
}
195-
_, err = pageTmpl.New("content").Funcs(funcMap).Parse(p.Template())
196-
if err != nil {
197-
return fmt.Errorf("failed to parse page template: %w", err)
198-
}
196+
// Clone the main layout and parse the specific page content
197+
pageTmpl, err := mainTmpl.Clone()
198+
if err != nil {
199+
return fmt.Errorf("failed to clone template: %w", err)
200+
}
201+
_, err = pageTmpl.New("content").Funcs(funcMap).Parse(p.Template())
202+
if err != nil {
203+
return fmt.Errorf("failed to parse page template: %w", err)
204+
}
199205

200-
data := map[string]interface{}{
201-
"Title": p.Name(),
202-
"Pages": allPages,
203-
"CurrentPage": filename,
204-
"PageData": p.PrepareData(history),
205-
"FooterPrefix": footerPrefix,
206-
"FooterText": footerText,
207-
}
206+
data := map[string]interface{}{
207+
"Title": p.Name(),
208+
"Pages": allPages,
209+
"CurrentPage": filename,
210+
"PageData": p.PrepareData(history),
211+
"FooterPrefix": footerPrefix,
212+
"FooterText": footerText,
213+
}
208214

209-
if err := pageTmpl.Execute(f, data); err != nil {
210-
return err
215+
return pageTmpl.Execute(f, data)
216+
}(); err != nil {
217+
return fmt.Errorf("failed to generate %s: %w", filename, err)
211218
}
212219
}
213220

pkg/cmd/inspect/inspect.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/xml"
55
"fmt"
66
"io"
7+
"log/slog"
78
"os"
89
"os/exec"
910
"strings"
@@ -53,7 +54,11 @@ func runInspect(opts *InspectOptions) error {
5354
if err != nil {
5455
return fmt.Errorf("failed to open zip: %w", err)
5556
}
56-
defer r.Close()
57+
defer func() {
58+
if err := r.Close(); err != nil {
59+
slog.Warn("failed to close zip reader", "error", err)
60+
}
61+
}()
5762

5863
var output strings.Builder
5964

@@ -76,7 +81,9 @@ func runInspect(opts *InspectOptions) error {
7681

7782
// Read file content
7883
fileBytes, err := io.ReadAll(rc)
79-
rc.Close()
84+
if closeErr := rc.Close(); closeErr != nil {
85+
output.WriteString(fmt.Sprintf("Warning: failed to close file: %v\n", closeErr))
86+
}
8087
if err != nil {
8188
output.WriteString(fmt.Sprintf("Error reading file: %v\n\n", err))
8289
continue

pkg/geocode/geocode.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,11 @@ func (g *NominatimGeocoder) Geocode(address string) (*Coordinate, error) {
109109
if err != nil {
110110
return nil, fmt.Errorf("geocoding request failed: %w", err)
111111
}
112-
defer resp.Body.Close()
112+
defer func() {
113+
if err := resp.Body.Close(); err != nil {
114+
slog.Debug("failed to close HTTP response body", "error", err)
115+
}
116+
}()
113117

114118
if resp.StatusCode != http.StatusOK {
115119
return nil, fmt.Errorf("geocoding API returned status %d", resp.StatusCode)
@@ -221,7 +225,7 @@ func (g *NominatimGeocoder) SaveCache() error {
221225
}
222226

223227
if err := os.Rename(tempPath, g.cachePath); err != nil {
224-
os.Remove(tempPath) // Clean up temp file on error
228+
_ = os.Remove(tempPath) // Best-effort cleanup
225229
return fmt.Errorf("failed to rename cache file: %w", err)
226230
}
227231

pkg/tui/messages.go

Lines changed: 0 additions & 14 deletions
This file was deleted.

pkg/tui/styles.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ import (
77
// Color palette matching the HTML dashboard theme
88
var (
99
// Primary colors
10-
colorBlue = lipgloss.Color("#58a6ff")
11-
colorDarkBg = lipgloss.Color("#24292e")
12-
colorGray = lipgloss.Color("#586069")
13-
colorWhite = lipgloss.Color("#ffffff")
14-
colorGreen = lipgloss.Color("#2ea44f")
15-
colorOrange = lipgloss.Color("#fb8500")
16-
colorBorder = lipgloss.Color("#30363d")
10+
colorBlue = lipgloss.Color("#58a6ff")
11+
colorDarkBg = lipgloss.Color("#24292e")
12+
colorGray = lipgloss.Color("#586069")
13+
colorWhite = lipgloss.Color("#ffffff")
14+
colorBorder = lipgloss.Color("#30363d")
1715
)
1816

1917
// Header and navigation styles
@@ -27,11 +25,11 @@ var (
2725
TabStyle = lipgloss.NewStyle().
2826
Padding(0, 2)
2927

30-
ActiveTabStyle = TabStyle.Copy().
28+
ActiveTabStyle = TabStyle.
3129
Foreground(colorBlue).
3230
Bold(true)
3331

34-
InactiveTabStyle = TabStyle.Copy().
32+
InactiveTabStyle = TabStyle.
3533
Foreground(colorWhite)
3634
)
3735

0 commit comments

Comments
 (0)