Skip to content

Commit ce96f56

Browse files
committed
all: merge master (85554d6) into gopls-release-branch.0.12
Also tidy and add back the replace directive. For golang/go#60917 Conflicts: - gopls/go.mod - gopls/go.sum Merge List: + 2023-06-20 85554d6 gopls/internal/lsp/cache: add debugging assertion for golang/go#60904 + 2023-06-20 9960b69 gopls/internal/lsp/cache: guard against "unsafe" by package path, not ID + 2023-06-20 6480332 gopls/internal/lsp/cache: use types.Unsafe in analysisPackage + 2023-06-20 155320d gopls/internal/lsp/work: don't crash when hovering over broken mod dir + 2023-06-20 b71392a gopls/internal/lsp/cache: reduce importing in analysis + 2023-06-20 d1a388b internal/gcimporter: avoid a crash when exporting a struct with no pkg + 2023-06-16 a4ed05f cmd/digraph: add "to dot" to emit Graphviz dot + 2023-06-15 7261b32 gopls/internal/regtest: fix goimports on windows when using vendoring + 2023-06-14 41e4e56 gopls/internal/lsp/source/completion: ensuring completion completeness + 2023-06-14 ac29460 go/ssa: fix bug in writeSignature on external functions + 2023-06-14 3b62e7e go/ssa: use core type within (*builder).receiver + 2023-06-14 f394d45 gopls/internal/lsp/cache: compute xrefs and methodsets asynchronously + 2023-06-14 27dbf85 go.mod: update golang.org/x dependencies + 2023-06-13 c6c9830 go/types/objectpath: memoize scope lookup in objectpath.Encoder + 2023-06-13 0245e1d gopls/internal/regtest/codelens: set GOWORK=off for go mod vendor + 2023-06-13 85be888 go/analysis/passes/defers: add analyser for defer mistake + 2023-06-13 c43232f cmd/digraph: improve examples using go list, mod + 2023-06-12 6e1595c internal/gcimporter: treat unknown constant values the same as invalid + 2023-06-12 c59d87f gopls/internal/lsp/cache: two minor simplifications + 2023-06-10 db6a81e go/packages/packagestest: set Config.Logf if the test is run verbosely + 2023-06-06 a01290f internal/typeparams: work around LookupFieldOrMethod inconsistency + 2023-06-05 6f567c8 gopls/internal/lsp/filecache: reduce lifespan of os.FileInfos + 2023-06-05 726c727 gopls/internal/lsp: enable min/max builtin completion test Change-Id: I85926c5d711102941750ad122844c10d13acc09a
2 parents e839744 + 85554d6 commit ce96f56

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1492
-792
lines changed

cmd/digraph/digraph.go

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ The support commands are:
3737
the set of nodes strongly connected to the specified one
3838
focus <node>
3939
the subgraph containing all directed paths that pass through the specified node
40+
to dot
41+
print the graph in Graphviz dot format (other formats may be supported in the future)
4042
4143
Input format:
4244
@@ -63,18 +65,32 @@ shirt -> sweater, not shirt -> tie -> sweater.
6365
6466
Example usage:
6567
66-
Using digraph with existing Go tools:
68+
Show which clothes (see above) must be donned before a jacket:
6769
68-
$ go mod graph | digraph nodes # Operate on the Go module graph.
69-
$ go list -m all | digraph nodes # Operate on the Go package graph.
70+
$ digraph reverse jacket
7071
71-
Show the transitive closure of imports of the digraph tool itself:
72+
Many tools can be persuaded to produce output in digraph format,
73+
as in the following examples.
7274
73-
$ go list -f '{{.ImportPath}} {{join .Imports " "}}' ... | digraph forward golang.org/x/tools/cmd/digraph
75+
Using an import graph produced by go list, show a path that indicates
76+
why the gopls application depends on the cmp package:
7477
75-
Show which clothes (see above) must be donned before a jacket:
78+
$ go list -f '{{.ImportPath}} {{join .Imports " "}}' -deps golang.org/x/tools/gopls |
79+
digraph somepath golang.org/x/tools/gopls github.com/google/go-cmp/cmp
7680
77-
$ digraph reverse jacket
81+
Show which packages in x/tools depend, perhaps indirectly, on the callgraph package:
82+
83+
$ go list -f '{{.ImportPath}} {{join .Imports " "}}' -deps golang.org/x/tools/... |
84+
digraph reverse golang.org/x/tools/go/callgraph
85+
86+
Visualize the package dependency graph of the current package:
87+
88+
$ go list -f '{{.ImportPath}} {{join .Imports " "}}' -deps |
89+
digraph to dot | dot -Tpng -o x.png
90+
91+
Using a module graph produced by go mod, show all dependencies of the current module:
92+
93+
$ go mod graph | digraph forward $(go list -m)
7894
*/
7995
package main // import "golang.org/x/tools/cmd/digraph"
8096

