Help us shape the future of Go! Take the 2026 Go Developer Survey

sidecar

package
v0.4.8 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package sidecar carries the format-agnostic logic for YAML sidecar files: the <target>.clover.yaml (or .yml) that holds update rules for a target that cannot host an inline clover: comment, strict JSON being the canonical case. It owns the discovery rule (which names are sidecars and which target they govern), decoding a sidecar document into one directive per entry, and the find line-locator that resolves an entry to the single target line it rewrites. It depends only on directive and pattern, never on scan, so scan can import it without a cycle and remain the sole builder of scan.File.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Locate

func Locate(lines []string, d directive.Directive) (int, error)

Locate resolves a sidecar entry's target line within lines via its locator (see Locator.Locate). Callers resolving several entries against the same file should share a Locator, which amortizes the per-file parse work across entries.

func Names

func Names(target string) []string

Names returns the candidate sidecar file names for target, in precedence order (.yaml before .yml), so a caller can probe for an existing sidecar or resolve which one wins when both are present.

func Refresh

func Refresh(
	data []byte,
	lines []string,
	keysFor func(provider string) []string,
	refresh func(line int, d directive.Directive) (directive.Directive, bool),
	fresh []directive.Directive,
) ([]byte, error)

Refresh re-emits a sidecar with selected entries patched in place. Each entry is parsed and located via its own locator; for one that locates, refresh may return a replacement directive (re-rendered in canonical order, carrying the entry's comments across - including any note on its keys). An entry that does not parse or does not locate is kept verbatim - so a force pass never deletes an unresolvable or hand-written entry it cannot reproduce - and the document's comments survive. The fresh entries are appended. lines is the located target's content, the source the locators resolve against.

func Render

func Render(entries []directive.Directive, keysFor func(provider string) []string) ([]byte, error)

Render serializes directive entries as a canonical YAML sidecar document. Each entry is rendered in canonical key order via the shared codec; keysFor supplies an entry's provider keys, kept a callback so this format-agnostic package never depends on the provider registry. It is the writer annotate generates new sidecars with - and the canonical form format re-emits toward.

func Schema

func Schema() []byte

Schema returns the embedded sidecar JSON schema document.

func SchemaURL

func SchemaURL() string

SchemaURL returns the schema's published location, read from its own $id so the document is the single source of truth for the URL a docs modeline points at.

func Target

func Target(name string) (string, bool)

Target reports the target file name a sidecar name governs: name with the .clover.yaml / .clover.yml suffix removed. ok is false when name is not a sidecar name, or when removing the suffix leaves an empty base - the bare .clover.yaml / .clover.yml configs, which are config, never sidecars.

Types

type Canonical

type Canonical struct {
	Content []byte
	Pruned  []string
	Changed bool
}

Canonical is the outcome of re-emitting a sidecar: the canonical bytes, the unknown keys a prune removed, and whether the bytes differ from the input.

func Canonicalize

func Canonicalize(
	data []byte,
	keysFor func(provider string) []string,
	prune bool,
) (Canonical, error)

Canonicalize re-emits a sidecar in canonical form: each entry's keys are reordered and its tags normalized, while every comment survives (the entry node is rebuilt in place and [carryComments] re-homes its own head, line, and foot comments plus any note on an individual key or value, and the document's own comments are kept by re-marshaling the parsed tree). With prune set, an entry's unknown keys are stripped; without it, an unknown key is rejected with an error so a stale key cannot pass a format gate. A structurally broken sidecar - one that does not parse, or whose entry is malformed - is left untouched (Changed false, no error): lint owns those diagnostics, not format.

type Entry

type Entry struct {
	Directive directive.Directive
	Line      int
	Err       error
}

Entry is one sidecar list item: its directive, the 1-based source line it was written on (for diagnostics), and any error from decoding that single entry.

func Entries

func Entries(data []byte) ([]Entry, error)

Entries decodes a sidecar document into one entry per top-level list item. The document must be a YAML sequence; each item is decoded with directive.ParseYAML, and a single malformed item is reported in its own Entry.Err rather than failing the whole document. A document that is not a sequence is a hard error.

type Leaf

type Leaf struct {
	Key   string
	Value string
	Line  int
	JQ    string
}

Leaf is a string-valued scalar in a JSON document, the unit annotate proposes a sidecar entry from: the object key that holds it (the last path segment, empty for array elements), its value, the 0-based line it sits on, and a jq expression that resolves uniquely to that line. Only leaves whose locator round-trips - jq resolves back to the leaf's own line, and nowhere else - are returned, so a generated locator is robust by construction.

func Leaves

func Leaves(source []byte) ([]Leaf, error)

Leaves enumerates the string-valued scalars in a JSON document, each paired with a verified jq locator, in line order. It is the recognition half of annotate's sidecar generation: the caller decides which leaves name a trackable reference. Source that does not parse as JSON yields an error, since only a JSON target carries a jq-locatable structure. A leaf whose locator the resolver would point elsewhere is dropped - an earlier member of a duplicated key, or a leaf below a shadowed duplicate ancestor.

A single position-aware descent records every string scalar's path and byte offset at once, so the cost is linear in the document size rather than the per-leaf re-parse-and-re-walk a naive enumeration would pay. Only a document the walk saw a duplicated key in pays for a second, structure-decoding parse to arbitrate which members survive.

type Locator added in v0.3.10

type Locator struct {
	// contains filtered or unexported fields
}

Locator resolves sidecar entries against one target file's lines. The per-file work a jq locator needs - joining the lines, indexing every value's byte offset in a single position-aware walk, and decoding the document for gojq path derivation - is done once, on first need, and shared by every entry. A Locator is not safe for concurrent use.

func NewLocator added in v0.3.10

func NewLocator(lines []string) *Locator

NewLocator returns a Locator resolving entries against lines, the target's LF-normalized content.

func (*Locator) Locate added in v0.3.10

func (l *Locator) Locate(d directive.Directive) (int, error)

Locate resolves one entry's target line via its locator. An entry must carry find or jq (neither present is a hard error). jq resolves the line by JSON path - robust against a duplicated version string or reordered keys - and a composing find then refines the region within that line at rewrite time; find alone scans for the single line whose content matches a glob or /regex/.

Jump to

Keyboard shortcuts

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