Skip to content

refactor: go 1.26 modernize#178

Open
gjermundgaraba wants to merge 2 commits intobjarneo:mainfrom
gjermundgaraba:refactor/go-1.26-modernize
Open

refactor: go 1.26 modernize#178
gjermundgaraba wants to merge 2 commits intobjarneo:mainfrom
gjermundgaraba:refactor/go-1.26-modernize

Conversation

@gjermundgaraba
Copy link
Copy Markdown
Contributor

@gjermundgaraba gjermundgaraba commented Apr 9, 2026

This is pretty straight-forward: https://go.dev/blog/gofix

Summary by CodeRabbit

  • Chores
    • General modernization and internal optimizations across providers, playback, UI rendering, plugins, and tests for improved reliability and maintainability.
    • More consistent parsing and iteration logic for playlists, station lists, lyrics, and metadata to reduce edge-case glitches.
    • Cache persistence updated so playlist timestamp is consistently stored.
    • Minor stability improvements to plugin concurrency and UI scrolling/rendering behavior.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 441b8bc6-0392-46dd-a6e0-67abe77582b9

📥 Commits

Reviewing files that changed from the base of the PR and between 35af053 and bc0a3a7.

📒 Files selected for processing (4)
  • external/ytmusic/classify.go
  • luaplugin/api_fs.go
  • player/icy.go
  • ui/model/view.go

📝 Walkthrough

Walkthrough

Modernized code to use Go 1.22+ idioms and helper utilities: replaced slice-producing splits with iterator-based splitters, switched interface{}any, simplified clamping with min/max, used strings.Cut* helpers, adjusted closure capture and WaitGroup goroutine patterns, and small JSON/tag and import tweaks.

Changes

Cohort / File(s) Summary
SplitSeq replacements
cmd/playlist.go, lyrics/lyrics.go, ui/vis_classic_peak_test.go, external/local/provider.go, external/radio/favorites.go, external/radio/provider.go
Replaced strings.Split(..., "\n") with strings.SplitSeq(..., "\n") and converted loops from value-style (for _, v := range) to iterator-style (for v := range) — review iteration variable semantics and trimming/filtering logic.
any (interface{} → any) changes
ipc/protocol.go, ipc/protocol_test.go, ipc/server.go, ipc/server_test.go, main.go
Replaced interface{} with any in Dispatcher types and related tests/callbacks; check API surface and tests compile with new alias.
min/max clamping & small math simplifications
player/chained_ogg.go, player/player.go, player/speed.go, player/tap.go, resolve/m3u.go, ui/model/filebrowser.go, ui/model/keys.go, ui/model/keys_nav.go, ui/model/tick.go, ui/model/view.go, ui/model/view_helpers.go, ui/model/view_nav.go, ui/model/view_overlays.go, ui/vis_retro.go, external/ytmusic/provider.go, external/ytmusic/classify.go
Replaced multi-statement clamps/conditional bounds with min()/max() expressions; verify numeric edge cases and off-by-one behavior remain identical.
strings.Cut and suffix/prefix helpers*
luaplugin/luaplugin.go, player/icy.go, resolve/m3u.go
Replaced HasPrefix/TrimSuffix/Index* patterns with strings.CutSuffix, strings.CutPrefix, and strings.Cut to simplify parsing; validate parsing branches and fallback behavior.
WaitGroup.Go and goroutine patterns
external/ytmusic/provider.go, external/ytmusic/classify.go, luaplugin/luaplugin_test.go, luaplugin/luaplugin_test.go
Replaced manual wg.Add(1); go func(){ defer wg.Done(); ... }() with wg.Go(func(){ ... }); examine goroutine lifecycles and captured loop variables.
Closure capture changes
luaplugin/api_log.go, luaplugin/hooks.go
Removed per-iteration shadowing (e.g., x := x) before starting closures — review that closures now capture the intended per-iteration values.
Collection/util imports & usage
external/spotify/provider.go
Added slices import and replaced manual loop membership checks with slices.Contains — ensure import and behavior match existing accepted status codes.
JSON tag change (cache)
external/ytmusic/cache.go
ytCache.PlaylistsAt JSON tag removed omitempty so playlists_at is always emitted — check persisted cache read/write compatibility.
Loop-style refactors (for range N / index mechanics)
luaplugin/api_control.go, playlist/playlist_test.go, playlist/shuffle_repeat_test.go, ui/model/speed_controls_test.go, ui/model/view_state_test.go, player/speed.go, ui/vis_butterfly.go, ui/vis_classic_peak_test.go
Converted counted loops to for i := range N or for x := range n forms and adjusted inner loop index usage; review test expectations and rendering loops for unchanged semantics.
I/O/clamping simplifications
luaplugin/api_fs.go, player/icy.go
Replaced conditional slicing with unconditional data[:min(...)] and used strings.Cut for title parsing; confirm bounds safety and returned values when limits or separators are absent.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: go 1.26 modernize' clearly and concisely summarizes the main change: modernizing the codebase for Go 1.26. It is specific, directly related to the changeset, and reflects the primary objective evident across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
player/icy.go (1)

42-44: 🧹 Nitpick | 🔵 Trivial

Consider using min() for clamping, consistent with Go 1.21+ idioms.

Since this PR modernizes the codebase for Go 1.26, the clamping logic could be simplified using the built-in min() function introduced in Go 1.21.

♻️ Proposed modernization
 	// Clamp the read so we never cross into a metadata block.
