Documentation
¶
Overview ¶
Package match compares the blocks a scan found against the previous ledger and decides, per id, what happened (docs/SPEC.md §16 pass 3): ok, moved, changed, moved-unmarked, rewritten?, deleted, or new. It also classifies a change (§20) so a finding can say "signature changed" instead of "hash differs", and so a stability policy can decide whether prose flags.
The classifier here is the generic one that works without a grammar: whitespace, comment, value, body, renamed, moved. The syntax tier in ext/treesitter registers a Classifier that adds signature and type; the interface is in the root package and this package accepts the result.
Index ¶
Constants ¶
const DefaultFuzzyThreshold = 0.8
DefaultFuzzyThreshold is the difflib ratio at or above which a vanished block is reported as `rewritten?` against its best unmarked candidate (§35 decisions: diff ratio, 0.8).
Variables ¶
var StateValues = []State{StateOK, StateMoved, StateChanged, StateMovedUnmarked, StateRewritten, StateDeleted, StateNew}
StateValues is the canonical order.
Functions ¶
func BlockKey ¶
BlockKey is how a def is identified across scans and between readers: its id, its environment, and the branch it was published from. An id alone is not enough. `port` defined for prod and for dev is two blocks, and so is an id published from main and from a feature branch; keyed by id, each comparison used whichever came last — listing prod before dev reported a change nothing made, and a published branch made main look behind.
func Classify ¶
Classify is the generic classifier (§20) for two versions of a block. It never returns ClassWhitespace alone with other classes: whitespace-only differences are invisible because hashes are computed over normalized text, so two blocks that differ only in whitespace have equal hashes and never reach Compare's changed branch. It returns:
- renamed when the symbol changed
- moved when the file or line range changed (in addition to other classes)
- value for fact-shaped kinds
- comment when old content is known and every differing line is a comment
- signature or type when a declaration's head changed
- value (and type, when what is declared changed) for a one-line constant: `MaxRetries = 5` to `= 3` is a value change exactly as a YAML key's is, and `api` must flag it (bug 27)
- unknown when oldContent is empty: the old body was not available, and the difference is real but undescribed (§20); never body
- body otherwise
Types ¶
type Change ¶
type Change struct {
ID string
State State
// Old is the previous ledger row; zero for StateNew.
Old ledger.Row
// New is the current block; zero for StateDeleted and StateRewritten.
New block.Block
// Candidate is the unmarked block a vanished id was matched to, for
// StateMovedUnmarked and StateRewritten.
Candidate block.Block
// Ratio is the similarity for StateRewritten.
Ratio float64
// Classes is non-empty only for StateChanged.
Classes []block.Class
// Diff is the compact unified diff for StateChanged, empty otherwise. It
// is computed against Old.Content only when the caller supplied it via
// Options.OldContent; the ledger stores hashes, not bodies.
Diff string
// Flags reports whether the change should flag citing prose under the
// block's stability policy. False for every state except StateChanged.
Flags bool
}
Change is the comparison result for one id.
func Compare ¶
Compare matches current blocks against previous rows. Every previous and every current def — an id in an environment, see Key — appears exactly once in the result, sorted by id then environment, so a caller can rely on completeness.
type Classifier ¶
Classifier decides the classes of a change between two versions of a block. The generic one is Classify; a grammar-aware one may replace it.
type Options ¶
type Options struct {
// FuzzyThreshold for rewritten?; zero means DefaultFuzzyThreshold.
FuzzyThreshold float64
// OldContent returns the body the block had in row, a previous ledger
// row, if the caller has it (from git at the ledger's commit, or the
// body store). It is handed the row rather than an id because an id
// alone cannot say which of several defs is meant — one per
// environment, one per published branch — and a by-id lookup served
// another environment's body. The row also carries its repo, so the
// same hook can answer for a foreign block. Nil, or a miss, means no
// diff and a hash difference classified as unknown (value for fact
// kinds), never body: `api` does not flag body, so guessing body for a
// change nobody could read let a signature change pass (bug 28).
OldContent func(row ledger.Row) (string, bool)
// Classify overrides the generic classifier.
Classify Classifier
// CommentPrefixes lists line-comment prefixes for the block's language so
// comment-only changes can be detected without a grammar. The caller
// derives it from extract.Styles; empty disables comment detection.
CommentPrefixes func(file string) []string
}
Options tunes matching.
type State ¶
type State string
State is what happened to an id between the previous ledger and now.
const ( StateOK State = "ok" // same hash, same place StateMoved State = "moved" // same hash, new file or lines StateChanged State = "changed" // same id, different hash StateMovedUnmarked State = "moved-unmarked" // id gone, a block with the same hash exists elsewhere StateRewritten State = "rewritten?" // id gone, a similar block exists; a guess, reported as such StateDeleted State = "deleted" // id gone, nothing similar StateNew State = "new" // id not in the previous ledger )