src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

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