-	if len(p) > ir.remaining {
-		p = p[:ir.remaining]
-	}
+	p = p[:min(len(p), ir.remaining)]
 	n, err := ir.r.Read(p)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@player/icy.go` around lines 42 - 44, Replace the manual length-clamp using an
if with Go's built-in min() to simplify and follow Go 1.21+ idioms: in the
slice-read logic where p and ir.remaining are used (the snippet showing if
len(p) > ir.remaining { p = p[:ir.remaining] }), compute the new length with
min(len(p), ir.remaining) and reslice p accordingly (use the min result to set p
= p[:min(...)]), keeping the same variable names and behavior.
external/ytmusic/classify.go (1)

89-110: 🧹 Nitpick | 🔵 Trivial

Consider modernizing to wg.Go() for consistency.

This goroutine still uses the manual wg.Add(1)/defer wg.Done() pattern while similar code in provider.go:fetchDurations was modernized to wg.Go(). With Go 1.22+ per-iteration loop variable scoping, you can capture pl directly:

♻️ Suggested refactor for consistency
 	for _, pl := range toClassify {
-		wg.Add(1)
-		go func(plID string) {
-			defer wg.Done()
+		wg.Go(func() {
 			sem <- struct{}{}
 			defer func() { <-sem }()
 
 			resp, err := svc.PlaylistItems.List([]string{"contentDetails"}).
-				PlaylistId(plID).
+				PlaylistId(pl.ID).
 				MaxResults(1).
 				Context(ctx).
 				Do()
 			if err != nil || len(resp.Items) == 0 {
-				sampleCh <- sampleResult{playlistID: plID}
+				sampleCh <- sampleResult{playlistID: pl.ID}
 				return
 			}
 			sampleCh <- sampleResult{
-				playlistID: plID,
+				playlistID: pl.ID,
 				videoID:    resp.Items[0].ContentDetails.VideoId,
 			}
-		}(pl.ID)
+		})
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@external/ytmusic/classify.go` around lines 89 - 110, Replace the manual
wg.Add(1)/defer wg.Done() goroutine pattern with wg.Go to match the style used
elsewhere: capture the loop variable pl directly (don’t pass pl.ID into the
closure), call wg.Go(func() error { ... return nil }) and move the semaphore
operations, API call (svc.PlaylistItems.List...PlaylistId(pl.ID)...Do()), and
sending to sampleCh/sampleResult inside that function; ensure errors still send
a sampleResult{playlistID: pl.ID} before returning an error or nil, and remove
the explicit wg.Add/Done calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@player/icy.go`:
- Around line 84-88: Remove the redundant alias variable `rest` introduced after
the strings.Cut call: delete the line `rest := after` and update subsequent
references of `rest` to use `after` directly (the variables returned from
strings.Cut in the same scope). This simplifies the logic in the parsing section
that currently uses `after`/`rest` without changing behavior.

---

Outside diff comments:
In `@external/ytmusic/classify.go`:
- Around line 89-110: Replace the manual wg.Add(1)/defer wg.Done() goroutine
pattern with wg.Go to match the style used elsewhere: capture the loop variable
pl directly (don’t pass pl.ID into the closure), call wg.Go(func() error { ...
return nil }) and move the semaphore operations, API call
(svc.PlaylistItems.List...PlaylistId(pl.ID)...Do()), and sending to
sampleCh/sampleResult inside that function; ensure errors still send a
sampleResult{playlistID: pl.ID} before returning an error or nil, and remove the
explicit wg.Add/Done calls.

In `@player/icy.go`:
- Around line 42-44: Replace the manual length-clamp using an if with Go's
built-in min() to simplify and follow Go 1.21+ idioms: in the slice-read logic
where p and ir.remaining are used (the snippet showing if len(p) > ir.remaining
{ p = p[:ir.remaining] }), compute the new length with min(len(p), ir.remaining)
and reslice p accordingly (use the min result to set p = p[:min(...)]), keeping
the same variable names and behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fc5939d5-0b8b-4bb7-9d95-df66bcbd43e0

📥 Commits

Reviewing files that changed from the base of the PR and between cdfe752 and 35af053.

📒 Files selected for processing (41)
  • cmd/playlist.go
  • external/local/provider.go
  • external/navidrome/client.go
  • external/radio/favorites.go
  • external/radio/provider.go
  • external/spotify/provider.go
  • external/ytmusic/cache.go
  • external/ytmusic/classify.go
  • external/ytmusic/provider.go
  • ipc/protocol.go
  • ipc/protocol_test.go
  • ipc/server.go
  • ipc/server_test.go
  • luaplugin/api_control.go
  • luaplugin/api_log.go
  • luaplugin/hooks.go
  • luaplugin/luaplugin.go
  • luaplugin/luaplugin_test.go
  • lyrics/lyrics.go
  • main.go
  • player/chained_ogg.go
  • player/icy.go
  • player/player.go
  • player/speed.go
  • player/tap.go
  • playlist/playlist_test.go
  • playlist/shuffle_repeat_test.go
  • resolve/m3u.go
  • ui/model/filebrowser.go
  • ui/model/keys.go
  • ui/model/keys_nav.go
  • ui/model/speed_controls_test.go
  • ui/model/tick.go
  • ui/model/view.go
  • ui/model/view_helpers.go
  • ui/model/view_nav.go
  • ui/model/view_overlays.go
  • ui/model/view_state_test.go
  • ui/vis_butterfly.go
  • ui/vis_classic_peak_test.go
  • ui/vis_retro.go
💤 Files with no reviewable changes (2)
  • luaplugin/api_log.go
  • luaplugin/hooks.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant