deadsetgo

package module
v1.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2026 License: GPL-3.0 Imports: 1 Imported by: 0

README

deadset-go

Go Reference Go version Mutation

Deterministic whole-program dead-code analysis for a Go module and the consumers it declares.

⚠️ Pre-release software

deadset-go implements the deadset contract at the version describe prints. analyze reads a Go module and writes the contract's JSON report, rendered beside it as text, GitHub annotations, SARIF 2.1.0 or a template of yours; explain answers whether one symbol is live, retained, reported or judged by nothing, and why. At its 1.12.0 release the analyzer reports 73 findings over its own source, every one of them true: exports narrower than they are declared, fields a pass writes that nothing reads, methods whose bodies never name their receiver, and two declarations only a test names. A green go vet or golangci-lint beside that number is not a contradiction, because both run per package with tests included, and these are the two questions they do not ask.

Every report names the analyzer's conformance result in its analyzer.conformance block, and an orchestrator admits a pass and nothing else, so read that block rather than gating blind on a report. The contract version, the corpus version, the declared gaps, the platform set and the non-goals are in docs/conformance.md. The report shape, the exit codes and the configuration keys can change until 1.0.

What it does

deadset-go loads a Go module with its tests, type-checks it and reports the declarations nothing uses: a function nobody calls, a struct field nothing reads, an exported symbol no consumer imports, an interface no value is converted to. Every verdict comes from type information and the reference graph, never from a text search, so two runs over one tree produce one report. Every kind it reports, and what it treats as a use, is in docs/kinds.md.

Three properties separate it from a per-package linter:

  • Consumers are part of the program. A library's exported API is dead only when no declared consumer uses it. Name the repositories that import the module and the analysis loads them into one whole-program graph, so an export a downstream repository calls is never reported.
  • Exemptions are computed, not configured. A method that satisfies an interface a value of its type is converted to, a main, an init, a test function, a symbol a go:linkname directive names: each is held live by a documented exemption class, and print-retained lists every symbol an exemption held back and the class that held it. The nine classes are in docs/exemptions.md.
  • A cascade is one finding. When a dead function is the only caller of three more, the report names the root and counts what falls with it, so the deletion total is known before the edit.

It also reports over-visibility: an exported symbol only its own package uses, which can be unexported without a behavior change.

The output is a report, never an edit: a JSON document, one path:line:col text line per finding, or SARIF 2.1.0 for code-scanning upload. Every verb refuses a --fix flag with exit 2.

Quick start

go install github.com/cplieger/deadset-go/cmd/deadset-go@latest
deadset-go version

Installing needs Go 1.27 or later, and running needs the go toolchain on PATH, which loads the packages. deadset-go runs no language server and builds with cgo disabled, so a host with no C toolchain runs it.

Commands

Verb What it does
analyze Loads the module and its declared consumers, writes the report, exits with the verdict
explain Says why a symbol is dead, why it is live, or why it was not reported
print-config Prints the resolved configuration with the source of every setting
print-roots Prints the resolved root set
print-retained Prints every symbol an exemption held back, with the classes that held it
describe Prints the analyzer's name, version, contract version and conformance record as JSON
version Prints the analyzer version and the contract version

Exit codes follow the contract: 0 clean, 1 findings, 2 a usage error or a requested source edit, 3 a load or type-check failure, 4 a finding whose cross-language reference is unresolved. Every configuration key, every flag, the three suppression forms and the exit-code table are in docs/configuration.md.

How it relates to deadcode

golang.org/x/tools/cmd/deadcode answers a different question, and running both is worth it. deadcode builds a call graph from each main with rapid type analysis, which resolves calls through interfaces by tracking the types that reach run time, and reports the functions no call path reaches. deadset-go covers the symbol kinds a call graph has no node for (types, fields, constants, variables, interface methods, type parameters), treats a library's declared consumers as part of the program, and records on each finding which relation produced it: a reference count of zero, or unreachability from the roots. Run deadcode for the functions and deadset-go for everything else. The two liveness relations, the reachability classes, the build matrix and what leaves the analysis are in docs/analysis.md.

Security

deadset-go reads source and writes a report. It edits no file, and every verb refuses a --fix flag, or any flag whose name contains fix, with exit 2. It spawns no analysis process other than the Go toolchain's own go list, which resolves the module's dependencies as go build does, and it opens no network connection of its own: a module download happens only where go list would download, so a run against a populated module cache stays offline.

  • deadset-spec: the contract and the conformance corpus deadset-go implements and passes before each release.
  • deadset-ts: the same analysis for TypeScript and JavaScript. Neither analyzer can analyze the other's language: the TypeScript 7 compiler module github.com/microsoft/TypeScript/tsc keeps every analysis package under internal/, its programmatic surface is a TypeScript client over a private protocol, and no port of Go's type checker to JavaScript exists.
  • deadset: runs both analyzers over a repository holding both languages, resolves the references that cross the language boundary and merges the reports into one.

