Documentation
¶
Overview ¶
Package scupper filters a Go coverage profile, removing blocks that the source has explicitly marked as excluded via comment directives. This lets a project set a 100% line-coverage target where "100%" means "all code that should be covered is covered" — build wiring, impossible error branches, and generated code are excluded visibly in the source itself.
A scupper is a deck drain that lets water run off deliberately; here it lets explicitly-marked lines drain out of the coverage count.
Four directive styles are supported:
//scupper:ignore — ignore the line it appears on (trailing or own-line) //scupper:ignore-start — begin an ignored block //scupper:ignore-end — end an ignored block //scupper:ignore-file — ignore the entire file
The default directive keyword is "scupper:ignore"; it is configurable so a project can adopt its own convention.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Block ¶
type Block struct {
File string // profile file token (import-path based), verbatim
StartLine int
StartCol int
EndLine int
EndCol int
NumStmt int
Count int
}
Block is one entry in a Go coverage profile: a half-open span of source with a statement count and a hit count.
file.go:startLine.startCol,endLine.endCol numStmt count
type Directives ¶
type Directives struct {
Line string // e.g. "scupper:ignore"
Start string // e.g. "scupper:ignore-start"
End string // e.g. "scupper:ignore-end"
File string // e.g. "scupper:ignore-file"
Func string // e.g. "scupper:ignore-func"
// RequireReason makes a directive without a trailing explanation a hard
// error. This enforces the "every dismissal is explicit and reviewable"
// rule — a bare `//coverage-ignore` is rejected; `//coverage-ignore: why`
// is accepted. The -end directive is exempt (it only closes a block whose
// -start already carries the reason).
RequireReason bool
}
Directives holds the configured comment keywords. Zero value is not usable; call DefaultDirectives.
func DefaultDirectives ¶
func DefaultDirectives(base string) Directives
DefaultDirectives returns the standard directive keywords built from base, e.g. base "scupper:ignore" yields "scupper:ignore-start" etc. Reasons are not required; set RequireReason on the result to enforce them.
type FileIgnore ¶
type FileIgnore struct {
WholeFile bool
// Ranges are inclusive [start,end] 1-based line numbers.
Ranges []Range
}
FileIgnore describes the ignored line ranges within a single source file.
func ScanFile ¶
func ScanFile(path string, d Directives) (FileIgnore, error)
ScanFile reads path and returns the ignored ranges implied by its directive comments.
Block directives must be balanced and correctly ordered. Every misuse is a hard error rather than a silent swallow — because a tool whose value is "exclusions are visible and reviewable" must not quietly mis-handle a mistyped directive:
- an ignore-end with no open block (a stray or swapped end);
- a second ignore-start while a block is already open (blocks do not nest);
- an ignore-start with no matching ignore-end (unterminated at EOF).
func (FileIgnore) Covers ¶
func (fi FileIgnore) Covers(n int) bool
Covers reports whether line n falls within any ignored range (or the whole file is ignored).
func (FileIgnore) OverlapsRange ¶
func (fi FileIgnore) OverlapsRange(lo, hi int) bool
OverlapsRange reports whether the inclusive line span [lo,hi] intersects any ignored range (or the whole file is ignored). Used to match a profile block, which may span several lines, against a directive that sits on any one of them.
type FilterResult ¶
type FilterResult struct {
Kept *Profile
RemovedStmts int // statements dropped because they were in ignored ranges
IgnoredFiles []string
}
FilterResult reports what Filter did.
func Filter ¶
func Filter(p *Profile, res *Resolver, d Directives) (*FilterResult, error)
Filter removes profile blocks that fall within ignored ranges of their source file. A block is removed if its start line is within an ignored range; this matches the intent of marking a statement or branch as ignored. Whole-file ignores drop every block for that file.
scanCache memoizes FileIgnore per resolved path so each source file is read once.
type Profile ¶
Profile is a parsed coverage profile.
func ParseProfile ¶
ParseProfile reads a Go coverage profile (the output of `go test -coverprofile`).
func (*Profile) Merge ¶
Merge collapses duplicate blocks — blocks sharing a span and statement count that appear more than once — into a single block whose count is the max of the duplicates. This is required to read a profile produced with `go test -coverpkg=./...`, where a package's blocks are emitted once per test binary that instruments it (count 0 from a binary that never runs them, count >0 from one that does). Taking the max means "covered by ANY run", matching how `go tool cover` and go-test-coverage merge such profiles. Without this, the same statement is counted several times — once covered, once not — producing a coverage number that is both wrong and below reality.
Block order is preserved by first appearance. A profile without duplicates is returned unchanged in effect (every block maps to itself).
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver maps a profile file token (import-path based, e.g. "example.com/mod/pkg/file.go") to an absolute path on disk. Resolution uses `go list` for the packages it encounters, cached per package directory.
func NewResolver ¶
NewResolver returns a Resolver that resolves packages relative to dir (the module root or any dir inside the module).
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
scupper
command
Command scupper enforces a REACHABILITY floor over a Go coverage profile: was every line executed at least once by some test, or explicitly dismissed with a reasoned //scupper:ignore directive? It filters the profile against those directives, then reports reachability and (optionally) enforces a threshold.
|
Command scupper enforces a REACHABILITY floor over a Go coverage profile: was every line executed at least once by some test, or explicitly dismissed with a reasoned //scupper:ignore directive? It filters the profile against those directives, then reports reachability and (optionally) enforces a threshold. |