Add isolint custom linter and documentation for both linters#197
Open
yanyi-wego wants to merge 7 commits intomainfrom
Open
Add isolint custom linter and documentation for both linters#197yanyi-wego wants to merge 7 commits intomainfrom
yanyi-wego wants to merge 7 commits intomainfrom
Conversation
Raw ISO code strings like "USD" or "SG" scattered across the codebase are fragile — typos compile fine and silently break runtime behavior. This linter flags them at build time and suggests the typed constants from currency and site packages, with auto-fix support via SuggestedFix text edits. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The stringlint linter shipped without agent-facing docs. This adds testing guidance (analysistest bidirectional contract, positive/negative test patterns) and performance notes explaining why LoadModeTypesInfo is required and what the linter already does well to stay fast within that constraint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
golangci-lint may leave pass.Pkg unset when running analyzers under LoadModeSyntax, since the load mode is a hint to the runner — not a guarantee that Pkg is populated. analysistest always uses the full go/packages loader with type-checking, so pass.Pkg is always non-nil in tests — making this panic invisible to the test suite and only surfacing in production golangci-lint runs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CI pre-push hook runs revive alongside go vet, but AGENTS.md did not document revive as a command. This meant agents (and contributors) could write code that passes go vet and tests but fails the pre-push lint gate. Adding the command to both linter AGENTS.md files closes that gap. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Not all environments have standalone revive installed. golangci-lint is already a dependency for running the custom module plugins, so providing it as an alternative ensures linting works without extra tool installation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move testing guide and design rationale into docs/decisions.md and docs/testing.md. AGENTS.md keeps bullets and links for fast context loading; docs/ holds the why for progressive disclosure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restrict detection to uppercase-only ISO literals — lowercase and
mixed case are no longer flagged, eliminating false positives on
common English words ("id", "to", "no", "do").
Add context-aware skipping via inspector.WithStack: import paths
and arguments to ORM/HTTP/filter methods (skipMethods) are now
excluded. Split AGENTS.md rationale into docs/ for progressive
disclosure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
enzo-wego
reviewed
Mar 3, 2026
enzo-wego
approved these changes
Mar 3, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
isolint, a new golangci-lint module plugin that flags raw uppercase ISO code string literals ("USD","SG") and recommends typed constants fromcurrencyandsitepackages, with auto-fix supportAGENTS.mdanddocs/documentation to bothisolintandstringlintcovering architecture, testing patterns, and design decisionsrevivelinter integration with Makefiles for both linter packagesApproach
isolintfollows the same architecture asstringlint—go/analysisanalyzer withinspector.WithStackfiltered traversal, golangci-lint module plugin registration, andanalysistest-based tests with.go.goldenfiles for suggested fix verification.Key design choices:
LoadModeSyntax— only needs string literal values, no type-checking required. Cheapest load mode; avoids forcing type-checking on other linters in the golangci-lint batchcurrency.IsISO4217()andsite.Currency()instead of hardcoded mapslen(lit.Value) != 4 && != 5) eliminates most string literals beforestrconv.Unquoteallocates"USD","SG"etc.; lowercase ("usd","sg") and mixed case ("Usd") are intentionally skipped to avoid false positives on English words and identifiers like"id","to","no"Select,Pluck,Omit), HTTP methods (Query,Param,FormValue), and filter methods (Equals,NotEquals) are skipped as they represent column/parameter names, not ISO code valuespass.Pkgguard — golangci-lint may leavepass.Pkgnil underLoadModeSyntax; the analyzer tolerates this safelyDocumentation for both linters was restructured into
AGENTS.md(quick reference) anddocs/(detailed decisions and testing guides).Testing
analysistest.Run+RunWithSuggestedFixeswith positive tests (// wantannotations), negative tests (valid.go,valid_contexts.go), and golden filesIsCurrencyCode/IsSiteCodeincodes_test.gonil_pkg_test.gofor the nilpass.Pkgedge case