Dependencies

deadset-go allows itself two dependencies: the Go standard library and golang.org/x/tools, which supplies the package loader and the type information no reimplementation can. go version -m on a released binary lists nothing else. Renovate keeps the pins in go.mod current.

Contributing

Issues and pull requests are welcome. The general guidelines live in cplieger/.github.

Disclaimer

This project is built with care and follows security best practices, but it is intended for personal / self-hosted use. No guarantees of fitness for production environments. Use at your own risk.

This project was built with AI-assisted tooling using Claude, GPT, and Kiro. The human maintainer defines architecture, supervises implementation, and makes all final decisions.

License

GPL-3.0-or-later. See LICENSE.

Documentation

Overview

Package deadsetgo carries the two documents this analyzer commits about its own conformance, so the command can state what a reader of the repository opens.

The documents sit at the root of the repository, where a reader looks for what the analyzer declines and where the products that consume them read them. The command's own package cannot carry them from there: an embed pattern reaches no file above the directory of the package that declares it, and the digest a report states has to be taken over the bytes the binary holds, because a digest written beside the document it describes is a second copy of one fact and the two can disagree at any commit. This package exists for that one reason and holds nothing else.

Index

Constants

This section is empty.

Variables

View Source
var Gaps []byte

Gaps is conformance.json: the corpus version this analyzer answers and every capability it declines, with the reason for each.

View Source
var Results []byte

Results is conformance-results.json: the per-fixture record this analyzer's corpus runner wrote, the result over the whole corpus included. The digest a report states in its conformance block is the SHA-256 of these bytes.

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
cmd
deadset-go command
Command deadset-go reports unused symbols in a Go module and its declared consumers.
Command deadset-go reports unused symbols in a Go module and its declared consumers.
internal
catalog
Package catalog is the issue-kind vocabulary this analyzer reports under: one row per live kind, carrying the languages it applies to, the default a configuration overrides, the ceiling on the confidence a finding of the kind may claim, and what a mechanical edit may do with it.
Package catalog is the issue-kind vocabulary this analyzer reports under: one row per live kind, carrying the languages it applies to, the default a configuration overrides, the ceiling on the confidence a finding of the kind may claim, and what a mechanical edit may do with it.
config
Package config resolves the deadset configuration.
Package config resolves the deadset configuration.
deps
Package deps answers what a target's dependency declarations and its module graph say: which direct requirement no import needs, which replace directive redirects nothing, and which modules a deletion candidate holds the last use of.
Package deps answers what a target's dependency declarations and its module graph say: which direct requirement no import needs, which replace directive redirects nothing, and which modules a deletion candidate holds the last use of.
edges
Package edges reads the declared cross-language edges of one target: the pairs that say one symbol exists because a symbol in another language uses it.
Package edges reads the declared cross-language edges of one target: the pairs that say one symbol exists because a symbol in another language uses it.
exempt
Package exempt computes the exemptions of one loaded build configuration: the classes of reason for which a symbol the reference graph alone would report is live all the same.
Package exempt computes the exemptions of one loaded build configuration: the classes of reason for which a symbol the reference graph alone would report is live all the same.
graph
Package graph builds the graph of one loaded build configuration: the symbols a target declares, the references between them, and what the roots keep alive.
Package graph builds the graph of one loaded build configuration: the symbols a target declares, the references between them, and what the roots keep alive.
kinds
Package kinds turns one run's liveness answers into the findings a report carries.
Package kinds turns one run's liveness answers into the findings a report carries.
load
Package load resolves one build configuration of a target into type-checked packages, test variants included.
Package load resolves one build configuration of a target into type-checked packages, test variants included.
matrix
Package matrix derives a build matrix from a target tree: the platform and tag atoms its files name, plus the configuration of the host.
Package matrix derives a build matrix from a target tree: the platform and tag atoms its files name, plus the configuration of the host.
report
Package report is the document one analysis produces and the five renderings of it.
Package report is the document one analysis produces and the five renderings of it.
scope
Package scope resolves what a run loads: the module it analyzes and the consumers whose references count against it.
Package scope resolves what a run loads: the module it analyzes and the consumers whose references count against it.
suppress
Package suppress reads the two suppression mechanisms of one target: the inline directives its source carries, and the entries of the ignore file at its root.
Package suppress reads the two suppression mechanisms of one target: the inline directives its source carries, and the entries of the ignore file at its root.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL