1 | <!--{ |
---|---|
2 | "Title": "Static analysis features of godoc" |
3 | }--> |
4 | |
5 | <style> |
6 | span.err { 'font-size:120%; color:darkred; background-color: yellow; } |
7 | img.ss { margin-left: 1in; } /* screenshot */ |
8 | img.dotted { border: thin dotted; } |
9 | </style> |
10 | |
11 | <!-- Images were grabbed from Chrome/Linux at 150% zoom, and are |
12 | displayed at 66% of natural size. This allows users to zoom a |
13 | little before seeing pixels. --> |
14 | |
15 | <p> |
16 | When invoked with the <code>-analysis</code> flag, godoc performs |
17 | static analysis on the Go packages it indexes and displays the |
18 | results in the source and package views. This document provides a |
19 | brief tour of these features. |
20 | </p> |
21 | |
22 | <h2>Type analysis features</h2> |
23 | <p> |
24 | <code>godoc -analysis=type</code> performs static checking similar |
25 | to that done by a compiler: it detects ill-formed programs, resolves |
26 | each identifier to the entity it denotes, computes the type of each |
27 | expression and the method set of each type, and determines which |
28 | types are assignable to each interface type. |
29 | |
30 | <b>Type analysis</b> is relatively quick, requiring about 10 seconds for |
31 | the >200 packages of the standard library, for example. |
32 | </p> |
33 | |
34 | <h3>Compiler errors</h3> |
35 | <p> |
36 | If any source file contains a compilation error, the source view |
37 | will highlight the errant location in red. Hovering over it |
38 | displays the error message. |
39 | </p> |
40 | <img class="ss" width='811' src='error1.png'><br/> |
41 | |
42 | <h3>Identifier resolution</h3> |
43 | <p> |
44 | In the source view, every referring identifier is annotated with |
45 | information about the language entity it refers to: a package, |
46 | constant, variable, type, function or statement label. |
47 | |
48 | Hovering over the identifier reveals the entity's kind and type |
49 | (e.g. <code>var x int</code> or <code>func f |
50 | func(int) string</code>). |
51 | </p> |
52 | <img class="ss" width='652' src='ident-field.png'><br/> |
53 | <br/> |
54 | <img class="ss" width='652' src='ident-func.png'> |
55 | <p> |
56 | Clicking the link takes you to the entity's definition. |
57 | </p> |
58 | <img class="ss" width='652' src='ident-def.png'><br/> |
59 | |
60 | <h3>Type information: size/alignment, method set, interfaces</h3> |
61 | <p> |
62 | Clicking on the identifier that defines a named type causes a panel |
63 | to appear, displaying information about the named type, including |
64 | its size and alignment in bytes, its |
65 | <a href='https://golang.org/ref/spec#Method_sets'>method set</a>, and its |
66 | <i>implements</i> relation: the set of types T that are assignable to |
67 | or from this type U where at least one of T or U is an interface. |
68 | |
69 | This example shows information about <code>net/rpc.methodType</code>. |
70 | </p> |
71 | <img class="ss" width='470' src='typeinfo-src.png'> |
72 | <p> |
73 | The method set includes not only the declared methods of the type, |
74 | but also any methods "promoted" from anonymous fields of structs, |
75 | such as <code>sync.Mutex</code> in this example. |
76 | |
77 | In addition, the receiver type is displayed as <code>*T</code> or |
78 | <code>T</code> depending on whether it requires the address or just |
79 | a copy of the receiver value. |
80 | </p> |
81 | <p> |
82 | The method set and <i>implements</i> relation are also available |
83 | via the package view. |
84 | </p> |
85 | <img class="ss dotted" width='716' src='typeinfo-pkg.png'> |
86 | |
87 | <h2>Pointer analysis features</h2> |
88 | <p> |
89 | <code>godoc -analysis=pointer</code> additionally performs a precise |
90 | whole-program <b>pointer analysis</b>. In other words, it |
91 | approximates the set of memory locations to which each |
92 | reference—not just vars of kind <code>*T</code>, but also |
93 | <code>[]T</code>, <code>func</code>, <code>map</code>, |
94 | <code>chan</code>, and <code>interface</code>—may refer. This |
95 | information reveals the possible destinations of each dynamic call |
96 | (via a <code>func</code> variable or interface method), and the |
97 | relationship between send and receive operations on the same |
98 | channel. |
99 | </p> |
100 | <p> |
101 | Compared to type analysis, pointer analysis requires more time and |
102 | memory, and is impractical for code bases exceeding a million lines. |
103 | </p> |
104 | |
105 | <h3>Call graph navigation</h3> |
106 | <p> |
107 | When pointer analysis is complete, the source view annotates the |
108 | code with <b>callers</b> and <b>callees</b> information: callers |
109 | information is associated with the <code>func</code> keyword that |
110 | declares a function, and callees information is associated with the |
111 | open paren '<span style="color: dark-blue"><code>(</code></span>' of |
112 | a function call. |
113 | </p> |
114 | <p> |
115 | In this example, hovering over the declaration of the |
116 | <code>rot13</code> function (defined in strings/strings_test.go) |
117 | reveals that it is called in exactly one place. |
118 | </p> |
119 | <img class="ss" width='612' src='callers1.png'> |
120 | <p> |
121 | Clicking the link navigates to the sole caller. (If there were |
122 | multiple callers, a list of choices would be displayed first.) |
123 | </p> |
124 | <img class="ss" width='680' src='callers2.png'> |
125 | <p> |
126 | Notice that hovering over this call reveals that there are 19 |
127 | possible callees at this site, of which our <code>rot13</code> |
128 | function was just one: this is a dynamic call through a variable of |
129 | type <code>func(rune) rune</code>. |
130 | |
131 | Clicking on the call brings up the list of all 19 potential callees, |
132 | shown truncated. Many of them are anonymous functions. |
133 | </p> |
134 | <img class="ss" width='564' src='call3.png'> |
135 | <p> |
136 | Pointer analysis gives a very precise approximation of the call |
137 | graph compared to type-based techniques. |
138 | |
139 | As a case in point, the next example shows the dynamic call inside |
140 | the <code>testing</code> package responsible for calling all |
141 | user-defined functions named <code>Example<i>XYZ</i></code>. |
142 | </p> |
143 | <img class="ss" width='361' src='call-eg.png'> |
144 | <p> |
145 | Recall that all such functions have type <code>func()</code>, |
146 | i.e. no arguments and no results. A type-based approximation could |
147 | only conclude that this call might dispatch to any function matching |
148 | that type—and these are very numerous in most |
149 | programs—but pointer analysis can track the flow of specific |
150 | <code>func</code> values through the testing package. |
151 | |
152 | As an indication of its precision, the result contains only |
153 | functions whose name starts with <code>Example</code>. |
154 | </p> |
155 | |
156 | <h3>Intra-package call graph</h3> |
157 | <p> |
158 | The same call graph information is presented in a very different way |
159 | in the package view. For each package, an interactive tree view |
160 | allows exploration of the call graph as it relates to just that |
161 | package; all functions from other packages are elided. |
162 | |
163 | The roots of the tree are the external entry points of the package: |
164 | not only its exported functions, but also any unexported or |
165 | anonymous functions that are called (dynamically) from outside the |
166 | package. |
167 | </p> |
168 | <p> |
169 | This example shows the entry points of the |
170 | <code>path/filepath</code> package, with the call graph for |
171 | <code>Glob</code> expanded several levels |
172 | </p> |
173 | <img class="ss dotted" width='501' src='ipcg-pkg.png'> |
174 | <p> |
175 | Notice that the nodes for Glob and Join appear multiple times: the |
176 | tree is a partial unrolling of a cyclic graph; the full unrolling |
177 | is in general infinite. |
178 | </p> |
179 | <p> |
180 | For each function documented in the package view, another |
181 | interactive tree view allows exploration of the same graph starting |
182 | at that function. |
183 | |
184 | This is a portion of the internal graph of |
185 | <code>net/http.ListenAndServe</code>. |
186 | </p> |
187 | <img class="ss dotted" width='455' src='ipcg-func.png'> |
188 | |
189 | <h3>Channel peers (send ↔ receive)</h3> |
190 | <p> |
191 | Because concurrent Go programs use channels to pass not just values |
192 | but also control between different goroutines, it is natural when |
193 | reading Go code to want to navigate from a channel send to the |
194 | corresponding receive so as to understand the sequence of events. |
195 | </p> |
196 | <p> |
197 | Godoc annotates every channel operation—make, send, range, |
198 | receive, close—with a link to a panel displaying information |
199 | about other operations that might alias the same channel. |
200 | </p> |
201 | <p> |
202 | This example, from the tests of <code>net/http</code>, shows a send |
203 | operation on a <code>chan bool</code>. |
204 | </p> |
205 | <img class="ss" width='811' src='chan1.png'> |
206 | <p> |
207 | Clicking on the <code><-</code> send operator reveals that this |
208 | channel is made at a unique location (line 332) and that there are |
209 | three receive operations that might read this value. |
210 | |
211 | It hardly needs pointing out that some channel element types are |
212 | very widely used (e.g. struct{}, bool, int, interface{}) and that a |
213 | typical Go program might contain dozens of receive operations on a |
214 | value of type <code>chan bool</code>; yet the pointer analysis is |
215 | able to distinguish operations on channels at a much finer precision |
216 | than based on their type alone. |
217 | </p> |
218 | <p> |
219 | Notice also that the send occurs in a different (anonymous) function |
220 | from the outer one containing the <code>make</code> and the receive |
221 | operations. |
222 | </p> |
223 | <p> |
224 | Here's another example of send on a different <code>chan |
225 | bool</code>, also in package <code>net/http</code>: |
226 | </p> |
227 | <img class="ss" width='774' src='chan2a.png'> |
228 | <p> |
229 | The analysis finds just one receive operation that might receive |
230 | from this channel, in the test for this feature. |
231 | </p> |
232 | <img class="ss" width='737' src='chan2b.png'> |
233 | |
234 | <h2>Known issues</h2> |
235 | <p> |
236 | All analysis results pertain to exactly |
237 | one configuration (e.g. amd64 linux). Files that are conditionally |
238 | compiled based on different platforms or build tags are not visible |
239 | to the analysis. |
240 | </p> |
241 | <p> |
242 | Files that <code>import "C"</code> require |
243 | preprocessing by the cgo tool. The file offsets after preprocessing |
244 | do not align with the unpreprocessed file, so markup is misaligned. |
245 | </p> |
246 | <p> |
247 | Files are not periodically re-analyzed. |
248 | If the files change underneath the running server, the displayed |
249 | markup is misaligned. |
250 | </p> |
251 | <p> |
252 | Additional issues are listed at |
253 | <a href='https://go.googlesource.com/tools/+/master/godoc/analysis/README'>tools/godoc/analysis/README</a>. |
254 | </p> |
255 |
Members