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.
[linter-miner] linter: add stringsindexcontains — flag strings.Index comparisons that should use strings.Contains #43253
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
Uh oh!
There was an error while loading. Please reload this page.
[linter-miner] linter: add stringsindexcontains — flag strings.Index comparisons that should use strings.Contains #43253
Changes from all commits
92bc49fd7e27a44498fcdFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
There are no files selected for viewing
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.
[/grill-with-docs] The inline comment block only lists 4 of the 6 supported patterns — it omits
strings.Index(s, sub) > -1andstrings.Index(s, sub) <= -1. A reader relying on this comment as spec would miss two valid patterns.💡 Suggested fix
@copilot please address this.
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.
The
pass *analysis.Passparameter is passed through here but is only used by the innerasStringsIndexCallcall. This is fine structurally, but it's worth noting thatnormalizeOperandshas a subtle issue: when neither operand is astrings.Indexcall, it returns(expr.Y, expr.X, true)— putting the right side as theleftresult withflipped=true. The caller inmatchIndexComparisonthen immediately callsasStringsIndexCall(pass, left)on that value, which will correctly returnfalse. But the semantic is slightly confusing: "flipped" should mean "we found Index on the right", yet here it can also mean "we found nothing". Consider renaming the return value or adding a doc comment clarifying the "no match" case to prevent future misuse.@copilot please address this.
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.
normalizeOperandsdiscards the*ast.CallExprand forcesasStringsIndexCallto re-traverse the same node immediately after.normalizeOperandscallsasStringsIndexCallto decide which side is the index call, returnsexpr.X/expr.Y(rawast.Expr), and thenmatchIndexComparisonimmediately callsasStringsIndexCallagain on the returnedleft. The same type assertion and selector walk runs twice on every binary expression that has astrings.Indexcall on either side.💡 Suggested fix
Return the
*ast.CallExprfromnormalizeOperandsto avoid redundant work:This is a minor structural issue, not blocking correctness, but the current design exists only because the return type was chosen poorly.
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.
[/codebase-design]
buildContainsFixacceptspass *analysis.Passbut never uses it. The unused parameter adds noise to the interface and suggests the function signature was copied from a similar helper that did usepass.💡 Suggested fix
Remove the
passparameter since all needed information is already provided via the explicit text arguments:Update the call site at line 81 accordingly.
@copilot please address this.
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.
The
pass *analysis.Passparameter is declared but never used in this function — all the needed data (the replacement text and AST position) is already passed in as pre-computed strings and theexprnode. Consider removing it to keep the signature minimal:And update the call site at line ~82 accordingly.
@copilot please address this.
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.
The test coverage is minimal — only 6 bad cases and 4 good cases. Missing coverage for the patterns listed in the PR description and in the doc comment of
matchIndexComparison:strings.Index(s, sub) > -1(GTR / -1 → contains)strings.Index(s, sub) <= -1(LEQ / -1 → not-contains)0 <= strings.Index(...)) and LSS (0 > strings.Index(...))Please add fixtures for these cases to
testdata/src/stringsindexcontains/stringsindexcontains.goso the full operator coverage documented in the implementation is actually tested.@copilot please address this.
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.
[/tdd] The
> -1(GTR) and<= -1(LEQ) patterns implemented inmatchIndexComparisonhave no corresponding testdata fixtures — these code paths are untested and could regress silently.💡 Suggested fixture additions
Add to
testdata/src/stringsindexcontains/stringsindexcontains.go:Similarly, the yoda-order variants for
0 <= strings.Index(...)and0 > strings.Index(...)are documented in the function godoc but have no fixture coverage.@copilot please address this.
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.
Suggested fixes are emitted but never validated — this is the primary value of the linter and it is completely untested.
The test calls
analysistest.Runbut the linter emitsSuggestedFixes.analysistest.Runonly checks that diagnostics fire on the expected lines; it never applies or validates the fix text edits. Every other linter in this repo that emits fixes usesRunWithSuggestedFixeswith matching.goldenfiles (e.g.,ctxbackground,lenstringsplit,lenstringzero,fprintlnsprintf,execcommandwithoutcontext).Given the stated purpose — automated repair of 42 occurrences — silently shipping unvalidated fix text is a serious quality gap.
💡 How to fix
analysistest.Run→analysistest.RunWithSuggestedFixesin the test..goldenfile undertestdata/src/stringsindexcontains/stringsindexcontains.go.goldencontaining the expected post-fix source.Without this change,
buildContainsFixcould produce incorrect replacements (wrong parenthesization, wrong package alias) and all tests would still pass.Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.