Skip to content

refactor(linters): consolidate duplicated AST/context helpers into internal/astutil#43649

Merged
pelikhan merged 4 commits into
mainfrom
copilot/refactor-dup-linter-helpers
Jul 6, 2026
Merged

refactor(linters): consolidate duplicated AST/context helpers into internal/astutil#43649
pelikhan merged 4 commits into
mainfrom
copilot/refactor-dup-linter-helpers

Conversation

Copilot AI commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

The linter suite had repeated helper implementations across analyzers (enclosingFuncType, context-type/param resolution, OS-call detection, and comparison-op flipping), creating avoidable drift risk. This PR centralizes those helpers in pkg/linters/internal/astutil and rewires affected analyzers to consume the shared implementations.

  • Shared helper consolidation

    • Added to pkg/linters/internal/astutil:
      • EnclosingFuncType
      • ContextContextType
      • ContextParamName
      • CalledOSFunc
      • FlipComparisonOp
    • Kept behavior aligned with existing analyzer logic while removing duplicate local implementations.
  • Analyzer migration to shared utilities

    • Updated:
      • execcommandwithoutcontext
      • httpnoctx
      • timesleepnocontext
      • ctxbackground
      • osgetenvlibrary
      • ossetenvlibrary
      • lenstringzero
      • stringsindexcontains
    • Removed per-package copies of the migrated helpers.
  • Context helper naming consistency

    • ctxbackground now uses the shared context helper path, eliminating local contextType naming divergence.
  • Shared helper unit coverage

    • Expanded astutil tests to cover new shared functions and their edge cases (func-type extraction, context lookup/param selection, OS function matching, operator flipping).
// before (local helper usage)
funcType := enclosingFuncType(encl.Node())
ctxName, ok := contextParamName(pass, funcType)

// after (shared astutil usage)
funcType := astutil.EnclosingFuncType(encl.Node())
ctxName, ok := astutil.ContextParamName(pass, funcType)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor consolidated duplicated linter AST helpers refactor(linters): consolidate duplicated AST/context helpers into internal/astutil Jul 6, 2026
Copilot AI requested a review from pelikhan July 6, 2026 01:26
@pelikhan pelikhan marked this pull request as ready for review July 6, 2026 01:29
Copilot AI review requested due to automatic review settings July 6, 2026 01:29
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality review.

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.

Pull request overview

This PR refactors the linter suite by consolidating repeated AST/type helper logic into pkg/linters/internal/astutil and updating multiple analyzers to use the shared helpers, with accompanying unit tests for the new shared functions.

Changes:

  • Added shared AST/type utilities in pkg/linters/internal/astutil (enclosing func type, context parameter detection, os.* call detection, comparison-op flipping).
  • Migrated several linters to use astutil helpers and removed their duplicated local implementations.
  • Expanded astutil unit tests to cover the newly centralized helper functions.
Show a summary per file
File Description
pkg/linters/internal/astutil/astutil.go Adds centralized AST/type helper functions used across linters.
pkg/linters/internal/astutil/astutil_test.go Adds unit coverage for the new shared helper functions.
pkg/linters/timesleepnocontext/timesleepnocontext.go Switches to shared astutil context/function helpers; removes local copies.
pkg/linters/execcommandwithoutcontext/execcommandwithoutcontext.go Switches to shared astutil context/function helpers; removes local copies.
pkg/linters/httpnoctx/httpnoctx.go Switches to shared astutil context/function helpers; removes local copies.
pkg/linters/ctxbackground/ctxbackground.go Switches to shared astutil context/function helpers; removes local copies.
pkg/linters/osgetenvlibrary/osgetenvlibrary.go Reuses shared astutil.CalledOSFunc for os.Getenv/os.LookupEnv detection.
pkg/linters/ossetenvlibrary/ossetenvlibrary.go Reuses shared astutil.CalledOSFunc for os.Setenv/os.Unsetenv detection.
pkg/linters/lenstringzero/lenstringzero.go Reuses shared astutil.FlipComparisonOp to normalize comparisons.
pkg/linters/stringsindexcontains/stringsindexcontains.go Reuses shared astutil.FlipComparisonOp to normalize comparisons.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Low

