formatter

package
v0.0.0-...-af88cc4 Latest Latest
Warning

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

Go to latest
Published: Jan 7, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package formatter provides Go source code formatting utilities.

Index

Constants

View Source
const DefaultColumnLimit = 80

DefaultColumnLimit is the default maximum line length.

View Source
const DefaultTabStop = 8

DefaultTabStop is the default tab width for visual calculations.

Variables

View Source
var DefaultOperatorRules = []OperatorRule{
	{Op: ",", Priority: 0, Context: "case"},
	{Op: "||", Priority: 1, Context: "expr"},
	{Op: "&&", Priority: 2, Context: "expr"},
	{Op: "==", Priority: 3, Context: "expr"},
	{Op: "!=", Priority: 3, Context: "expr"},
	{Op: "+", Priority: 4, Context: "expr"},
	{Op: "-", Priority: 4, Context: "expr"},
}

DefaultOperatorRules defines standard Go formatting preferences.

Functions

func DefaultCallPatterns

func DefaultCallPatterns() []string

DefaultCallPatterns returns all default patterns.

func DefaultFmtPatterns

func DefaultFmtPatterns() []string

DefaultFmtPatterns returns the standard fmt function patterns.

func DefaultLogPatterns

func DefaultLogPatterns() []string

DefaultLogPatterns returns the standard log function patterns.

func DefaultMultilineExcludes

func DefaultMultilineExcludes() []string

DefaultMultilineExcludes returns function name substrings that the generic multiline call formatter should exclude from formatting.

These are calls handled by the log/printf stage, and keeping this list in one place avoids mismatches between stages (e.g. auto call-arg expression edits).

func FormatCallGreedy

func FormatCallGreedy(call []byte, wsIndent string, baseLen int, colLimit,
	ts int) string

FormatCallGreedy formats a function call using the greedy left-flow packing algorithm. This is exported for use by the DSL LeftFlowCallAction to ensure identical output between the DSL formatter and the legacy pipeline.

Parameters:

  • call: the raw bytes of the call expression (e.g., "log.Infof(...)")
  • wsIndent: the leading whitespace of the line
  • baseLen: visual width from line start to call start
  • colLimit: column limit (e.g., 80)
  • ts: tab stop width (e.g., 8)

Returns the formatted call as a string.

func FormatCallGreedyNext

func FormatCallGreedyNext(call []byte, wsIndent string, baseLen int, colLimit,
	ts int) string

FormatCallGreedyNext is an opt-in wrapper around the greedy call formatter intended for the "next" rule profile. It enables additional heuristics that are safe to evolve without breaking golden fixtures:

  • Join-aware string splitting when there are trailing call args, matching gofmt's context-sensitive spacing around '+'.
  • Reservation for the trailing ')' when deciding whether a final string literal fits, avoiding off-by-one overflow at the column limit.

func FormatCallPackedMultiLine

func FormatCallPackedMultiLine(call []byte, wsIndent string, colLimit,
	ts int) string

FormatCallPackedMultiLine is an exported wrapper around formatCallPackedMultiLine for use by the DSL engine. It formats a generic function call into a packed multi-line style when the single-line form would exceed the column limit.

Parameters:

  • call: the raw call expression bytes
  • wsIndent: the whitespace indent string for continuation lines
  • colLimit: column limit (e.g., 80)
  • ts: tab stop width (e.g., 8)

Returns the formatted call as a string.

func FormatCallPackedMultiLineNext

func FormatCallPackedMultiLineNext(call []byte, wsIndent string, colLimit,
	ts int) string

FormatCallPackedMultiLineNext is an opt-in wrapper around formatCallPackedMultiLineNext for use by the DSL engine and the "next" rule profile. It preserves legacy packed multiline output by default (FormatCallPackedMultiLine) and only applies next behavior when explicitly selected.

func FormatCompactCallsInSource

func FormatCompactCallsInSource(src []byte, cfg Config) ([]byte, bool)

FormatCompactCallsInSource applies the compact-call stage formatting to src using cfg and reports whether it changed anything.

This exists so DSL parity stages can delegate to the legacy implementation without importing the formatter package from the dsl package.

func FormatCompositeLiteralArg

func FormatCompositeLiteralArg(arg, contIndent string,
	forceExpand ...bool) (string, bool)

FormatCompositeLiteralArg detects a top-level composite literal in arg and formats its elements across multiple lines, indented under contIndent. It returns the formatted string and true if a composite literal was reformatted. If forceExpand is true, keyed maps/structs will always be expanded even if they fit inline. This is used when the containing call already has multiline elements.

func FormatFile

func FormatFile(src []byte) []byte

FormatFile applies formatting with default config and default targets. This is a convenience wrapper for callers that don't need custom config.

func FormatFuncSignature

func FormatFuncSignature(signature, indent string, colLimit,
	tabStop int) (string, bool)

FormatFuncSignature formats a function signature (the line starting with "func" up to and including the opening brace) using left-flow packing. This function is exported for use by the DSL engine. The signature parameter should be the complete func line ending with "{". Returns the formatted signature with a trailing newline if multi-line, and a boolean indicating if a blank line should be added after the opening brace.

