-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
all: merge master (7eebab3) into gopls-release-branch.0.17
Also add back the x/tools replace directive for gopls. For golang/go#70301 Merge List: + 2024-12-04 7eebab3 gopls/internal/golang: support extract variable at top level + 2024-12-04 e334696 gopls/internal/golang: ignore effects for change signature refactoring + 2024-12-04 3901733 internal/refactor/inline: substitute groups of dependent arguments + 2024-12-03 61b2408 gopls/internal/golang: add "Extract constant" counterpart + 2024-12-03 c01eead internal/gcimporter: require binary export data header + 2024-12-03 9a04136 gopls/internal/golang/stubmethods: refine crash into bug report + 2024-12-03 01e0b05 internal/refactor/inline: fix condition for splice assignment strategy + 2024-12-03 557f540 gopls/internal/golang: don't offer to move variadic parameters + 2024-12-03 399ee16 internal/gcimporter: update FindExportData to return a non-negative size + 2024-12-03 25b0003 internal/refactor/inline: more precise redundant conversion detection + 2024-12-03 eb46939 gopls/internal/test/marker: add reproducers for moveparam bug bash bugs + 2024-12-03 4296223 gopls/internal/analysis/yield: add comment about dataflow + 2024-12-03 7a4f3b0 internal/gcimporter: require archive files + 2024-12-02 2f73c61 gopls/internal/golang: avoid crash in lookupDocLinkSymbol + 2024-12-02 ef3d603 gopls/internal/golang/completion: fix crash with extra results + 2024-12-02 8ffeaba gopls/internal/settings: enable 'waitgroup' analyzer + 2024-12-02 4317959 go/analysis/passes/waitgroup: report WaitGroup.Add in goroutine + 2024-12-02 72fdfa6 gopls/internal/golang: Disable test generation for generic functions + 2024-12-02 b80f1ed gopls/internal/analysis/yield: peephole-optimize phi(false, x) + 2024-11-28 e7bd227 gopls/internal/golang: fix folding range for function calls + 2024-11-28 e71702b internal/versions: remove constraint.GoVersion wrapper + 2024-11-28 c99edec gopls/internal/golang/completion: add alias support for literals + 2024-11-27 bfe3046 go/packages: add a unit test for golang/go#70394 + 2024-11-27 df87831 gopls/internal/undeclaredname: add missing colon when appropriate + 2024-11-26 53efd30 gopls/internal/golang: simplify package name collection in add test Change-Id: I476e80493f61732701784befe2b130ca967b259e
- Loading branch information
Showing
72 changed files
with
2,482 additions
and
656 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright 2024 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Package waitgroup defines an Analyzer that detects simple misuses | ||
// of sync.WaitGroup. | ||
// | ||
// # Analyzer waitgroup | ||
// | ||
// waitgroup: check for misuses of sync.WaitGroup | ||
// | ||
// This analyzer detects mistaken calls to the (*sync.WaitGroup).Add | ||
// method from inside a new goroutine, causing Add to race with Wait: | ||
// | ||
// // WRONG | ||
// var wg sync.WaitGroup | ||
// go func() { | ||
// wg.Add(1) // "WaitGroup.Add called from inside new goroutine" | ||
// defer wg.Done() | ||
// ... | ||
// }() | ||
// wg.Wait() // (may return prematurely before new goroutine starts) | ||
// | ||
// The correct code calls Add before starting the goroutine: | ||
// | ||
// // RIGHT | ||
// var wg sync.WaitGroup | ||
// wg.Add(1) | ||
// go func() { | ||
// defer wg.Done() | ||
// ... | ||
// }() | ||
// wg.Wait() | ||
package waitgroup |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright 2024 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
//go:build ignore | ||
|
||
// The waitgroup command applies the golang.org/x/tools/go/analysis/passes/waitgroup | ||
// analysis to the specified packages of Go source code. | ||
package main | ||
|
||
import ( | ||
"golang.org/x/tools/go/analysis/passes/waitgroup" | ||
"golang.org/x/tools/go/analysis/singlechecker" | ||
) | ||
|
||
func main() { singlechecker.Main(waitgroup.Analyzer) } |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package a | ||
|
||
import "sync" | ||
|
||
func f() { | ||
var wg sync.WaitGroup | ||
wg.Add(1) // ok | ||
go func() { | ||
wg.Add(1) // want "WaitGroup.Add called from inside new goroutine" | ||
// ... | ||
wg.Add(1) // ok | ||
}() | ||
wg.Add(1) // ok | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// Copyright 2023 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Package waitgroup defines an Analyzer that detects simple misuses | ||
// of sync.WaitGroup. | ||
package waitgroup | ||
|
||
import ( | ||
_ "embed" | ||
"go/ast" | ||
"go/types" | ||
"reflect" | ||
|
||
"golang.org/x/tools/go/analysis" | ||
"golang.org/x/tools/go/analysis/passes/inspect" | ||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil" | ||
"golang.org/x/tools/go/ast/inspector" | ||
"golang.org/x/tools/go/types/typeutil" | ||
"golang.org/x/tools/internal/typesinternal" | ||
) | ||
|
||
//go:embed doc.go | ||
var doc string | ||
|
||
var Analyzer = &analysis.Analyzer{ | ||
Name: "waitgroup", | ||
Doc: analysisutil.MustExtractDoc(doc, "waitgroup"), | ||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup", | ||
Requires: []*analysis.Analyzer{inspect.Analyzer}, | ||
Run: run, | ||
} | ||
|
||
func run(pass *analysis.Pass) (any, error) { | ||
if !analysisutil.Imports(pass.Pkg, "sync") { | ||
return nil, nil // doesn't directly import sync | ||
} | ||
|
||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) | ||
nodeFilter := []ast.Node{ | ||
(*ast.CallExpr)(nil), | ||
} | ||
|
||
inspect.WithStack(nodeFilter, func(n ast.Node, push bool, stack []ast.Node) (proceed bool) { | ||
if push { | ||
call := n.(*ast.CallExpr) | ||
if fn, ok := typeutil.Callee(pass.TypesInfo, call).(*types.Func); ok && | ||
isMethodNamed(fn, "sync", "WaitGroup", "Add") && | ||
hasSuffix(stack, wantSuffix) && | ||
backindex(stack, 1) == backindex(stack, 2).(*ast.BlockStmt).List[0] { // ExprStmt must be Block's first stmt | ||
|
||
pass.Reportf(call.Lparen, "WaitGroup.Add called from inside new goroutine") | ||
} | ||
} | ||
return true | ||
}) | ||
|
||
return nil, nil | ||
} | ||
|
||
// go func() { | ||
// wg.Add(1) | ||
// ... | ||
// }() | ||
var wantSuffix = []ast.Node{ | ||
(*ast.GoStmt)(nil), | ||
(*ast.CallExpr)(nil), | ||
(*ast.FuncLit)(nil), | ||
(*ast.BlockStmt)(nil), | ||
(*ast.ExprStmt)(nil), | ||
(*ast.CallExpr)(nil), | ||
} | ||
|
||
// hasSuffix reports whether stack has the matching suffix, | ||
// considering only node types. | ||
func hasSuffix(stack, suffix []ast.Node) bool { | ||
// TODO(adonovan): the inspector could implement this for us. | ||
if len(stack) < len(suffix) { | ||
return false | ||
} | ||
for i := range len(suffix) { | ||
if reflect.TypeOf(backindex(stack, i)) != reflect.TypeOf(backindex(suffix, i)) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
// isMethodNamed reports whether f is a method with the specified | ||
// package, receiver type, and method names. | ||
func isMethodNamed(fn *types.Func, pkg, recv, name string) bool { | ||
if fn.Pkg() != nil && fn.Pkg().Path() == pkg && fn.Name() == name { | ||
if r := fn.Type().(*types.Signature).Recv(); r != nil { | ||
if _, gotRecv := typesinternal.ReceiverNamed(r); gotRecv != nil { | ||
return gotRecv.Obj().Name() == recv | ||
} | ||
} | ||
} | ||
return false | ||
} | ||
|
||
// backindex is like [slices.Index] but from the back of the slice. | ||
func backindex[T any](slice []T, i int) T { | ||
return slice[len(slice)-1-i] | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright 2024 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package waitgroup_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"golang.org/x/tools/go/analysis/analysistest" | ||
"golang.org/x/tools/go/analysis/passes/waitgroup" | ||
) | ||
|
||
func Test(t *testing.T) { | ||
analysistest.Run(t, analysistest.TestData(), waitgroup.Analyzer, "a") | ||
} |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Oops, something went wrong.