Comment on lines +270 to +277
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := FlipComparisonOp(tt.in); got != tt.want {
t.Fatalf("FlipComparisonOp(%v) = %v, want %v", tt.in, got, tt.want)
}
})
}
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (246 new lines in pkg/linters/) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/43649-consolidate-linter-astutil-helpers.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI could not infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-43649: Consolidate Duplicated AST/Context Helpers into internal/astutil

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 43649-consolidate-linter-astutil-helpers.md for PR #43649).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 58.7 AIC · ⌖ 12.8 AIC · ⊞ 8.5K ·
Comment /review to run again

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 91/100 — Excellent

Analyzed 8 test(s): 7 design, 1 implementation, 1 violation(s).

📊 Metrics (8 tests)
Metric Value
Analyzed 8 (Go: 8, JS: 0)
✅ Design 7 (87.5%)
⚠️ Implementation 1 (12.5%)
Edge/error coverage 7 (87.5%)
Duplicate clusters 0
Inflation No (1.26:1)
🚨 Violations 1 (missing build tag)
Test File Classification Issues
TestRhsExprForIndex astutil_test.go design_test None
TestIsStringLiteral astutil_test.go design_test None
TestNodeText astutil_test.go implementation_test Happy-path only, no error/edge case
TestIsPkgSelector astutil_test.go design_test None
TestEnclosingFuncType astutil_test.go design_test None
TestContextHelpers astutil_test.go design_test None
TestCalledOSFunc astutil_test.go design_test None
TestFlipComparisonOp astutil_test.go design_test None
⚠️ Flagged Tests (2)

astutil_test.go (line 1)Hard violation: missing //go:build tag. All new *_test.go files in this repository must declare //go:build !integration (or //go:build integration) on line 1. Every other linter test in pkg/linters/ carries this tag. Fix: add //go:build !integration as the very first line of the file.

TestNodeText (astutil_test.go:58) — implementation_test, low_value. Only asserts the happy path: NodeText of an *ast.Ident returns its name. Missing edge cases: nil node (should return ""), printer error path. Consider adding at least one error/edge-case subtest.

Verdict

Failed. 12.5% implementation tests (passes 30% threshold). Hard violation: pkg/linters/internal/astutil/astutil_test.go is missing the mandatory //go:build !integration (or //go:build integration) build tag on line 1. Add this tag to match the convention used by all other linter test files.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · 42.1 AIC · ⌖ 12.3 AIC · ⊞ 6.8K ·
Comment /review to run again

@github-actions github-actions Bot 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.

❌ Test Quality Sentinel: 91/100. Hard violation: pkg/linters/internal/astutil/astutil_test.go is missing the mandatory //go:build !integration build tag on line 1. Review flagged tests in the comment above.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Hey @copilot-swe-agent 👋 — great work on this linter refactor! Centralizing EnclosingFuncType, ContextParamName, CalledOSFunc, FlipComparisonOp, and friends into internal/astutil is exactly the kind of drift-prevention housekeeping that keeps the analyzer suite maintainable as it grows.

The PR is well-scoped, the description clearly explains the motivation and what changed, and the expanded astutil_test.go coverage (127 lines) gives solid confidence that the shared helpers behave correctly across edge cases. This looks ready for review. 🚀

Generated by ✅ Contribution Check · 275.8 AIC · ⌖ 21.7 AIC · ⊞ 6.2K ·

@github-actions github-actions Bot 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.

Skills-Based Review 🧠

Applied /codebase-design and /tdd — 4 targeted issues raised, all minor. The refactor itself is clean and well-motivated.

📋 Key Themes & Highlights

Key Themes

  • Leaky abstraction in httpnoctx: The ctxType parameter on hasContextInEnclosingFunc and the redundant fnType.Params == nil guard expose implementation details that the shared helpers already encapsulate.
  • Test coverage gaps on new helpers: The _-named parameter edge case in ContextParamName and the *ast.Ident call form in CalledOSFunc are untested paths.
  • Monolithic test function: TestContextHelpers combines two independent concerns; splitting into table-driven subtests improves failure locality.

Positive Highlights

  • ✅ Excellent reduction of 271 lines of duplicated boilerplate across 8 packages — zero behavioral delta
  • ✅ Shared helpers add proper nil guards (pass == nil, pass.Pkg == nil, pass.TypesInfo == nil) that several originals lacked
  • CalledOSFunc variadic allowedNames design cleanly replaces per-package if name != ... && name != ... chains
  • FlipComparisonOp tests follow the table-driven pattern with t.Parallel() — the right model for the other helpers too
  • ✅ New slices.Contains usage is idiomatic Go 1.21+

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 72.4 AIC · ⌖ 8.25 AIC · ⊞ 6.7K
Comment /matt to run again

