deadsetgo

package module
v1.28.0 Latest Latest
Warning

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

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

README

deadset-go

Go Reference Go version Mutation

deadset-go finds dead code in a Go module and in the repositories that import it, and writes a report your CI can fail on.

It type-checks the module with its tests through golang.org/x/tools, its one run-time dependency, and reports without editing your code. It is in active development, so the report shape, exit codes and configuration keys can change between minor releases. It supports Linux only, needs Go 1.27.1 or later and is licensed under GPL-3.0-or-later.

Why use it

deadset-go is built for a CI gate on dead code across a module, with every verdict from type information and the reference graph.

  • It reports unused declarations, declarations only tests use, and tests of dead code.
  • It reports exports only their own package uses, fields written and never read, and uncalled interface methods.
  • Inside a function, it reports unused parameters, results and receivers, unreachable code and dead stores.
  • It loads the consumers you name, so an export a downstream repository calls is never reported.
  • Nine exemption classes hold back code that encoders, fmt, templates or reflection reach.
  • The same tree gives the same report, as JSON, text, GitHub annotations, SARIF 2.1.0 or your own template.

Consider deadcode if you want the functions no call path from a main package reaches. It follows calls through func values, interface methods and reflection, and -whylive shows the path that keeps a function live.

Install

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

Usage

deadset-go loads packages with the go toolchain on your PATH and never downloads a module, so run go mod download in the module and in every consumer first. Then create a deadset.json at the module root that says whether the module is an application or a library, and run analyze there:

echo '{ "target": { "kind": "application" } }' > deadset.json
deadset-go analyze --report=deadset-report.json

analyze writes the JSON report to deadset-report.json and a text rendering beside it as deadset-report.json.txt. Take this main.go:

package main

import "fmt"

type counter struct {
	count int
	label string
}

func (c *counter) increment() { c.count++ }

func greet(name string) string { return "hello " + name }

func farewell(name string) string { return "bye " + name }

func main() {
	c := &counter{label: "x"}
	c.increment()
	fmt.Println(greet("you"), c.count)
}

The text rendering lists two findings:

main.go:7:2: field counter.label: field counter.label is written once and never read [certain] (DS1301)
main.go:14:6: function farewell: unexported function has no reference in the target [certain] (DS1002)
summary: 2 findings (0 allow, 0 warn, 2 deny), 1 deletable line, 0 suppressions in effect, 0 reasons recorded, 0 stale suppressions, 0 pending, 0 omitted

The run exits 1 because the report holds a finding at deny severity, and 0 when it holds none. Common next steps:

  • Add --format=sarif or --format=github for a SARIF file or GitHub annotations. Naming any format replaces the text rendering, so add --format=text to keep it.
  • Run deadset-go explain farewell to see why one symbol is reported, retained, live or not reported.
  • To keep one declaration, put //deadset:ignore DS1002 -- <reason> on the line above it. To accept today's findings, add --baseline-write=deadset-baseline.json.

A library's unused exports are reported only when a scope document lists its consumers. Put a scope.json in a folder that holds the library and its consumers, with each path relative to that file:

{
  "target": { "path": "lib", "role": "target" },
  "consumers": [{ "path": "app", "role": "consumer" }]
}

Then run from that folder, with --target naming the library folder whose deadset.json says library:

deadset-go analyze --target=lib --scope=scope.json --report=deadset-report.json

API

deadset-go is a standalone command, and its interface is seven verbs, the JSON report and the exit codes.

  • analyze writes the report and exits with the verdict, and explain answers for one symbol.
  • print-config, print-roots and print-retained print the resolved configuration with each setting's source, the root set, and every symbol an exemption held back.
  • describe prints the analyzer, contract and schema versions and the conformance record as JSON, and version prints the analyzer and contract versions.
  • The run exits 0 when no finding fails it and 1 when one does. It exits 2 on a usage error or a refused source-edit flag, and 3 when the analysis fails before a verdict. It exits 4 when a finding is about a symbol a cross-language edge names, which only the merge in deadset can settle.

The report follows the deadset contract. Configuration and invocation lists every flag, setting and suppression form.

Unsupported by design

  • Source edits. Every verb only reports, and a flag whose name holds fix, edit, delete or rewrite exits with 2. The JSON report carries what an external codemod needs.
  • Network access. Consumers are local checkouts, and the toolchain runs with GOPROXY=off. A module missing from the module cache then stops the run with exit 3 where a declared or host configuration needs it.
  • Runtime evidence. Coverage profiles and production logs are not inputs.
  • Guesses. A kind ships only where its answer follows exactly from type information and the module graph.
  • Other languages. deadset-ts analyzes TypeScript and JavaScript.

Conformance, platforms and non-goals explains each one.

deadset-go implements the deadset contract, which fixes the issue codes, the report schema and the exit codes. It passes all 120 of the contract's conformance fixtures that carry a Go rendering, and every report names that result.

  • deadset-ts is the same analysis for TypeScript and JavaScript.
  • deadset runs both analyzers as one command and merges their reports, resolving the references between Go and TypeScript code.

Documentation

Contributing

See CONTRIBUTING.md.

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.
jsondoc
Package jsondoc encodes the JSON documents this analyzer writes: the report, its renderings, the resolved configuration and the describe document, each one value with a closing newline.
Package jsondoc encodes the JSON documents this analyzer writes: the report, its renderings, the resolved configuration and the describe document, each one value with a closing newline.
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.
memory
Package memory adapts a run to the memory the machine makes available: it holds the runtime's soft memory limit below the ceiling the machine allows, collects less often while the heap is far below it, and ends the run through its context when the analysis needs more than the machine has.
Package memory adapts a run to the memory the machine makes available: it holds the runtime's soft memory limit below the ceiling the machine allows, collects less often while the heap is far below it, and ends the run through its context when the analysis needs more than the machine has.
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.
reportdoc
Package reportdoc is the Contract's report document in Go: one field per member, in the schema's member order, with the JSON name the schema gives each.
Package reportdoc is the Contract's report document in Go: one field per member, in the schema's member order, with the JSON name the schema gives each.
reporttest
Package reporttest reads back a report document the report package wrote, which is what a test that runs the analyzer end to end and a round trip of the document compare against.
Package reporttest reads back a report document the report package wrote, which is what a test that runs the analyzer end to end and a round trip of the document compare against.
schema
Package schema checks a JSON document against a JSON Schema 2020-12 document written in the keywords the Contract's schemas use, and holds byte copies of the two schemas the report this analyzer writes is an instance of.
Package schema checks a JSON document against a JSON Schema 2020-12 document written in the keywords the Contract's schemas use, and holds byte copies of the two schemas the report this analyzer writes is an instance of.
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.
testsupport
Package testsupport holds what the tests of several packages share: a memo that builds one value per key for every test of a package asking for it, and a deep copy that hands each of those tests a value of its own.
Package testsupport holds what the tests of several packages share: a memo that builds one value per key for every test of a package asking for it, and a deep copy that hands each of those tests a value of its own.

Jump to

Keyboard shortcuts

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