@@ -128,6 +144,8 @@ The support commands are:
128144
the set of nodes nodes strongly connected to the specified one
129145
focus <node>
130146
the subgraph containing all directed paths that pass through the specified node
147+
to dot
148+
print the graph in Graphviz dot format (other formats may be supported in the future)
131149
`)
132150
os.Exit(2)
133151
}
@@ -198,6 +216,14 @@ func (g graph) addEdges(from string, to ...string) {
198216
}
199217
}
200218

219+
func (g graph) nodelist() nodelist {
220+
nodes := make(nodeset)
221+
for node := range g {
222+
nodes[node] = true
223+
}
224+
return nodes.sort()
225+
}
226+
201227
func (g graph) reachableFrom(roots nodeset) nodeset {
202228
seen := make(nodeset)
203229
var visit func(node string)
@@ -347,6 +373,20 @@ func (g graph) somepath(from, to string) error {
347373
return nil
348374
}
349375

376+
func (g graph) toDot(w *bytes.Buffer) {
377+
fmt.Fprintln(w, "digraph {")
378+
for _, src := range g.nodelist() {
379+
for _, dst := range g[src].sort() {
380+
// Dot's quoting rules appear to align with Go's for escString,
381+
// which is the syntax of node IDs. Labels require significantly
382+
// more quoting, but that appears not to be necessary if the node ID
383+
// is implicitly used as the label.
384+
fmt.Fprintf(w, "\t%q -> %q;\n", src, dst)
385+
}
386+
}
387+
fmt.Fprintln(w, "}")
388+
}
389+
350390
func parse(rd io.Reader) (graph, error) {
351391
g := make(graph)
352392

@@ -395,11 +435,7 @@ func digraph(cmd string, args []string) error {
395435
if len(args) != 0 {
396436
return fmt.Errorf("usage: digraph nodes")
397437
}
398-
nodes := make(nodeset)
399-
for node := range g {
400-
nodes[node] = true
401-
}
402-
nodes.sort().println("\n")
438+
g.nodelist().println("\n")
403439

404440
case "degree":
405441
if len(args) != 0 {
@@ -554,6 +590,14 @@ func digraph(cmd string, args []string) error {
554590
sort.Strings(edgesSorted)
555591
fmt.Fprintln(stdout, strings.Join(edgesSorted, "\n"))
556592

593+
case "to":
594+
if len(args) != 1 || args[0] != "dot" {
595+
return fmt.Errorf("usage: digraph to dot")
596+
}
597+
var b bytes.Buffer
598+
g.toDot(&b)
599+
stdout.Write(b.Bytes())
600+
557601
default:
558602
return fmt.Errorf("no such command %q", cmd)
559603
}

cmd/digraph/digraph_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package main
66
import (
77
"bytes"
88
"fmt"
9+
"io"
910
"reflect"
1011
"sort"
1112
"strings"
@@ -346,3 +347,27 @@ func TestFocus(t *testing.T) {
346347
})
347348
}
348349
}
350+
351+
func TestToDot(t *testing.T) {
352+
in := `a b c
353+
b "d\"\\d"
354+
c "d\"\\d"`
355+
want := `digraph {
356+
"a" -> "b";
357+
"a" -> "c";
358+
"b" -> "d\"\\d";
359+
"c" -> "d\"\\d";
360+
}
361+
`
362+
defer func(in io.Reader, out io.Writer) { stdin, stdout = in, out }(stdin, stdout)
363+
stdin = strings.NewReader(in)
364+
stdout = new(bytes.Buffer)
365+
if err := digraph("to", []string{"dot"}); err != nil {
366+
t.Fatal(err)
367+
}
368+
got := stdout.(fmt.Stringer).String()
369+
if got != want {
370+
t.Errorf("digraph(to, dot) = got %q, want %q", got, want)
371+
}
372+
373+
}

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ go 1.18 // tagx:compat 1.16
44

55
require (
66
github.com/yuin/goldmark v1.4.13
7-
golang.org/x/mod v0.10.0
8-
golang.org/x/net v0.10.0
9-
golang.org/x/sys v0.8.0
7+
golang.org/x/mod v0.11.0
8+
golang.org/x/net v0.11.0
9+
golang.org/x/sys v0.9.0
1010
)
1111

12-
require golang.org/x/sync v0.2.0
12+
require golang.org/x/sync v0.3.0

go.sum

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,43 @@ github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
22
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
33
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
44
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
5+
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
56
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
67
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
7-
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
8-
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
8+
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
9+
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
910
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
1011
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
1112
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
1213
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
13-
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
1414
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
15+
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
16+
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
1517
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1618
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1719
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
18-
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
19-
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
20+
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
21+
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
2022
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
2123
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2224
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2325
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2426
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2527
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
26-
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
2728
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
29+
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
30+
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2831
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
2932
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
3033
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
3134
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
35+
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
3236
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
3337
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
3438
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
3539
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
3640
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
41+
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
3742
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
3843
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
3944
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// The defers command runs the defers analyzer.
6+
package main
7+
8+
import (
9+
"golang.org/x/tools/go/analysis/passes/defers"
10+
"golang.org/x/tools/go/analysis/singlechecker"
11+
)
12+
13+
func main() { singlechecker.Main(defers.Analyzer) }

go/analysis/passes/defers/defer.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package defers
6+
7+
import (
8+
_ "embed"
9+
"go/ast"
10+
"go/types"
11+
12+
"golang.org/x/tools/go/analysis"
13+
"golang.org/x/tools/go/analysis/passes/inspect"
14+
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
15+
"golang.org/x/tools/go/ast/inspector"
16+
"golang.org/x/tools/go/types/typeutil"
17+
)
18+
19+
//go:embed doc.go
20+
var doc string
21+
22+
// Analyzer is the defer analyzer.
23+
var Analyzer = &analysis.Analyzer{
24+
Name: "defer",
25+
Requires: []*analysis.Analyzer{inspect.Analyzer},
26+
Doc: analysisutil.MustExtractDoc(doc, "defer"),
27+
Run: run,
28+
}
29+
30+
func run(pass *analysis.Pass) (interface{}, error) {
31+
if !analysisutil.Imports(pass.Pkg, "time") {
32+
return nil, nil
33+
}
34+
35+
checkDeferCall := func(node ast.Node) bool {
36+
switch v := node.(type) {
37+
case *ast.CallExpr:
38+
fn, ok := typeutil.Callee(pass.TypesInfo, v).(*types.Func)
39+
if ok && fn.Name() == "Since" && fn.Pkg().Path() == "time" {
40+
pass.Reportf(v.Pos(), "call to time.Since is not deferred")
41+
}
42+
case *ast.FuncLit:
43+
return false // prune
44+
}
45+
return true
46+
}
47+
48+
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
49+
50+
nodeFilter := []ast.Node{
51+
(*ast.DeferStmt)(nil),
52+
}
53+
54+
inspect.Preorder(nodeFilter, func(n ast.Node) {
55+
d := n.(*ast.DeferStmt)
56+
ast.Inspect(d.Call, checkDeferCall)
57+
})
58+
59+
return nil, nil
60+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package defers_test
6+
7+
import (
8+
"testing"
9+
10+
"golang.org/x/tools/go/analysis/analysistest"
11+
"golang.org/x/tools/go/analysis/passes/defers"
12+
)
13+
14+
func Test(t *testing.T) {
15+
testdata := analysistest.TestData()
16+
analysistest.Run(t, testdata, defers.Analyzer, "a")
17+
}

go/analysis/passes/defers/doc.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package defers defines an Analyzer that checks for common mistakes in defer
6+
// statements.
7+
//
8+
// # Analyzer defer
9+
//
10+
// defer: report common mistakes in defer statements
11+
//
12+
// The defer analyzer reports a diagnostic when a defer statement would
13+
// result in a non-deferred call to time.Since, as experience has shown
14+
// that this is nearly always a mistake.
15+
//
16+
// For example:
17+
//
18+
// start := time.Now()
19+
// ...
20+
// defer recordLatency(time.Since(start)) // error: call to time.Since is not deferred
21+
//
22+
// The correct code is:
23+
//
24+
// defer func() { recordLatency(time.Since(start)) }()`
25+
package defers

0 commit comments

Comments
 (0)