diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | cmd/gocapturedrefrace/main.go | 10 | ||||
| -rw-r--r-- | go.mod | 10 | ||||
| -rw-r--r-- | go.sum | 7 | ||||
| -rw-r--r-- | gocapturedrefrace.go | 45 | ||||
| -rw-r--r-- | testdata/simple.go | 9 | 
6 files changed, 82 insertions, 0 deletions
| diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd1a426 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/private/ diff --git a/cmd/gocapturedrefrace/main.go b/cmd/gocapturedrefrace/main.go new file mode 100644 index 0000000..d637a38 --- /dev/null +++ b/cmd/gocapturedrefrace/main.go @@ -0,0 +1,10 @@ +package main + +import ( +	"git.teddywing.com/gocapturedrefrace" +	"golang.org/x/tools/go/analysis/singlechecker" +) + +func main() { +	singlechecker.Main(gocapturedrefrace.Analyzer) +} @@ -0,0 +1,10 @@ +module git.teddywing.com/gocapturedrefrace + +go 1.20 + +require golang.org/x/tools v0.9.1 + +require ( +	golang.org/x/mod v0.10.0 // indirect +	golang.org/x/sys v0.8.0 // indirect +) @@ -0,0 +1,7 @@ +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= diff --git a/gocapturedrefrace.go b/gocapturedrefrace.go new file mode 100644 index 0000000..762473b --- /dev/null +++ b/gocapturedrefrace.go @@ -0,0 +1,45 @@ +package gocapturedrefrace + +import ( +	"bytes" +	"go/ast" +	"go/printer" + +	"golang.org/x/tools/go/analysis" +) + +var Analyzer = &analysis.Analyzer{ +	Name: "gocapturedrefrace", +	Doc:  "reports captured references in goroutine closures", +	Run:  run, +} + +func run(pass *analysis.Pass) (interface{}, error) { +	for _, file := range pass.Files { +		ast.Inspect( +			file, +			func(node ast.Node) bool { +				goStmt, ok := node.(*ast.GoStmt) +				if !ok { +					return true +				} + +				var printedNode bytes.Buffer +				err := printer.Fprint(&printedNode, pass.Fset, goStmt) +				if err != nil { +					panic(err) +				} + +				pass.Reportf( +					goStmt.Pos(), +					"go statement found %q", +					printedNode, +				) + +				return true +			}, +		) +	} + +	return nil, nil +} diff --git a/testdata/simple.go b/testdata/simple.go new file mode 100644 index 0000000..496be52 --- /dev/null +++ b/testdata/simple.go @@ -0,0 +1,9 @@ +package main + +func main() { +	capturedReference := 0 + +	go func() { +		capturedReference += 1 +	}() +} | 
