Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / go / pointer / example_test.go
1 // Copyright 2013 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 pointer_test
6
7 import (
8         "fmt"
9         "sort"
10
11         "golang.org/x/tools/go/callgraph"
12         "golang.org/x/tools/go/loader"
13         "golang.org/x/tools/go/pointer"
14         "golang.org/x/tools/go/ssa"
15         "golang.org/x/tools/go/ssa/ssautil"
16 )
17
18 // This program demonstrates how to use the pointer analysis to
19 // obtain a conservative call-graph of a Go program.
20 // It also shows how to compute the points-to set of a variable,
21 // in this case, (C).f's ch parameter.
22 //
23 func Example() {
24         const myprog = `
25 package main
26
27 import "fmt"
28
29 type I interface {
30         f(map[string]int)
31 }
32
33 type C struct{}
34
35 func (C) f(m map[string]int) {
36         fmt.Println("C.f()")
37 }
38
39 func main() {
40         var i I = C{}
41         x := map[string]int{"one":1}
42         i.f(x) // dynamic method call
43 }
44 `
45         var conf loader.Config
46
47         // Parse the input file, a string.
48         // (Command-line tools should use conf.FromArgs.)
49         file, err := conf.ParseFile("myprog.go", myprog)
50         if err != nil {
51                 fmt.Print(err) // parse error
52                 return
53         }
54
55         // Create single-file main package and import its dependencies.
56         conf.CreateFromFiles("main", file)
57
58         iprog, err := conf.Load()
59         if err != nil {
60                 fmt.Print(err) // type error in some package
61                 return
62         }
63
64         // Create SSA-form program representation.
65         prog := ssautil.CreateProgram(iprog, 0)
66         mainPkg := prog.Package(iprog.Created[0].Pkg)
67
68         // Build SSA code for bodies of all functions in the whole program.
69         prog.Build()
70
71         // Configure the pointer analysis to build a call-graph.
72         config := &pointer.Config{
73                 Mains:          []*ssa.Package{mainPkg},
74                 BuildCallGraph: true,
75         }
76
77         // Query points-to set of (C).f's parameter m, a map.
78         C := mainPkg.Type("C").Type()
79         Cfm := prog.LookupMethod(C, mainPkg.Pkg, "f").Params[1]
80         config.AddQuery(Cfm)
81
82         // Run the pointer analysis.
83         result, err := pointer.Analyze(config)
84         if err != nil {
85                 panic(err) // internal error in pointer analysis
86         }
87
88         // Find edges originating from the main package.
89         // By converting to strings, we de-duplicate nodes
90         // representing the same function due to context sensitivity.
91         var edges []string
92         callgraph.GraphVisitEdges(result.CallGraph, func(edge *callgraph.Edge) error {
93                 caller := edge.Caller.Func
94                 if caller.Pkg == mainPkg {
95                         edges = append(edges, fmt.Sprint(caller, " --> ", edge.Callee.Func))
96                 }
97                 return nil
98         })
99
100         // Print the edges in sorted order.
101         sort.Strings(edges)
102         for _, edge := range edges {
103                 fmt.Println(edge)
104         }
105         fmt.Println()
106
107         // Print the labels of (C).f(m)'s points-to set.
108         fmt.Println("m may point to:")
109         var labels []string
110         for _, l := range result.Queries[Cfm].PointsTo().Labels() {
111                 label := fmt.Sprintf("  %s: %s", prog.Fset.Position(l.Pos()), l)
112                 labels = append(labels, label)
113         }
114         sort.Strings(labels)
115         for _, label := range labels {
116                 fmt.Println(label)
117         }
118
119         // Output:
120         // (main.C).f --> fmt.Println
121         // main.init --> fmt.init
122         // main.main --> (main.C).f
123         //
124         // m may point to:
125         //   myprog.go:18:21: makemap
126 }