Rewrite JSON formatter to avoid decoder internals#203
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthrough
ChangesJSON formatting
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/utils/utils.go`:
- Line 436: Update FormatJson and all listed fmt.Fprint write sites to propagate
io.Writer errors instead of discarding them. Route the JSON output writes,
including the final newline write near the end of FormatJson, through a checked
helper that returns failures immediately so processContent receives the error
and truncated output is not reported as successful.
- Around line 436-474: Update the container formatting logic around formatToken
and the decoder loops so opening newlines are emitted only when the first child
is encountered, and pre-close newlines are emitted only when index > 0. Apply
the same behavior to both object and array handling, preserving indentation for
non-empty containers. Add empty object and array fixtures to the exact-output
tests.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 542301a7-ff4b-41b1-a78c-fb66d21f198b
📒 Files selected for processing (1)
internal/utils/utils.go
a01c128 to
348da75
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
internal/utils/utils_test.go (1)
137-142: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
t.Runandassert.NoErrorfor table-driven tests.Wrapping the table-driven test cases in
t.Runisolates failures and identifies exactly which input failed. Additionally, usingassert.NoErrorinstead ofassert.Nilis idiomatic intestify, as it prints the actual error message rather than a generic type mismatch if a failure occurs.♻️ Proposed refactor
for _, testCase := range tests { - output := new(strings.Builder) - formatErr := FormatJson(strings.NewReader(testCase.input), output, " ", ColorsDisabled) - assert.Nil(t, formatErr) - assert.Equal(t, testCase.expected, output.String()) + t.Run(testCase.input, func(t *testing.T) { + output := new(strings.Builder) + formatErr := FormatJson(strings.NewReader(testCase.input), output, " ", ColorsDisabled) + assert.NoError(t, formatErr) + assert.Equal(t, testCase.expected, output.String()) + }) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/utils/utils_test.go` around lines 137 - 142, Update the table-driven loop in the FormatJson test to wrap each case with t.Run using its test-case name, and replace assert.Nil on formatErr with assert.NoError. Preserve the existing input, expected output, and ColorsDisabled assertions inside each subtest.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@internal/utils/utils_test.go`:
- Around line 137-142: Update the table-driven loop in the FormatJson test to
wrap each case with t.Run using its test-case name, and replace assert.Nil on
formatErr with assert.NoError. Preserve the existing input, expected output, and
ColorsDisabled assertions inside each subtest.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b2cb20c0-5e74-466a-8c8e-48e7bf13a991
📒 Files selected for processing (2)
internal/utils/utils.gointernal/utils/utils_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
- internal/utils/utils.go
Go 1.27 enables the new encoding/json implementation, where json.Decoder no longer exposes the same private tokenState field layout. FormatJson was using reflection to read that unexported field, which caused a panic with Go 1.27rc2 when FieldByName returned a zero reflect.Value. Track object and array formatting state using the public Decoder Token and More APIs instead. This keeps the existing output behavior while avoiding dependency on encoding/json implementation details, making the formatter work with both Go 1.26 and Go 1.27. Signed-off-by: Mikel Olasagasti Uranga <mikel@olasagasti.info>
348da75 to
9540fe2
Compare
|
Looks good! @mikelolasagasti thank you for your work! |
Go 1.27 enables the new encoding/json implementation, where json.Decoder no longer exposes the same private tokenState field layout. FormatJson was using reflection to read that unexported field, which caused a panic with Go 1.27rc2 when FieldByName returned a zero reflect.Value.
Track object and array formatting state using the public Decoder Token and More APIs instead. This keeps the existing output behavior while avoiding dependency on encoding/json implementation details, making the formatter work with both Go 1.26 and Go 1.27.
Fixes #202
Summary by CodeRabbit
Bug Fixes
Tests