-
Notifications
You must be signed in to change notification settings - Fork 529
Guard suggested fixes against comment loss in five linters #57860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
50 changes: 50 additions & 0 deletions
50
docs/adr/57860-guard-linter-autofixes-against-comment-loss.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # ADR-57860: Guard Linter Autofixes Against Comment Loss | ||
|
|
||
| **Date**: 2026-09-02 | ||
| **Status**: Draft | ||
| **Deciders**: pelikhan, adr-writer agent | ||
|
|
||
| --- | ||
|
|
||
| ### Context | ||
|
|
||
| This pull request changes five Go linters that currently emit whole-expression `SuggestedFix` text edits for simplifications such as `append`, `time.Now().Sub`, `strings.Join`, `strings.Count`, and `strings.Index`. The PR description and tests show that these fixes can silently delete inline or trailing comments when the replacement span overlaps commented source, because AST printing does not preserve comments inside the rewritten expression. The diff introduces a shared overlap check in `pkg/linters/internal/astutil` and updates each affected linter plus golden tests. Because this changes the policy for when autofixes are emitted across multiple analyzers, the behavior should be captured explicitly. | ||
|
|
||
| ### Decision | ||
|
|
||
| We will keep reporting the diagnostics from these linters, but suppress their `SuggestedFix` autofixes whenever the replacement span overlaps source comments. We will centralize the overlap detection in `astutil.HasOverlappingComment` and make shared fix construction helpers accept the parsed files needed to perform that check. We chose this approach because preserving user comments is more important than always offering an automatic rewrite, and the diff shows a single reusable guard can address the issue consistently across all five linters. | ||
|
|
||
| ### Alternatives Considered | ||
|
|
||
| #### Alternative 1: Continue Emitting Autofixes Unconditionally | ||
|
|
||
| Keep the existing behavior and allow the analyzers to replace the full expression even when comments appear inside the rewritten span. | ||
|
|
||
| This was considered because it preserves maximum autofix coverage and requires no additional guard logic. It was not chosen because the PR evidence shows this behavior can silently delete user comments, which is a correctness and trust issue for `-fix` output. | ||
|
|
||
| #### Alternative 2: Rebuild Fixes to Preserve Comments | ||
|
|
||
| Teach each linter to generate narrower edits or comment-aware rewrites that retain inline and trailing comments while still applying an autofix. | ||
|
|
||
| This was considered because it could preserve both automation and comments. It was not chosen in this PR because the implemented evidence shows a simpler, shared suppression strategy across five linters, while a fully comment-preserving rewrite mechanism would be more complex and is not demonstrated by the current changes. | ||
|
|
||
| ### Consequences | ||
|
|
||
| #### Positive | ||
| - `go analysis -fix` no longer risks silently deleting overlapping inline or trailing comments for the affected linters. | ||
| - The overlap policy is applied consistently through a shared helper and shared test coverage. | ||
| - Diagnostics still surface the simplification opportunity even when an autofix is unsafe to apply automatically. | ||
|
|
||
| #### Negative | ||
| - Some findings that were previously auto-fixable now require manual edits when comments overlap the replacement span. | ||
| - Analyzer code paths become slightly more complex because fix generation now depends on parsed files and overlap checks. | ||
| - Future linters that emit whole-expression rewrites must remember to apply the same safety rule or use the shared helper correctly. | ||
|
|
||
| #### Neutral | ||
| - Testdata and golden files now explicitly encode the distinction between reporting a diagnostic and offering a fix. | ||
| - Shared helper signatures change to accept `pass.Files`, which updates caller contracts without changing the diagnostic messages themselves. | ||
| - The decision applies only to overlapping-comment cases; safe autofixes continue to be emitted for uncommented expressions. | ||
|
|
||
| --- | ||
|
|
||
| *ADR created by [adr-writer agent]. Review and finalize before changing status from Draft to Accepted.* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change fixes comment loss in four of the five linters, but
timenowsubonly got fixture updates and still has no executable regression test proving the analyzer suppresses autofixes when comments overlap. That leaves the core bug vulnerable to reintroduction because golden files alone do not assert whether aSuggestedFixwas omitted versus simply happened to produce identical output.💡 Add a real analyzer regression for the suppressed fix path
Please add a test that exercises
timenowsubthrough the analyzer and verifies the diagnostic is still reported without a suggested fix when the replaced span contains a comment. Right now onlyBuildContainsFixhas a unit test for the no-fix path; the other direct call-site guards rely on testdata that cannot distinguish "diagnostic with no fix" from "diagnostic with a fix that happened not to rewrite this file." A focused test here would lock in the behavior this PR is trying to preserve.