chore: upgrade to Go 1.27 and golangci-lint 2.13.1 - #1830
Conversation
Go 1.27's unicode tables are Unicode 17.0.0 and golang.org/x/text/cases selects its own 17.0.0 tables under //go:build go1.27, so the delta internal/utils/unicode17 carried on top of Go 1.26's Unicode 15.0 tables is gone. Its category predicates move to internal/utils/ecmascript, which keeps depguard denying the standard library's unicode under a rule.
Go 1.27's unicode tables are the edition Node reads, so a rule asks unicode.IsLetter and its siblings directly. depguard no longer denies the package; forbidigo denies the calls that still disagree with JavaScript, which are unicode.To*, SimpleFold and IsSpace. buildCaseTables walks a patched copy of unicode.CaseRanges rather than that table plus a second list: the six characters whose only uppercase is a sequence have no case range of their own, yet still fold onto another character.
This reverts commit 0d2bcbe.
This reverts commit 9feb899.
v2 keeps formatters in their own top-level section, which this config never had, so golangci-lint fmt was a no-op and 82 files under cmd/ and internal/ had drifted out of gofmt. Enable gofmt there and format them. Four doc comments held JavaScript snippets whose quoting gofmt rewrites -- '' becomes a closing curly quote, as does a doubled backtick -- so they are reworded to survive the formatter. CI ran the formatter in write mode, where it can never fail; it now runs --diff. errcheck and paralleltest leave the enable list, which the disable block above it had been overriding all along.
… had internal/fourslash lives in the typescript-go submodule, which is a module of its own and outside the ./cmd/... ./internal/... scope this config is ever run against.
elecmonkey
left a comment
There was a problem hiding this comment.
The toolchain and Unicode changes otherwise appear behaviorally consistent, but the upgraded lint tool causes the required Lint&Check job to fail deterministically with five staticcheck errors. The patch is therefore not currently mergeable.
- [P1] Resolve SA1019 errors exposed by v2.13.1 —
.github/workflows/ci.yml:126
With this version pinned, everyLint&Checkrun fails before reaching the remaining checks: staticcheck reports five SA1019 errors for deprecatedESModuleInteropandRangeLengthfields ininternal/config/all_rules_test.go,internal/lsp/document_changes_test.go, andinternal/plugins/import/utils/export_map_test.go. Update or explicitly suppress those usages as part of the upgrade so the required CI job can pass.
# Conflicts: # internal/plugins/unicorn/rules/filename_case/filename_case_test.go
Added |
Go 1.26 → Go 1.27 benchmark resultsI benchmarked the same PR source ( Focused Go benchmarksGOMAXPROCS=8 go test -run='^$' -bench='.' -benchtime=2s -count=8 ./tests/bench-go/
A second interleaved confirmation using prebuilt benchmark binaries, ten paired samples, and a one-second benchmark time produced:
Bytes allocated per operation were unchanged. Allocation counts were unchanged for syntax and type-aware linting; semantic diagnostics used approximately 0.05% fewer allocations under Go 1.27. End-to-end CLI benchmarkI also ran the repository's complete
Neither difference is statistically significant, so there is no observable end-to-end CLI regression under the CI configuration. As a supplementary check, 30 pairs using the machine's default processor count showed Go 1.27 faster by 2.06% for total CLI latency ( Binary sizeDefault binaries:
Go 1.27 is 695,437 bytes smaller (−1.41%). Binaries built with
The stripped Go 1.27 binary is 811,010 bytes smaller (−2.31%). Stripping reduced the Go 1.26 binary by 28.74% and the Go 1.27 binary by 29.39%. ConclusionThe focused inner-loop benchmarks show a reproducible CPU slowdown of roughly 1.5–2%. However, the representative end-to-end VS Code CLI workload does not reproduce that regression and is nominally slightly faster under Go 1.27. Memory usage is unchanged, and both regular and stripped binaries are smaller. |
# Conflicts: # internal/plugins/react_hooks/rules/rules_of_hooks/rules_of_hooks_extras_test.go
Summary
Moves the toolchain to Go 1.27 and golangci-lint v2.13.1, and takes the three cleanups that unblocks.
Toolchain
go.modandgo.workmove togo 1.27.0, withgo.work'stoolchainline following.shim/*and thetypescript-gosubmodule stay ongo 1.26.go-versionpins across the workflows move to1.27.0.v2.13.1, the first release built with go1.27; 2.12.x refuses to load a module targeting 1.27 at all.internal/utils/unicode17is deletedThe package carried the case mappings, foldings and general categories Unicode 16 and 17 added on top of the 15.0 tables Go 1.26 shipped, and named go1.27 as the release that would retire it. Go 1.27 is
unicode.Version17.0.0 andgolang.org/x/text/casesselects its own 17.0.0 tables under//go:build go1.27. That is what ties the deletion to thegodirective bump: built on 1.26, the same code silently reads Unicode 15.A rule now asks the standard library for a general category directly.
depguardno longer deniesunicodeunderinternal/rules/**andinternal/plugins/**, andforbidigodenies the calls that still disagree with JavaScript:unicode.To*,SimpleFoldandIsSpace.esregexp.buildCaseTableswalks a patched copy ofunicode.CaseRanges. Six characters whose only uppercase is a sequence — ΐ, ΰ, ſt, st — have no case range of their own, yet simple case folding still brings each onto another character, so a walk over the standard library's table alone cannot reach them.SA5011 workarounds reverted
#1337, #1441 and #1448 added
returnaftert.Fatal/t.Fatalfin test nil guards to silence staticcheck SA5011 false positives from golangci-lint v2.12.2. The cause is fixed in v2.13.0, so the 76 dead returns are gone.golangci-lint fmtnow formatsv2 keeps formatters in their own top-level section, which this config never had, so
golangci-lint fmtwas a no-op and 82 files undercmd/andinternal/had drifted out of gofmt.formatters.enablegetsgofmt, and those files are formatted. Four doc comments held JavaScript snippets whose quoting gofmt rewrites, and are reworded to survive it.The CI step ran the formatter in write mode, where it can never fail; it now runs
--diff.errcheckandparalleltestleave theenablelist, which thedisableblock above it had been overriding all along.Related Links
Checklist