doc.go (6399B)
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 /* 6 The deadcode command reports unreachable functions in Go programs. 7 8 Usage: deadcode [flags] package... 9 10 The deadcode command loads a Go program from source then uses Rapid 11 Type Analysis (RTA) to build a call graph of all the functions 12 reachable from the program's main function. Any functions that are not 13 reachable are reported as dead code, grouped by package. 14 15 Packages are expressed in the notation of 'go list' (or other 16 underlying build system if you are using an alternative 17 golang.org/x/go/packages driver). Only executable (main) packages are 18 considered starting points for the analysis. 19 20 The -test flag causes it to analyze test executables too. Tests 21 sometimes make use of functions that would otherwise appear to be dead 22 code, and public API functions reported as dead with -test indicate 23 possible gaps in your test coverage. Bear in mind that an Example test 24 function without an "Output:" comment is merely documentation: 25 it is dead code, and does not contribute coverage. 26 27 The -filter flag restricts results to packages that match the provided 28 regular expression; its default value matches the listed packages and any other 29 packages belonging to the same modules. Use -filter= to display all results. 30 31 Example: show all dead code within the gopls module: 32 33 $ deadcode -test golang.org/x/tools/gopls/... 34 35 The analysis can soundly analyze dynamic calls though func values, 36 interface methods, and reflection. However, it does not currently 37 understand the aliasing created by //go:linkname directives, so it 38 will fail to recognize that calls to a linkname-annotated function 39 with no body in fact dispatch to the function named in the annotation. 40 This may result in the latter function being spuriously reported as dead. 41 42 By default, the tool does not report dead functions in generated files, 43 as determined by the special comment described in 44 https://go.dev/s/generatedcode. Use the -generated flag to include them. 45 46 The tool also does not report marker interface methods by default. 47 Marker interface methods are typically used to create compile-time constraints 48 to ensure that only specific types can implement a particular interface. 49 These methods have no other functionality (empty function body) and are never invoked. 50 Although marker interface methods are technically unreachable, removing them would break 51 the interface implementation. Hence, the tool excludes them from the report. 52 53 In any case, just because a function is reported as dead does not mean 54 it is unconditionally safe to delete it. For example, a dead function 55 may be referenced by another dead function, and a dead method may be 56 required to satisfy an interface that is never called. 57 Some judgement is required. 58 59 The analysis is valid only for a single GOOS/GOARCH/-tags configuration, 60 so a function reported as dead may be live in a different configuration. 61 Consider running the tool once for each configuration of interest. 62 Consider using a line-oriented output format (see below) to make it 63 easier to compute the intersection of results across all runs. 64 65 # Output 66 67 The command supports three output formats. 68 69 With no flags, the command prints the name and location of each dead 70 function in the form of a typical compiler diagnostic, for example: 71 72 $ deadcode -f='{{range .Funcs}}{{println .Position}}{{end}}' -test ./gopls/... 73 gopls/internal/protocol/command.go:1206:6: unreachable func: openClientEditor 74 gopls/internal/template/parse.go:414:18: unreachable func: Parsed.WriteNode 75 gopls/internal/template/parse.go:419:18: unreachable func: wrNode.writeNode 76 77 With the -json flag, the command prints an array of Package 78 objects, as defined by the JSON schema (see below). 79 80 With the -f=template flag, the command executes the specified template 81 on each Package record. So, this template shows dead functions grouped 82 by package: 83 84 $ deadcode -f='{{println .Path}}{{range .Funcs}}{{printf "\t%s\n" .Name}}{{end}}{{println}}' -test ./gopls/... 85 golang.org/x/tools/gopls/internal/lsp 86 openClientEditor 87 88 golang.org/x/tools/gopls/internal/template 89 Parsed.WriteNode 90 wrNode.writeNode 91 92 # Why is a function not dead? 93 94 The -whylive=function flag explain why the named function is not dead 95 by showing an arbitrary shortest path to it from one of the main functions. 96 (To enumerate the functions in a program, or for more sophisticated 97 call graph queries, use golang.org/x/tools/cmd/callgraph.) 98 99 Fully static call paths are preferred over paths involving dynamic 100 edges, even if longer. Paths starting from a non-test package are 101 preferred over those from tests. Paths from main functions are 102 preferred over paths from init functions. 103 104 The result is a list of Edge objects (see JSON schema below). 105 Again, the -json and -f=template flags may be used to control 106 the formatting of the list of Edge objects. 107 The default format shows, for each edge in the path, whether the call 108 is static or dynamic, and its source line number. For example: 109 110 $ deadcode -whylive=bytes.Buffer.String -test ./cmd/deadcode/... 111 golang.org/x/tools/cmd/deadcode.main 112 static@L0117 --> golang.org/x/tools/go/packages.Load 113 static@L0262 --> golang.org/x/tools/go/packages.defaultDriver 114 static@L0305 --> golang.org/x/tools/go/packages.goListDriver 115 static@L0153 --> golang.org/x/tools/go/packages.goListDriver$1 116 static@L0154 --> golang.org/x/tools/go/internal/packagesdriver.GetSizesForArgsGolist 117 static@L0044 --> bytes.Buffer.String 118 119 # JSON schema 120 121 type Package struct { 122 Name string // declared name 123 Path string // full import path 124 Funcs []Function // list of dead functions within it 125 } 126 127 type Function struct { 128 Name string // name (sans package qualifier) 129 Position Position // file/line/column of function declaration 130 Generated bool // function is declared in a generated .go file 131 Marker bool // function is a marker interface method 132 } 133 134 type Edge struct { 135 Initial string // initial entrypoint (main or init); first edge only 136 Kind string // = static | dynamic 137 Position Position // file/line/column of call site 138 Callee string // target of the call 139 } 140 141 type Position struct { 142 File string // name of file 143 Line, Col int // line and byte index, both 1-based 144 } 145 */ 146 package main