Comments that could not be inline-anchored

pkg/linters/httpnoctx/httpnoctx.go:144

[/codebase-design] The fnType.Params == nil guard here is redundant — ContextParamName already handles a nil Params field internally (astutil.go line 84). Keeping it leaks implementation details of the helper into the caller and will drift if the helper's contract ever tightens.

<details>
<summary>💡 Suggested fix</summary>

Drop the Params arm from the nil check:

// before
if fnType == nil || fnType.Params == nil {
    continue
}

// after
if fnType == nil {
    continue
}
`…

</details>

<details><summary>pkg/linters/httpnoctx/httpnoctx.go:137</summary>

**[/codebase-design]** `ctxType types.Type` is passed into `hasContextInEnclosingFunc` only to guard against a nil early exit (line 138–140), but `ContextParamName` re-derives the context type internally. This creates a shallow module interface — the caller must know enough to pre-fetch and pass `ctxType`, but the callee duplicates the lookup anyway.

&lt;details&gt;
&lt;summary&gt;💡 Suggested fix&lt;/summary&gt;

Remove `ctxType` from the signature and drop the early-exit nil guard:
```go
// signature before
f…

</details>

<details><summary>pkg/linters/internal/astutil/astutil_test.go:171</summary>

**[/tdd]** `TestContextHelpers` is a monolithic test function that exercises `ContextContextType` and `ContextParamName` in a single body. When either fails the first assertion, the second scenario is never reached, and failure messages don&#39;t indicate which case broke.

&lt;details&gt;
&lt;summary&gt;💡 Suggested structure&lt;/summary&gt;

