internal/lsp/source: add the unusedwrite analyzer
Fixes golang/go#44461
Change-Id: I0e002a26cd188cd9b5a14e44d7f880f9f414af36
Reviewed-on: https://go-review.googlesource.com/c/tools/+/295172
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Trust: Rebecca Stambler <rstambler@golang.org>
Trust: Peter Weinberger <pjw@google.com>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
diff --git a/gopls/doc/analyzers.md b/gopls/doc/analyzers.md
index 747b17e..6a25f30 100644
--- a/gopls/doc/analyzers.md
+++ b/gopls/doc/analyzers.md
@@ -468,6 +468,35 @@
**Enabled by default.**
+## **unusedwrite**
+
+checks for unused writes
+
+The analyzer reports instances of writes to struct fields and
+arrays that are never read. Specifically, when a struct object
+or an array is copied, its elements are copied implicitly by
+the compiler, and any element write to this copy does nothing
+with the original object.
+
+For example:
+
+ type T struct { x int }
+ func f(input []T) {
+ for i, v := range input { // v is a copy
+ v.x = i // unused write to field x
+ }
+ }
+
+Another example is about non-pointer receiver:
+
+ type T struct { x int }
+ func (t T) f() { // t is a copy
+ t.x = i // unused write to field x
+ }
+
+
+**Disabled by default. Enable it by setting `"analyses": {"unusedwrite": true}`.**
+
## **fillreturns**
suggested fixes for "wrong number of return values (want %d, got %d)"
diff --git a/internal/lsp/source/api_json.go b/internal/lsp/source/api_json.go
index 7352130..aa7b518 100755
--- a/internal/lsp/source/api_json.go
+++ b/internal/lsp/source/api_json.go
@@ -477,6 +477,11 @@
Default: "true",
},
{
+ Name: "\"unusedwrite\"",
+ Doc: "checks for unused writes\n\nThe analyzer reports instances of writes to struct fields and\narrays that are never read. Specifically, when a struct object\nor an array is copied, its elements are copied implicitly by\nthe compiler, and any element write to this copy does nothing\nwith the original object.\n\nFor example:\n\n\ttype T struct { x int }\n\tfunc f(input []T) {\n\t\tfor i, v := range input { // v is a copy\n\t\t\tv.x = i // unused write to field x\n\t\t}\n\t}\n\nAnother example is about non-pointer receiver:\n\n\ttype T struct { x int }\n\tfunc (t T) f() { // t is a copy\n\t\tt.x = i // unused write to field x\n\t}\n",
+ Default: "false",
+ },
+ {
Name: "\"fillreturns\"",
Doc: "suggested fixes for \"wrong number of return values (want %d, got %d)\"\n\nThis checker provides suggested fixes for type errors of the\ntype \"wrong number of return values (want %d, got %d)\". For example:\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\nwill turn into\n\tfunc m() (int, string, *bool, error) {\n\t\treturn 0, \"\", nil, nil\n\t}\n\nThis functionality is similar to https://github.com/sqs/goreturns.\n",
Default: "true",
@@ -990,6 +995,11 @@
Default: true,
},
{
+ Name: "unusedwrite",
+ Doc: "checks for unused writes\n\nThe analyzer reports instances of writes to struct fields and\narrays that are never read. Specifically, when a struct object\nor an array is copied, its elements are copied implicitly by\nthe compiler, and any element write to this copy does nothing\nwith the original object.\n\nFor example:\n\n\ttype T struct { x int }\n\tfunc f(input []T) {\n\t\tfor i, v := range input { // v is a copy\n\t\t\tv.x = i // unused write to field x\n\t\t}\n\t}\n\nAnother example is about non-pointer receiver:\n\n\ttype T struct { x int }\n\tfunc (t T) f() { // t is a copy\n\t\tt.x = i // unused write to field x\n\t}\n",
+ Default: false,
+ },
+ {
Name: "fillreturns",
Doc: "suggested fixes for \"wrong number of return values (want %d, got %d)\"\n\nThis checker provides suggested fixes for type errors of the\ntype \"wrong number of return values (want %d, got %d)\". For example:\n\tfunc m() (int, string, *bool, error) {\n\t\treturn\n\t}\nwill turn into\n\tfunc m() (int, string, *bool, error) {\n\t\treturn 0, \"\", nil, nil\n\t}\n\nThis functionality is similar to https://github.com/sqs/goreturns.\n",
Default: true,
diff --git a/internal/lsp/source/options.go b/internal/lsp/source/options.go
index 05d3c9a..cb19dee 100644
--- a/internal/lsp/source/options.go
+++ b/internal/lsp/source/options.go
@@ -44,6 +44,7 @@
"golang.org/x/tools/go/analysis/passes/unreachable"
"golang.org/x/tools/go/analysis/passes/unsafeptr"
"golang.org/x/tools/go/analysis/passes/unusedresult"
+ "golang.org/x/tools/go/analysis/passes/unusedwrite"
"golang.org/x/tools/internal/lsp/analysis/fillreturns"
"golang.org/x/tools/internal/lsp/analysis/fillstruct"
"golang.org/x/tools/internal/lsp/analysis/nonewvars"
@@ -1142,6 +1143,7 @@
sortslice.Analyzer.Name: {Analyzer: sortslice.Analyzer, Enabled: true},
testinggoroutine.Analyzer.Name: {Analyzer: testinggoroutine.Analyzer, Enabled: true},
unusedparams.Analyzer.Name: {Analyzer: unusedparams.Analyzer, Enabled: false},
+ unusedwrite.Analyzer.Name: {Analyzer: unusedwrite.Analyzer, Enabled: false},
// gofmt -s suite:
simplifycompositelit.Analyzer.Name: {Analyzer: simplifycompositelit.Analyzer, Enabled: true, HighConfidence: true},