Skip to content

fix(linters): handle parenthesized callees in walkdirignoredeerror, uncheckedflushreturn, sprintferrorsnew, httprespbodyclose - #75599

Merged
pelikhan merged 1 commit into
mainfrom
sergo/paren-unwrap-walk-flush-errnew-body-r122-00bb688bfa62c97c
Nov 7, 2026
Merged

pelikhan merged 1 commit into
mainfrom
sergo/paren-unwrap-walk-flush-errnew-body-r122-00bb688bfa62c97c

Conversation

@github-actions

@github-actions github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes four linters that missed parenthesized callees. One of them also dropped diagnostics it had already detected. This continues the Sergo paren-unwrap series (#74277, #74382, #74737, #75085, #75294); all of those PRs are merged.

Findings

Linter Location Problem Effect
walkdirignoredeerror walkdirignoredeerror.go:112 astutil.PackageCall already resolves (filepath.Walk)(...) and dot-imported Walk(...), but reportIfNotSkipped then re-asserted call.Fun.(*ast.SelectorExpr) only to get the name, and returned early when that failed Diagnostic detected, then silently dropped (false negative)
uncheckedflushreturn isFlushCallReturningError call.Fun.(*ast.SelectorExpr) without unwrapping (w.Flush)(), _ = (w.Flush)(), defer (w.Flush)() not reported
sprintferrorsnew run lines 40/52/56 callee, argument and inner callee not unwrapped (errors.New)(fmt.Sprintf(..)), errors.New((fmt.Sprintf(..))), errors.New((fmt.Sprintf)(..)) not reported. gopls/staticcheck S1028 already flags all three forms, which confirms they are the same pattern
httprespbodyclose bodyCloseReceiver, inspectNode callee, Body receiver, response ident, and the ExprStmt/assignment RHS not unwrapped False positive: defer (resp.Body.Close)() was not seen as a deferred close, so a function that also closed manually on an early-return branch was reported. Manual (resp.Body.Close)() / (resp.Body).Close() were missed

Changes

  • walkdirignoredeerror: isWalkDirCall becomes walkDirCallName, which returns the function name resolved from type information. The reporter takes that name, so the SelectorExpr re-check and its early return are gone.
  • uncheckedflushreturn, sprintferrorsnew, httprespbodyclose: wrap the relevant expressions in astutil.UnwrapParenExpr.
  • New fixture cases:
    • walkdirignoredeerror: parenthesized callees, plus a new dotimport.go covering . "path/filepath"
    • uncheckedflushreturn: badParenthesizedCallee covering the bare, blank-assign and defer forms
    • sprintferrorsnew: badParenthesized with 3 forms
    • httprespbodyclose: new parens.go with 2 bad cases and 1 regression case for the false positive (GoodParenDeferClose)

Validation

  • Serena get_diagnostics_for_file (gopls) on all 4 changed analyzer sources: 0 diagnostics.
  • The same check on the changed and new fixtures returns only the expected unusedfunc info and S1028 warnings. That means they type-check, including the dot-import fixture.
  • ⚠️ go test and gofmt were not run: both commands are denied in this sandbox. CI should run go test ./pkg/linters/walk-dir-ignored-error/ ./pkg/linters/uncheckedflushreturn/ ./pkg/linters/sprintferrorsnew/ ./pkg/linters/httprespbodyclose/. I aligned fixture comments by hand to match gofmt.

🤖 Generated with [Claude Code]((claude.com/redacted)

Generated by 🤖 Sergo - Serena Go Expert · claude · routed: opus55 medium · ~144 AIC · ⌖ ~2 AIC · ⊞ 3.8K · ◷

  • expires on Nov 13, 2026, 7:53 PM UTC-08:00

@github-actions github-actions Bot added cookie Issue Monster Loves Cookies! sergo labels Nov 7, 2026
@pelikhan
pelikhan marked this pull request as ready for review November 7, 2026 04:27
Copilot AI auto review requested due to automatic review settings November 7, 2026 04:27
@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Ponytail Reviewer completed successfully!

Ponytail Reviewer

Outcome: reported_no_action

The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible.

Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.

Generated from Ponytail Reviewer · routed: gpt56 max · ~3 AIC · ⌖ ~1 AIC · ⊞ 118 · ◷

Generated by Ponytail Reviewer for #75599

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ PR Specification Reviewer completed successfully!

PR Specification Reviewer

Outcome: reported_no_action

The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible.

Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.

Generated from PR Specification Reviewer · gpt56 · ~2 AIC · ⌖ ~2 AIC · ⊞ 1.6K · ◷

Generated by PR Specification Reviewer for #75599

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel

Outcome: reported_no_action

The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible.

Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.

Generated from Test Quality Sentinel · routed: gpt56 max · ~2 AIC · ⌖ ~2 AIC · ⊞ 6.3K · ◷

🧪 Test quality analysis by Test Quality Sentinel

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues were identified for the parenthesis-handling updates across the four Go linters.

No open issues 🎉

What changed in this PR

This PR extends the earlier parenthesis-handling fixes to four gh-aw Go linters, improving diagnostic consistency for equivalent Go expressions.

Changes:

  • Preserve directory-walk diagnostics by using resolved function names, including for dot-imported calls.
  • Unwrap parenthesized expressions in flush, error-formatting, and HTTP response-body checks.
  • Add regression fixtures for missed diagnostics and correctly deferred response-body closes.
File Description
pkg/​linters/​walk-dir-ignored-error/​walkdirignoredeerror.go Report using resolved function names without rechecking selector syntax.
pkg/​linters/​walk-dir-ignored-error/​testdata/​src/​walkdirignoredeerror/​walkdirignoredeerror.go Cover parenthesized Walk and WalkDir callees.
pkg/​linters/​walk-dir-ignored-error/​testdata/​src/​walkdirignoredeerror/​dotimport.go Cover discarded and handled errors from dot-imported calls.
pkg/​linters/​uncheckedflushreturn/​uncheckedflushreturn.go Recognize parenthesized Flush callees.
pkg/​linters/​uncheckedflushreturn/​testdata/​src/​uncheckedflushreturn/​uncheckedflushreturn.go Cover bare, blank-assigned, and deferred parenthesized Flush calls.
pkg/​linters/​sprintferrorsnew/​testdata/​src/​sprintferrorsnew/​sprintferrorsnew.go Cover parentheses around outer callees, arguments, and inner callees.
pkg/​linters/​sprintferrorsnew/​sprintferrorsnew.go Unwrap expressions when matching errors.New(fmt.Sprintf(...)).
pkg/​linters/​httprespbodyclose/​testdata/​src/​httprespbodyclose/​parens.go Cover manual parenthesized closes and a deferred-close regression.
pkg/​linters/​httprespbodyclose/​httprespbodyclose.go Unwrap close callees, receivers, and statement expressions.

Review effort: Balanced (auto)

@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor Author

✅ Design Decision Gate — ADR Verified

ADR reviewed: ADR-75294: Unwrap Parenthesized Expressions in Linter Matchers (link unavailable: invalid HTTPS URL) — implementation aligns with the stated decision. Great work! 🏗️

📋 Verification Summary
  • pkg/linters/uncheckedflushreturn, sprintferrorsnew, and httprespbodyclose use targeted astutil.UnwrapParenExpr calls at the affected matcher boundaries.
  • walk-dir-ignored-error now obtains the resolved Walk/WalkDir name from type information instead of re-asserting a selector, covering parenthesized and dot-imported calls without introducing a shared matcher abstraction.
  • The added fixtures cover parenthesized callees, arguments, receivers, dot imports, and the GoodParenDeferClose regression case described by the decision.

Next action: keep the ADR referenced in the PR description for discoverability.

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · pi · routed: gpt56 max · ~2 AIC · ⌖ ~2 AIC · ⊞ 7.7K · ◷
Comment /review to run again

@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor Author

Comment Memory

Peek at saved memory (pr-code-quality-reviewer)
reviewed_at: 2026-11-07T04:31:24Z
review_event: REQUEST_CHANGES
top_themes: [incomplete parenthesis unwrapping in package qualifiers]
files_reviewed: [pkg/linters/sprintferrorsnew/sprintferrorsnew.go, pkg/linters/httprespbodyclose/httprespbodyclose.go, pkg/linters/walk-dir-ignored-error/walkdirignoredeerror.go, pkg/linters/uncheckedflushreturn/uncheckedflushreturn.go]
comment_count: 1

Note

This comment is managed by comment memory.

Expand the saved memory block to view or edit the persistent context for this thread.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · ~4 AIC · ⌖ ~1 AIC · ⊞ 1.6K · ◷
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Found one blocking correctness gap: the sprintferrorsnew changes unwrap the outer callee and inner call, but package qualifiers remain unwrapped, so parenthesized forms like (errors).New(...) and (fmt).Sprintf(...) are still missed. Please address this and add coverage. Static review only; tests were not run in this environment.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · ~4 AIC · ⌖ ~1 AIC · ⊞ 1.6K
Comment /review to run again

sel, ok := call.Fun.(*ast.SelectorExpr)
// Match errors.New(...), including a parenthesized callee such as
// (errors.New)(...).
sel, ok := astutil.UnwrapParenExpr(call.Fun).(*ast.SelectorExpr)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This unwraps only the call expression itself, but IsPkgSelector still requires sel.X to be a bare *ast.Ident. Therefore forms such as (errors).New(fmt.Sprintf("...")) and errors.New((fmt).Sprintf("...")) remain false negatives, despite the new parenthesized-callee coverage. Please unwrap sel.X (or update the helper) and add fixtures for package-qualifier parentheses.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /tdd and /diagnosing-bugs. Requesting changes for one missed-diagnostic gap in httprespbodyclose. The other three linters look correct.

📋 Key Themes & Highlights

Key Themes

  • Incomplete paren handling in httprespbodyclose: the PR fixes the callee, receiver, and ExprStmt/Rhs paths in markBodyClose, but trackHTTPAssignment still uses bare lhs.(*ast.Ident) and rhs.(*ast.CallExpr). A fully parenthesized assignment RHS, resp, err := (client.Do(req)), is never tracked, so the leak diagnostic is silently dropped. Reproduced with a temporary fixture (since removed); it passes once those two assertions use astutil.UnwrapParenExpr. See the inline comment.
  • Regression coverage gap: parens.go covers the callee and receiver forms but not this RHS form. Adding a BadParenthesizedAssignRHS case would lock in the fix.

Verification

  • Ran go test -count=1 on all four changed packages: all pass. The PR notes go test was not run in its sandbox, so this closes that gap.
  • gofmt -l on the four packages: clean.

Positive Highlights

  • ✅ walkDirCallName derives the name from type info. This removes a silent false negative for dot-imported Walk(...) and deletes the early return. Clean fix.
  • ✅ The (resp.Body.Close)() defer regression case (GoodParenDeferClose) correctly pins the false positive that was fixed.
  • ✅ Consistent use of the shared astutil.UnwrapParenExpr helper across all four linters.

@copilot please address the review comments above.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · routed: haiku55 xhigh · ~4 AIC · ⌖ ~1 AIC · ⊞ 5.5K
Comment /matt to run again

// Also check RHS for manual Body.Close() in assignments like: err := resp.Body.Close()
for _, rhs := range assign.Rhs {
if call, ok := rhs.(*ast.CallExpr); ok {
if call, ok := astutil.UnwrapParenExpr(rhs).(*ast.CallExpr); ok {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[/tdd] [/diagnosing-bugs] The assignment tracking path still misses parenthesized forms. trackHTTPAssignment (lines 184 and 197) still uses bare lhs.(*ast.Ident) and rhs.(*ast.CallExpr), so resp, err := (client.Do(req)) is never tracked and the missing-defer diagnostic is silently dropped. I reproduced this with a temporary fixture: it fails on this branch and passes with the unwrap change below applied to lines 184 and 197.

💡 Suggested fix and regression test

In trackHTTPAssignment:

ident, ok := astutil.UnwrapParenExpr(lhs).(*ast.Ident)
...
if call, ok := astutil.UnwrapParenExpr(rhs).(*ast.CallExpr); ok {

Add this case to parens.go so the gap stays covered:

// BadParenthesizedAssignRHS wraps the whole assignment RHS in parentheses.
func BadParenthesizedAssignRHS(client *http.Client, req *http.Request) ([]byte, error) {
	resp, err := (client.Do(req)) // want `HTTP response Body\.Close\(\) should be deferred immediately after receiving the response to prevent resource leaks`
	if err != nil {
		return nil, err
	}
	data, readErr := io.ReadAll(resp.Body)
	resp.Body.Close()
	return data, readErr
}

@copilot please address this.

@pelikhan
pelikhan merged commit e6041e1 into main Nov 7, 2026
94 checks passed
@pelikhan
pelikhan deleted the sergo/paren-unwrap-walk-flush-errnew-body-r122-00bb688bfa62c97c branch November 7, 2026 05:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cookie Issue Monster Loves Cookies! sergo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants