| 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