func FormatFuncSignatureLegacy

func FormatFuncSignatureLegacy(signature, indent string, colLimit,
	tabStop int) (string, bool)

FormatFuncSignatureLegacy formats a function declaration signature using the legacy FuncSigFormatter implementation. This is used by native DSL signature rules to preserve parity while applying edits at AST-selected spans.

func FormatFuncSignatureNext

func FormatFuncSignatureNext(signature, indent string, colLimit,
	tabStop int) (string, bool)

FormatFuncSignatureNext formats a function declaration signature for the "next" profile. Unlike the legacy behavior, it will reflow some already-multiline signatures into a single line when they fit within the column limit.

Example:

func f() ( *T, error) {

becomes:

func f() (*T, error) {

func FormatFuncSigsInSource

func FormatFuncSigsInSource(src []byte, colLimit, tabStop int) ([]byte, bool)

FormatFuncSigsInSource applies the legacy function signature formatter to src and reports whether it changed anything.

This is exported so DSL stages can delegate to the legacy implementation without creating an import cycle.

func FormatInterfaceMethod

func FormatInterfaceMethod(method, indent string, colLimit,
	tabStop int) string

FormatInterfaceMethod formats an interface method declaration using left-flow packing. This function is exported for use by the DSL engine.

func FormatInterfaceMethodLegacy

func FormatInterfaceMethodLegacy(method, indent string, colLimit,
	tabStop int) string

FormatInterfaceMethodLegacy formats an interface method signature using the legacy FuncSigFormatter implementation.

func FormatInterfaceMethodNext

func FormatInterfaceMethodNext(method, indent string, colLimit,
	tabStop int) string

FormatInterfaceMethodNext formats an interface method signature for the "next" profile, using the same normalization/collapse behavior as FormatFuncSignatureNext.

func ValidatePipelineConfig

func ValidatePipelineConfig(cfg PipelineConfig) error

ValidatePipelineConfig performs best-effort validation of PipelineConfig.

This is intended to catch specification/config mistakes early (unknown style values) and provide actionable errors for CLI callers.

NewPipeline remains best-effort; callers that want strictness should validate up front.

Types

type BaseConfig

type BaseConfig struct {
	ColumnLimit int // Maximum line length (default: 80)
	TabStop     int // Tab width for visual calculations (default: 8)
}

BaseConfig holds common formatting configuration.

func NewBaseConfig

func NewBaseConfig(col, tab int) BaseConfig

NewBaseConfig creates a BaseConfig with defaults applied. Zero values are replaced with defaults.

func (BaseConfig) FirstLineWidth

func (c BaseConfig) FirstLineWidth(content string) int

FirstLineWidth returns the visual width of the first line in content.

func (BaseConfig) FitsInLimit

func (c BaseConfig) FitsInLimit(currentCol int, content string) bool

FitsInLimit checks if content at currentCol fits within the column limit.

func (BaseConfig) LastLineWidth

func (c BaseConfig) LastLineWidth(content string) int

LastLineWidth returns the visual width of the last line in content.

func (BaseConfig) Remaining

func (c BaseConfig) Remaining(currentCol int) int

Remaining returns how many columns remain before hitting the limit.

func (BaseConfig) Width

func (c BaseConfig) Width(s string) int

Width returns the visual width of a string, accounting for tabs.

func (BaseConfig) WidthFrom

func (c BaseConfig) WidthFrom(currentCol int, content string) int

WidthFrom returns the visual width after appending content starting from currentCol.

type BreakContext

type BreakContext struct {
	Elements   []string   // The elements to format (e.g., function arguments)
	Indent     Indent     // Current base indentation
	CurrentCol int        // Starting column position
	Config     BaseConfig // Formatting configuration
}

BreakContext provides context for breaking decisions.

type BreakResult

type BreakResult struct {
	Content string // The formatted content
	Broke   bool   // Whether line breaks were added
}

BreakResult contains the result of a breaking operation.

type Breaker

type Breaker interface {
	// Break splits elements to fit within the column limit.
	Break(ctx BreakContext) BreakResult
}

Breaker defines a strategy for breaking content across lines.

type CallRule

type CallRule struct {
	// Patterns are the function call prefixes to match (e.g., "log.Infof(",
	// "fmt.Errorf(")
	Patterns []string

	// Breaker is the strategy for breaking arguments.
	Breaker Breaker

	// Splitter defines how to split the argument body into elements. If
	// nil, DefaultCommaSplitter is used.
	Splitter ElementSplitter

	// Priority determines application order (higher = applied first).
	Priority int
}

CallRule formats function calls matching specific patterns.

func (*CallRule) Apply

func (r *CallRule) Apply(src []byte, pos int, cfg BaseConfig) ([]byte, int)

Apply implements Rule.

func (*CallRule) Match

func (r *CallRule) Match(src []byte, pos int) bool

Match implements Rule.

func (*CallRule) Name

func (r *CallRule) Name() string

Name implements Rule.

type CommaSplitter

type CommaSplitter struct {
	RespectAllBrackets bool // If true, respects (), [], and {}; otherwise just ()
}

CommaSplitter splits content by commas at depth 0.

func DefaultCommaSplitter

func DefaultCommaSplitter() *CommaSplitter

DefaultCommaSplitter creates a comma splitter that respects all bracket types.

func (*CommaSplitter) Split

func (s *CommaSplitter) Split(content string) []string

Split implements ElementSplitter.

type CompactCallFormatter

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

CompactCallFormatter implements compact packing formatting for function calls.

func NewCompactCallFormatter

func NewCompactCallFormatter(cfg Config) *CompactCallFormatter

NewCompactCallFormatter creates a new compact packing formatter with defaults.

func (*CompactCallFormatter) FormatFile

func (f *CompactCallFormatter) FormatFile(src []byte) []byte

FormatFile formats with the formatter's config.

func (*CompactCallFormatter) OwnedSpans

func (f *CompactCallFormatter) OwnedSpans(src []byte) llast.OffsetSpanSet

OwnedSpans returns the spans of calls that the compact call formatter would consider formatting. In the legacy pipeline, this stage typically runs before expression formatting, but exposing ownership allows the pipeline to enforce boundaries regardless of stage order.

type Config

type Config struct {
	ColumnLimit int
	TabStop     int
	Targets     []string
	// Excludes is a list of substrings; if any matches the callee name of a
	// non-target call, fallback formatting will skip that call. This
	// mirrors the legacy multiline-call exclude semantics
	// (strings.Contains).
	//
	// Note: This only applies to the fallback formatter
	// (FallbackNonTargets); targeted calls (Targets) are still formatted as
	// usual.
	Excludes []string
	// FallbackNonTargets enables formatting of non-targeted function calls
	// that exceed the column limit using a packed multi-line style.
	FallbackNonTargets bool
	// FallbackNonTargetsExcludeSelectors disables fallback formatting for
	// selector calls (e.g. `pkg.Func(...)` or `x.Method(...)`). This can be
	// useful in pipelines that want selector calls handled by a dedicated
	// multiline stage instead.
	FallbackNonTargetsExcludeSelectors bool

	// UseASTSelection switches this legacy call formatter from scan-based
	// call detection to AST-based call selection. The formatting logic
	// remains the same; only the "which calls do we consider next?"
	// selector changes.
	//
	// This is intentionally opt-in to preserve golden fixtures.
	UseASTSelection bool

	// SkipGofmt skips the internal gofmt pass, useful when running in a
	// pipeline that will run gofmt at the end.
	SkipGofmt bool

	// ParseSafe enables parse-safe behavior: if the formatter's output does
	// not successfully gofmt, the original input is returned unchanged.
	// This avoids returning syntactically invalid Go when a heuristic
	// rewrite goes wrong.
	ParseSafe bool
}

Config holds configuration for the compact packing formatter.

type DSLBundle

type DSLBundle struct {
	Comments       DSLStageSpec
	LogCalls       DSLStageSpec
	Expressions    DSLStageSpec
	MultiLineCalls DSLStageSpec
	Signatures     DSLStageSpec
	BlankLines     DSLStageSpec
}

DSLBundle is the cohesive per-stage DSL rule/config selection for a given StageOptions.

The intent is to make it easy to reason about "what rules run where" and to make selection an explicit, testable piece of logic.

func ResolveDSLBundle

func ResolveDSLBundle(opts StageOptions) DSLBundle

ResolveDSLBundle returns the cohesive per-stage DSL rule/config selection for the given stage options.

This is intentionally a single entrypoint so profile- and option-driven rule selection stays centralized and easy to test.

type DSLExprConfig

type DSLExprConfig struct {
	ColumnLimit   int
	TabStop       int
	Rules         []dsl.Rule // Custom rules (if nil, uses defaults)
	Trace         bool       // Enable DSL rule tracing to stderr
	TraceReasons  bool       // Include "why fired/didn't fire" reasons in DSL tracing
	NodeOrder     dsl.NodeOrder
	MaxIterations int // Override engine MaxIterations (0 keeps default)
	// AutoMaxIterations enables an AST-informed iteration cap (node-count
	// based) rather than a fixed constant. This is intended for stages that
	// legitimately need many iterations (e.g. signature formatting across
	// many declarations) while remaining protected against cycles.
	AutoMaxIterations bool
	DetectCycles      bool
	SkipGofmt         bool // Skip gofmt (pipelines may run gofmt once at end)

	StageName string

	// OwnedSpansFunc optionally declares which regions of the source this
	// stage "owns" for pipeline-level stage fighting prevention. When nil,
	// the stage declares no ownership.
	OwnedSpansFunc func(src []byte) llast.OffsetSpanSet

	// Budget provides optional safety guardrails for the DSL engine.
	Budget dsl.RewriteBudget
}

DSLExprConfig holds configuration for the DSL expression formatter.

type DSLExprFormatter

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

DSLExprFormatter uses the DSL engine to format expressions.

func NewDSLExprFormatter

func NewDSLExprFormatter(cfg DSLExprConfig) *DSLExprFormatter

NewDSLExprFormatter creates a new DSL-based expression formatter.

func (*DSLExprFormatter) FormatFile

func (f *DSLExprFormatter) FormatFile(src []byte) []byte

FormatFile formats the source file using DSL rules.

func (*DSLExprFormatter) OwnedSpans

func (f *DSLExprFormatter) OwnedSpans(src []byte) llast.OffsetSpanSet

func (*DSLExprFormatter) SetOwnershipRegistry

func (f *DSLExprFormatter) SetOwnershipRegistry(reg *OwnershipRegistry)

type DSLStageOptions

type DSLStageOptions struct {
	Trace        bool
	TraceReasons bool

	UseBlankLinesNative bool
	UseFuncSigsNative   bool

	AllowCallArgs bool
	AutoCallArgs  bool
}

type DSLStageSpec

type DSLStageSpec struct {
	Rules             []dsl.Rule
	NodeOrder         dsl.NodeOrder
	MaxIterations     int
	AutoMaxIterations bool
	DetectCycles      bool
}

DSLStageSpec describes how a single stage should run under the DSL engine. It intentionally mirrors DSLExprConfig fields that are policy-driven rather than derived from the file formatting config (column limit/tab stop).

type ElementSplitter

type ElementSplitter interface {
	Split(content string) []string
}

ElementSplitter defines how to split content into elements.

type Formatter

type Formatter interface {
	FormatFile(src []byte) []byte
}

Formatter defines a generic source formatter.

type FuncSigConfig

type FuncSigConfig struct {
	ColumnLimit int
	TabStop     int
	// CanonicalMultilineSigLists forces a gofmt-like formatting style for
	// multiline parameter and result lists. In particular, if a
	// parenthesized return list doesn't fit on one line, we prefer: f(...)
	// ( a, b, ) rather than partially breaking inside the list, e.g.:
	// f(...) (a, b)
	//
	// This is enabled for the "next" profile, but kept off for legacy
	// behavior to avoid changing golden fixtures.
	CanonicalMultilineSigLists bool

	// ReserveTrailingComma reserves space for a trailing comma on a line
	// when we might need to break before the next element. This helps avoid
	// placing a comma exactly on the column boundary (or overflowing by one
	// column) due to late comma insertion.
	ReserveTrailingComma bool

	// PreferInlineSmallReturnList prefers keeping small parenthesized
	// return lists (e.g. `([]T, error)`) on one line by breaking parameters
	// earlier.
	PreferInlineSmallReturnList bool

	// BreakLongFuncTypeParams enables breaking of function-typed parameters
	// when their inner parameter list exceeds the column limit (even when
	// there is no nested struct type).
	//
	// This is intentionally opt-in to preserve legacy fixtures; it is used
	// by the "next" profile to improve readability of long callback
	// signatures.
	BreakLongFuncTypeParams bool

	// FormatInlineStructParams forces signature reflow when parameters
	// include inline struct types with semicolons (which gofmt will expand
	// into multiline blocks). This is intentionally opt-in because it can
	// be a readability-only change even when no single line exceeds the
	// column limit.
	FormatInlineStructParams bool
}

FuncSigConfig holds configuration for the function signature formatter.

type FuncSigFormatter

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

FuncSigFormatter formats long function signatures by breaking them across lines.

func NewFuncSigFormatter

func NewFuncSigFormatter(cfg FuncSigConfig) *FuncSigFormatter

NewFuncSigFormatter creates a new function signature formatter with defaults.

func (*FuncSigFormatter) FormatFile

func (f *FuncSigFormatter) FormatFile(src []byte) []byte

FormatFile formats long function signatures in the source file.

type Indent

type Indent struct {
	Base    string // Leading whitespace of the line (spaces and tabs)
	TabStop int    // Tab width for visual width calculations
}

Indent tracks indentation for a formatting context.

func IndentFromLine

func IndentFromLine(src []byte, lineStart int, tabStop int) Indent

IndentFromLine extracts the indentation from a line in the source. lineStart is the position of the first character of the line.

func IndentFromSource

func IndentFromSource(src []byte, pos int, tabStop int) Indent

IndentFromSource extracts the indentation for the line containing pos.

func NewIndent

func NewIndent(base string, tabStop int) Indent

NewIndent creates an Indent with the given base whitespace.

func (Indent) Bytes

func (i Indent) Bytes() []byte

Bytes returns the indentation as a byte slice.

func (Indent) Column

func (i Indent) Column() int

Column returns the column position after this indentation (same as Width).

func (Indent) Continuation

func (i Indent) Continuation() Indent

Continuation returns a new Indent with one additional tab for continuation lines.

func (Indent) FitsContent

func (i Indent) FitsContent(content string, cfg BaseConfig) bool

FitsContent checks if content starting after this indentation fits within the column limit.

func (Indent) IsEmpty

func (i Indent) IsEmpty() bool

IsEmpty returns true if the indentation is empty.

func (Indent) String

func (i Indent) String() string

String returns the base indentation string.

func (Indent) Width

func (i Indent) Width() int

Width returns the visual width of the base indentation.

func (Indent) WithExtra

func (i Indent) WithExtra(extra string) Indent

WithExtra returns a new Indent with additional whitespace appended.

func (Indent) WithSpaces

func (i Indent) WithSpaces(n int) Indent

WithSpaces returns a new Indent with n additional spaces.

type LeftFlowBreaker

type LeftFlowBreaker struct {
	Separator     string // Separator between elements (e.g., ", ")
	OpenBracket   string // Opening bracket (e.g., "(")
	CloseBracket  string // Closing bracket (e.g., ")")
	TrailingComma bool   // Add trailing comma before closing bracket
}

LeftFlowBreaker packs elements left-to-right, breaking when limit exceeded. Used for: function call arguments, list elements.

func NewLeftFlowBreaker

func NewLeftFlowBreaker() *LeftFlowBreaker

NewLeftFlowBreaker creates a new LeftFlowBreaker with default settings for function calls.

func (*LeftFlowBreaker) Break

Break implements Breaker for left-flow packing.

type NoopFormatter

type NoopFormatter struct{}

NoopFormatter returns its input unchanged. It is used as a stage placeholder when a pipeline disables a stage without falling back to legacy behavior.

func (NoopFormatter) FormatFile

func (NoopFormatter) FormatFile(src []byte) []byte

type OperatorRule

type OperatorRule struct {
	Op       string // The operator (e.g., "&&", "||", ",")
	Priority int    // Lower = break first (prefer breaking here)
	Context  string // Where this applies (e.g., "expr", "case", "call")
}

OperatorRule defines how to break at a specific operator.

type OwnedSpanProvider

type OwnedSpanProvider interface {
	OwnedSpans(src []byte) llast.OffsetSpanSet
}

OwnedSpanProvider is an optional interface that a stage formatter can implement to declare which regions of the source it conceptually "owns".

Ownership is used to prevent stage fighting by allowing earlier stages to avoid rewriting inside spans that will be formatted later.

type OwnershipAware

type OwnershipAware interface {
	SetOwnershipRegistry(reg *OwnershipRegistry)
}

OwnershipAware is an optional interface that a stage formatter can implement to receive pipeline-level ownership information about later stages.

type OwnershipPolicy

type OwnershipPolicy struct {
	Registry  *OwnershipRegistry
	StageName string
}

OwnershipPolicy describes how a stage should treat pipeline ownership spans.

The default policy is "forbid edits that overlap any spans owned by other stages in the current pass". This prevents stage fighting when multiple stages could rewrite the same region.

func NewOwnershipPolicy

func NewOwnershipPolicy(reg *OwnershipRegistry,
	stageName string) OwnershipPolicy

func (OwnershipPolicy) ForbiddenSpans

func (p OwnershipPolicy) ForbiddenSpans() llast.OffsetSpanSet

type OwnershipRegistry

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

OwnershipRegistry holds owned spans for a specific formatting pass.

The registry is always scoped to the current source snapshot. Pipelines that want robustness across stage rewrites should recompute the registry between stages, rather than attempting to map offsets through edits.

func BuildOwnershipRegistry

func BuildOwnershipRegistry(src []byte, stages []Stage) *OwnershipRegistry

BuildOwnershipRegistry computes owned spans for the provided stages on the given source snapshot.

func (*OwnershipRegistry) AllOwned

func (r *OwnershipRegistry) AllOwned() llast.OffsetSpanSet

AllOwned returns the union of all owned spans.

func (*OwnershipRegistry) AllOwnedAfter

func (r *OwnershipRegistry) AllOwnedAfter(
	stageName string) llast.OffsetSpanSet

AllOwnedAfter returns the union of owned spans declared by stages that run after the provided stage name.

This supports a directional ownership policy: earlier stages should avoid rewriting spans that later stages "own", but later stages are allowed to rewrite inside earlier-stage owned spans as part of the pipeline.

func (*OwnershipRegistry) AllOwnedExcept

func (r *OwnershipRegistry) AllOwnedExcept(
	stageName string) llast.OffsetSpanSet

AllOwnedExcept returns the union of all owned spans except those owned by the provided stage name.

func (*OwnershipRegistry) ByStage

func (r *OwnershipRegistry) ByStage(stageName string) (llast.OffsetSpanSet,
	bool)

ByStage returns the span set owned by a specific stage name, if present.

type Pipeline

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

Pipeline orchestrates all formatters in sequence and runs gofmt once at the end.

func NewPipeline

func NewPipeline(cfg PipelineConfig) *Pipeline

NewPipeline creates a new formatting pipeline with the given config.

func NewPipelineWithStages

func NewPipelineWithStages(cfg PipelineConfig, stages []Stage) *Pipeline

NewPipelineWithStages creates a pipeline with custom stages.

func (*Pipeline) Config

func (p *Pipeline) Config() BaseConfig

Config returns the pipeline's base configuration.

func (*Pipeline) Format

func (p *Pipeline) Format(src []byte) []byte

Format applies all formatters in sequence and runs gofmt at the end.

func (*Pipeline) Plan

func (p *Pipeline) Plan() PipelinePlan

Plan returns the resolved plan for this pipeline.

func (*Pipeline) Stages

func (p *Pipeline) Stages() []Stage

Stages returns the pipeline's stages for inspection.

type PipelineConfig

type PipelineConfig struct {
	ColumnLimit            int
	TabStop                int
	MoveInlineAbove        bool     // For comment formatter
	Excludes               []string // Functions to exclude from multiline formatting
	UseDSLComments         bool     // Use DSL-based comment formatting (delegates to legacy)
	UseDSLLogCalls         bool     // Use DSL-based log/printf call formatting
	UseDSLMultiLineCalls   bool     // Use DSL-based multiline call formatting
	DSLMultiLineStyle      string   // DSL multiline formatting style (empty => legacy)
	UseDSLExpr             bool     // Use DSL-based expression formatter
	UseDSLFuncSigs         bool     // Use DSL-based signature formatter (delegates to legacy)
	UseDSLFuncSigsNative   bool     // Use native DSL signature rules (fallback to legacy)
	DSLSigsStyle           string   // DSL signature style: legacy|dsl (empty => legacy)
	UseDSLBlankLines       bool     // Use DSL-based blank line formatter
	UseDSLBlankLinesNative bool     // Use native DSL blank line rules (fallback to legacy)
	// DSLBlankLinesExtraIfErrReturn inserts a blank line before:
	//
	// if err != nil { return ... }
	//
	// This is intentionally opt-in because it is opinionated and may
	// interact with users' desired grouping/spacing style.
	DSLBlankLinesExtraIfErrReturn bool
	// LogCallsMinTailLen controls the minimum tail length for string splits
	// in printf/logcall formatting under the "next" profile. When 0, a
	// profile default is used.
	LogCallsMinTailLen int
	// LogCallsSelectorNames overrides the set of recognized printf-style
	// selector names for suffix-only matching (e.g. "Infof", "Errorf").
	// When empty, a built-in default set is used.
	LogCallsSelectorNames []string
	// LogCallsSelectorPrefixes restricts log/printf call selection (compact
	// logcall formatting) to selector calls whose receiver expression has
	// one of these prefixes (e.g. "rpcLog", "zap.L().Sugar()"). When empty,
	// the next profile matches any selector prefix.
	LogCallsSelectorPrefixes []string
	TraceDSL                 bool // Enable DSL rule tracing (only when UseDSLExpr)
	TraceDSLReasons          bool // Include "why fired/didn't fire" reasons in DSL tracing

	// UseOwnershipRegistry enables pipeline-level stage ownership
	// boundaries. When enabled, the pipeline will compute owned span sets
	// for later stages and provide them to earlier stages that support
	// ownership-aware behavior.
	//
	// This remains opt-in to preserve golden fixtures.
	UseOwnershipRegistry bool

	// AllowDSLCallArgs enables limited expression formatting within call
	// arguments when using the DSL expression stage.
	AllowDSLCallArgs bool

	// AutoDSLCallArgs enables limited expression formatting within call
	// arguments only for calls that are known to be ignored by later
	// call-formatting stages. This is less invasive than AllowDSLCallArgs
	// but may miss some cases.
	AutoDSLCallArgs bool

	// DSLExprLogicalStyle controls long &&/|| chain formatting inside the
	// DSL expression stage. Empty means legacy behavior.
	DSLExprLogicalStyle string

	// DSLExprArithmeticStyle controls long arithmetic chain formatting
	// inside the DSL expression stage. Empty means legacy behavior.
	DSLExprArithmeticStyle string

	// DSLExprCaseClauseStyle controls long `case A, B, ...:` list
	// formatting inside the DSL expression stage. Empty means legacy
	// behavior.
	DSLExprCaseClauseStyle string

	// DSLExprSelectorChainStyle controls long selector chain formatting
	// inside the DSL expression stage. Empty means legacy behavior.
	DSLExprSelectorChainStyle string

	// StagePlanOverride forces an explicit stage selection for the
	// pipeline. This is intended for controlled experiments and debugging.
	StagePlanOverride *StagePlan

	// MaxPipelineIterations controls how many full pipeline passes are
	// allowed. When > 0, the pipeline will run stages + gofmt repeatedly
	// until the output stabilizes (no changes) or a cycle is detected.
	//
	// When 0, NewPipeline runs a single pass. The CLI defaults to a small
	// fixpoint search (see `--fixpoint-iters`) because it tends to produce
	// more stable results on large files.
	MaxPipelineIterations int
}

PipelineConfig holds configuration for the formatting pipeline.

type PipelinePlan

type PipelinePlan struct {
	StagePlan StagePlan

	// Key style knobs
	DSLMultiLineStyle string
	DSLSigsStyle      string

	// Native toggles
	UseDSLFuncSigsNative   bool
	UseDSLBlankLinesNative bool
	// Extra blank-line behavior (native blank lines only).
	DSLBlankLinesExtraIfErrReturn bool

	// Expression style knobs
	DSLExprLogicalStyle       string
	DSLExprArithmeticStyle    string
	DSLExprCaseClauseStyle    string
	DSLExprSelectorChainStyle string

	// Call-args policies
	AllowDSLCallArgs bool
	AutoDSLCallArgs  bool
}

PipelinePlan is a best-effort summary of resolved pipeline behavior. It is designed for debugging and UX (e.g. CLI `--print-plan`).

func ResolvePipelinePlan

func ResolvePipelinePlan(cfg PipelineConfig) PipelinePlan

ResolvePipelinePlan returns the plan that would be used by NewPipeline after applying mode/policy bundles and safety adjustments.

type Preset

type Preset struct {
	Config    BaseConfig
	CallRules []CallRule
}

Preset defines a complete formatting configuration.

func DefaultPreset

func DefaultPreset() Preset

DefaultPreset returns the standard llformat configuration.

func NewPreset

func NewPreset(columnLimit, tabStop int) Preset

NewPreset creates a preset with the given configuration.

func (Preset) RuleMatcher

func (p Preset) RuleMatcher() *RuleMatcher

RuleMatcher creates a RuleMatcher from this preset.

func (Preset) ToRules

func (p Preset) ToRules() []Rule

ToRules converts the preset's call rules to a slice of Rule interface.

func (Preset) WithCallPatterns

func (p Preset) WithCallPatterns(patterns []string, breaker Breaker,
	priority int) Preset

WithCallPatterns returns a new Preset with additional call patterns.

type Rule

type Rule interface {
	// Name returns the rule's identifier for debugging/logging.
	Name() string

	// Match returns true if this rule applies at the given position.
	Match(src []byte, pos int) bool

	// Apply formats the matched content. Returns the replacement bytes and
	// the number of source bytes consumed.
	Apply(src []byte, pos int,
		cfg BaseConfig) (replacement []byte, consumed int)
}

Rule defines a formatting rule that can be applied to source.

type RuleMatcher

type RuleMatcher struct {
	Rules  []Rule
	Config BaseConfig
}

RuleMatcher applies multiple rules to source code.

func NewRuleMatcher

func NewRuleMatcher(rules []Rule, cfg BaseConfig) *RuleMatcher

NewRuleMatcher creates a RuleMatcher with the given rules.

func (*RuleMatcher) ApplyAt

func (m *RuleMatcher) ApplyAt(src []byte, pos int) ([]byte, int)

ApplyAt applies the first matching rule at position. Returns nil, 0 if no rule matches.

func (*RuleMatcher) MatchAt

func (m *RuleMatcher) MatchAt(src []byte, pos int) Rule

MatchAt returns the first matching rule at the given position, or nil.

type Scanner

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

Scanner provides stateful source scanning that skips strings and comments. It wraps the low-level scanner package utilities into a convenient struct.

func NewScanner

func NewScanner(src []byte) *Scanner

NewScanner creates a new Scanner for the given source.

func (*Scanner) Advance

func (s *Scanner) Advance() byte

Advance moves forward one byte and returns the byte that was at the current position. Returns 0 if at end.

func (*Scanner) AdvanceBy

func (s *Scanner) AdvanceBy(n int)

AdvanceBy moves forward by n bytes.

func (*Scanner) AtEnd

func (s *Scanner) AtEnd() bool

AtEnd returns true if the scanner is at the end of input.

func (*Scanner) IsAtBlockComment

func (s *Scanner) IsAtBlockComment() bool

IsAtBlockComment returns true if the current position is at a /* comment.

func (*Scanner) IsAtLineComment

func (s *Scanner) IsAtLineComment() bool

IsAtLineComment returns true if the current position is at a // comment.

func (*Scanner) IsAtString

func (s *Scanner) IsAtString() bool

IsAtString returns true if the current position is at a string start.

func (*Scanner) Len

func (s *Scanner) Len() int

Len returns the total length of the source.

func (*Scanner) Match

func (s *Scanner) Match(pattern string) bool

Match returns true if the source at current position matches the given string.

func (*Scanner) Peek

func (s *Scanner) Peek() byte

Peek returns the byte at the current position, or 0 if at end.

func (*Scanner) PeekAt

func (s *Scanner) PeekAt(offset int) byte

PeekAt returns the byte at the given offset from current position, or 0 if out of bounds.

func (*Scanner) Pos

func (s *Scanner) Pos() int

Pos returns the current position in the source.

func (*Scanner) Remaining

func (s *Scanner) Remaining() []byte

Remaining returns the source from current position to end.

func (*Scanner) RemainingFrom

func (s *Scanner) RemainingFrom(start int) []byte

RemainingFrom returns the source from start to the end.

func (*Scanner) ScanBalancedParen

func (s *Scanner) ScanBalancedParen() int

ScanBalancedParen finds the matching ')' starting from the current '('. Returns the position of ')' or -1 if not found. Does not advance position.

func (*Scanner) SetPos

func (s *Scanner) SetPos(pos int)

SetPos sets the current position.

func (*Scanner) SkipLiteral

func (s *Scanner) SkipLiteral() bool

SkipLiteral skips a string literal or comment at the current position. Returns true if something was skipped.

func (*Scanner) SkipLiterals

func (s *Scanner) SkipLiterals()

SkipLiterals advances past all contiguous string literals and comments.

func (*Scanner) SkipPastNewline

func (s *Scanner) SkipPastNewline() bool

SkipPastNewline advances past the next newline (if present).

func (*Scanner) SkipToNewline

func (s *Scanner) SkipToNewline()

SkipToNewline advances to the next newline or end of input.

func (*Scanner) SkipWhitespace

func (s *Scanner) SkipWhitespace()

SkipWhitespace advances past spaces and tabs (but not newlines).

func (*Scanner) Slice

func (s *Scanner) Slice(start, end int) []byte

Slice returns a slice of the source from start to end.

func (*Scanner) SliceFrom

func (s *Scanner) SliceFrom(start int) []byte

SliceFrom returns a slice from start to current position.

func (*Scanner) Source

func (s *Scanner) Source() []byte

Source returns the full source.

type SpacingOptions

type SpacingOptions struct {
	BlankBeforeReturn   bool // Add blank line before return statements
	BlankBetweenCases   bool // Add blank line between case blocks
	BlankBetweenMethods bool // Add blank line between methods
}

SpacingOptions controls blank line formatting.

type Stage

type Stage struct {
	// Name uniquely identifies this stage.
	Name string

	// Formatter is the formatter to apply.
	Formatter Formatter

	// Requires lists the names of stages that must run before this one.
	// This allows explicit dependency declaration rather than implicit
	// ordering.
	Requires []string
}

Stage represents a named formatting stage in the pipeline.

func DefaultStages

func DefaultStages(cfg BaseConfig, commentMoveInline bool,
	excludes []string) []Stage

DefaultStages returns the standard llformat stage configuration. This creates stages from the existing formatters with explicit dependencies.

func DefaultStagesWithOptions

func DefaultStagesWithOptions(cfg BaseConfig, opts StageOptions) []Stage

DefaultStagesWithOptions returns stages with full configuration options.

func NewStage

func NewStage(name string, formatter Formatter) Stage

NewStage creates a new stage with the given name and formatter.

func StageOrder

func StageOrder(stages []Stage) ([]Stage, error)

StageOrder validates and returns the execution order for stages. Returns an error if there are cycles or missing dependencies.

func (Stage) WithRequires

func (s Stage) WithRequires(requires ...string) Stage

WithRequires returns a new Stage with the given dependencies.

type StageMode

type StageMode string

StageMode describes whether a stage runs via the DSL engine or is disabled.

const (
	StageModeOff StageMode = "off"
	StageModeDSL StageMode = "dsl"
)

type StageOptions

type StageOptions struct {
	Selection StageSelectionOptions
	Style     StageStyleOptions
	DSL       DSLStageOptions
}

StageOptions contains options for configuring the stage pipeline.

type StagePlan

type StagePlan struct {
	Comments       StageMode
	LogCalls       StageMode
	Expressions    StageMode
	MultiLineCalls StageMode
	Signatures     StageMode
	BlankLines     StageMode
}

StagePlan is the coherent per-stage execution plan for a pipeline run.

llformat is next-only: callers can override the per-stage DSL/off plan, but there is no longer a user-facing "profile" selector.

type StageSelectionOptions

type StageSelectionOptions struct {
	StagePlan *StagePlan
}

type StageStyleOptions

type StageStyleOptions struct {
	CommentMoveInline bool
	Excludes          []string

	DSLMultiLineStyle string
	DSLSigsStyle      string
	// DSLLogCallsMinTailLen controls how aggressively the "next" log/printf
	// call formatter avoids leaving a tiny remainder segment on the next
	// line when splitting a long string literal. A value of 0 uses the
	// profile default.
	DSLLogCallsMinTailLen int
	// DSLLogCallsSelectorNames overrides the set of recognized printf-style
	// selector names for suffix-only matching. When empty, a built-in
	// default set is used.
	DSLLogCallsSelectorNames []string
	// DSLLogCallsSelectorPrefixes restricts log/printf call selection to
	// calls whose selector receiver expression has one of these prefixes.
	// When empty, the next profile targets any selector prefix.
	DSLLogCallsSelectorPrefixes []string
	// DSLBlankLinesExtraIfErrReturn controls whether native DSL blank line
	// rules should insert a blank line before `if err != nil { return ...
	// }` patterns.
	DSLBlankLinesExtraIfErrReturn bool

	DSLExprLogicalStyle       string
	DSLExprArithmeticStyle    string
	DSLExprCaseClauseStyle    string
	DSLExprSelectorChainStyle string
}

type VerticalBreaker

type VerticalBreaker struct {
	Separator     string // Separator (e.g., ",")
	OpenBracket   string // Opening bracket
	CloseBracket  string // Closing bracket
	TrailingComma bool   // Add trailing comma
}

VerticalBreaker puts each element on its own line. Used for: multi-line function calls (one arg per line).

func NewVerticalBreaker

func NewVerticalBreaker() *VerticalBreaker

NewVerticalBreaker creates a new VerticalBreaker with default settings.

func (*VerticalBreaker) Break

Break implements Breaker for vertical layout.

Jump to

Keyboard shortcuts

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