Split into focused subtests:
```go
func TestContextContextType(t *testing.T) {
    t.Parallel()
    t.Run(&quot;with_context_import&quot;, func(t *testing.T) { ... })
    t.Run(&quot;without…

</details>

<details><summary>pkg/linters/internal/astutil/astutil_test.go:223</summary>

**[/tdd]** `TestCalledOSFunc` tests the `*ast.SelectorExpr` call form but never exercises the `*ast.Ident` branch (direct function call without a package qualifier, e.g. a dot-import). That branch in `CalledOSFunc` (astutil.go line 141) is reachable and has no regression protection.

&lt;details&gt;
&lt;summary&gt;💡 Suggested addition&lt;/summary&gt;

```go
// add after existing selector test
identIdent := ast.NewIdent(&quot;Getenv&quot;)
passIdent := &amp;analysis.Pass{
    TypesInfo: &amp;types.Info{
        Uses: map[*ast.Ide…

</details>

@github-actions github-actions Bot 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.

Review: refactor(linters): consolidate duplicated AST/context helpers into internal/astutil

Good clean-up — 271 lines deleted, duplication eliminated across 8 analyzers, and new helpers are better-guarded than their local counterparts (nil checks on pass, pass.Pkg, pass.TypesInfo).

Two non-blocking suggestions:

  1. httpnoctx: leaked ctxType parameterhasContextInEnclosingFunc still accepts ctxType types.Type but after migration the only role of that parameter is a nil guard; the actual matching is fully delegated to ContextParamName. This leaves a misleading signature and causes ContextContextType to be called twice. The parameter (and its call-site assignment at line 47) can be safely removed.

  2. TestContextHelpers: missing blank-param coverageContextParamName explicitly skips "_"-named parameters but the test doesn't exercise that path. Easy to add one extra assertion using makePassWithFuncType(true, "_").

Both items are refactoring opportunities rather than bugs — the migrated behavior is correct.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 115.4 AIC · ⌖ 8.46 AIC · ⊞ 4.9K

Comments that could not be inline-anchored

pkg/linters/httpnoctx/httpnoctx.go:137

After the migration to astutil.ContextParamName, the ctxType types.Type parameter is now only used for a nil guard, while all actual context matching is delegated to ContextParamName which re-calls ContextContextType internally. This creates two issues:

  1. ContextContextType(pass) is called twice per http.NewRequest check (once eagerly at line 47, once inside ContextParamName).
  2. The parameter signature is misleading — it implies the caller controls the context type, but it's ig…
pkg/linters/internal/astutil/astutil_test.go:221

TestContextHelpers doesn't cover the blank parameter name path in ContextParamName. The implementation explicitly skips &quot;_&quot;-named parameters (see astutil.go: if name.Name != &quot;_&quot;), but there is no test asserting that a function with only _ context.Context returns (&quot;&quot;, false).

Consider adding a case using makePassWithFuncType(true, &quot;_&quot;) and asserting ok == false:

passBlank, fnTypeBlank := makePassWithFuncType(true, &quot;_&quot;)
if _, ok := ContextParamName(passBlank, fnTypeBlank</details>

@github-actions github-actions Bot 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.

Consolidation is solid — one real regression and two test issues need fixing

The deduplication intent is correct and the shared helpers are well-structured. One issue in httpnoctx is a genuine correctness-of-API + performance regression introduced by the refactor; two test concerns are worth addressing before merge.

🔍 Findings summary

Blocking (medium):

  • httpnoctx.go hasContextInEnclosingFunc: ctxType types.Type parameter is now a dead parameter — only its nil check on line 138 is used; ContextParamName redundantly calls ContextContextType (O(imports)) once per enclosing-function per call site instead of once per pass. The API implies the pre-computed type is being used for matching, but it is not.

Non-blocking (medium):

  • astutil_test.go TestCalledOSFunc: in-place mutation of pass.TypesInfo.Uses to switch test scenarios is a latent data race if subtests are ever parallelised, inconsistent with the t.Parallel() pattern throughout this file.

Non-blocking (low):

  • astutil_test.go TestContextHelpers: blank-identifier (_) context parameter path in ContextParamName is never exercised; the explicit skip on line 97 of astutil.go goes untested.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • proxy.golang.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "proxy.golang.org"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer · 183.7 AIC · ⌖ 5.46 AIC · ⊞ 5.4K
Comment /review to run again

return true
}
}
if _, ok := astutil.ContextParamName(pass, fnType); ok {

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.

Vestigial ctxType parameter causes redundant import scanning on every loop iteration.

After this refactor, hasContextInEnclosingFunc still accepts ctxType types.Type and uses it only for the nil early-exit on line 138. But ContextParamName internally calls ContextContextType again on every invocation inside the loop. The original code computed ctxType once in run() — O(imports). After this change, ContextContextType is called O(call_sites × nesting_depth × imports).

💡 Suggested fix

Either drop the parameter and compute ctxType once inside the function, or add a helper that accepts a pre-computed type to avoid repeated import iteration:

func hasContextInEnclosingFunc(pass *analysis.Pass, cursor inspector.Cursor) bool {
	ctxType := astutil.ContextContextType(pass)
	if ctxType == nil {
		return false
	}
	for enclosing := range cursor.Enclosing((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)) {
		fnType := astutil.EnclosingFuncType(enclosing.Node())
		if fnType == nil || fnType.Params == nil {
			continue
		}
		if _, ok := astutil.ContextParamName(pass, fnType); ok {
			return true
		}
	}
	return false
}

The ctxType value computed at line 47 of run() is now passed into this function but only used for the nil guard — it no longer participates in the actual type comparison at all, making the parameter misleading.

t.Fatal("CalledOSFunc() = ok=true for non-allowed name, want false")
}

pass.TypesInfo.Uses[selIdent] = otherFunc

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.

Shared state mutation between test scenarios is a latent data race.

pass.TypesInfo.Uses[selIdent] = otherFunc mutates the shared map to switch between test scenarios within a single non-parallel test function. If this test is ever refactored into parallel subtests (consistent with the t.Parallel() pattern used throughout this file), the concurrent map writes will trigger the race detector.

💡 Suggested fix

Construct independent pass and call objects per scenario rather than mutating shared state:

makeCall := func(fn types.Object) (*analysis.Pass, *ast.CallExpr) {
    id := ast.NewIdent("Getenv")
    p := &analysis.Pass{
        TypesInfo: &types.Info{
            Uses: map[*ast.Ident]types.Object{id: fn},
        },
    }
    c := &ast.CallExpr{Fun: &ast.SelectorExpr{X: ast.NewIdent("os"), Sel: id}}
    return p, c
}

osPass, osCall := makeCall(osFunc)
if fn, ok := CalledOSFunc(osPass, osCall, "Getenv", "LookupEnv"); !ok || fn != osFunc { ... }

otherPass, otherCall := makeCall(otherFunc)
if _, ok := CalledOSFunc(otherPass, otherCall); ok { ... }

if got := ContextContextType(passWithContext); got == nil {
t.Fatal("ContextContextType() = nil, want context.Context type")
}
name, ok := ContextParamName(passWithContext, fnTypeWithContext)

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.

ContextParamName blank-identifier branch (_ param name) is untested.

astutil.go line 97 explicitly skips blank-named parameters (if name.Name != "_"), returning ("", false) to signal no usable context param. This is a meaningful edge case — a function signature like func(context.Context, error) with a blank context receiver should not yield a param name. The test only exercises the happy path (ctx) and the no-context-import path; no case calls ContextParamName with a _-named parameter.

💡 Suggested addition
// Blank-named context param should not match.
passBlank, fnTypeBlank := makePassWithFuncType(true, "_")
if name, ok := ContextParamName(passBlank, fnTypeBlank); ok {
    t.Fatalf("ContextParamName() = (%q, true) for blank param, want (\"\", false)", name)
}

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address unresolved review feedback, and rerun checks once the branch is current.

Unresolved review feedback to address:

  • github-actions — add the required //go:build !integration tag to pkg/linters/internal/astutil/astutil_test.go
  • github-actions — remove the dead ctxType parameter / redundant lookup path in pkg/linters/httpnoctx/httpnoctx.go
  • github-actions — add the missing blank-identifier and direct *ast.Ident helper coverage called out in review feedback
  • github-actions — tighten the remaining httpnoctx helper API cleanup and related test refinements noted by review bots

Once those are addressed, rerun checks and update the PR if anything is still stale.

Generated by 👨‍🍳 PR Sous Chef · 17.4 AIC · ⌖ 11.7 AIC · ⊞ 7.1K ·
Comment /souschef to run again

- Add //go:build !integration tag to astutil_test.go
- Add blank-identifier param coverage to TestContextHelpers
- Add direct *ast.Ident coverage to TestCalledOSFunc
- Remove dead ctxType param from hasContextInEnclosingFunc in httpnoctx.go
  (ContextParamName already resolves context type internally)

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, address unresolved review feedback, and rerun checks once the branch is current.

Unresolved review feedback to address:...

Addressed all the unresolved feedback in commit fix(linters): address review feedback on astutil_test and httpnoctx:

  • //go:build !integration tag — added to pkg/linters/internal/astutil/astutil_test.go to match every other test file in the linter suite.
  • Dead ctxType param — removed from hasContextInEnclosingFunc in httpnoctx.go. The function already delegates to astutil.ContextParamName which resolves the context type internally, making the outer nil-guard and the call-site ContextContextType lookup redundant.
  • Blank-identifier coverage — added a case to TestContextHelpers verifying that a context parameter named _ is correctly skipped by ContextParamName.
  • Direct *ast.Ident coverage — added a case to TestCalledOSFunc exercising the non-SelectorExpr path in CalledOSFunc.
  • Range variable capture — the reviewer's tt := tt suggestion is moot on Go 1.22+ (loop variables are per-iteration); the copyloopvar linter would flag it as redundant, so no change was made.

Local validation (make fmt, make lint, make agent-report-progress) all green.

Copilot AI requested a review from gh-aw-bot July 6, 2026 02:10
@pelikhan pelikhan merged commit c9361ed into main Jul 6, 2026
29 checks passed
@pelikhan pelikhan deleted the copilot/refactor-dup-linter-helpers branch July 6, 2026 02:55
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill and close the loop on the remaining review state. Your latest update says the requested fixes are addressed and checks are green; please rerun/refresh anything needed so stale blocking review state is cleared, then confirm the branch is ready for maintainer review.

Please also ensure the ADR link is present in the PR body before handoff.

Run: https://github.com/github/gh-aw/actions/runs/28764674525

Generated by 👨‍🍳 PR Sous Chef · 4.08 AIC · ⌖ 9.33 AIC · ⊞ 7.1K ·
Comment /souschef to run again

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.

[refactor] Consolidate duplicated linter AST helpers into internal/astutil

4 participants