format

package
v0.0.9 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package format provides single-responsibility visitors that together implement gofmt-style normalization. Each visitor handles one aspect:

  • TabsAndIndentsVisitor — re-indent post-newline whitespace
  • BlankLinesVisitor — collapse runs of >1 blank line and trim blank lines at block boundaries
  • SpacesVisitor — token-level spacing fixes (binary operators, commas, etc.)
  • RemoveTrailingWhitespaceVisitor — strip trailing space/tab from line endings inside Whitespace

AutoFormatVisitor composes the four into a fixed pipeline via DoAfterVisit. Each is independently usable for recipes that only need one pass.

All visitors honor a `stopAfter java.Tree` parameter: when non-nil, traversal halts after the given node has been visited, leaving downstream subtrees untouched. When nil, the entire visited subtree is processed.

The package is deliberately minimal. gofmt's full rule set (column alignment in const blocks, struct field tag alignment, etc.) is not implemented yet — recipes that need byte-exact gofmt output should pipe through the gofmt binary; AutoFormat targets the "splice in a synthesized subtree and put it at the right indent" use case.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AutoFormatVisitor

type AutoFormatVisitor struct {
	visitor.GoVisitor
	// contains filtered or unexported fields
}

AutoFormatVisitor composes the per-responsibility format visitors into a single end-to-end pipeline. The pipeline applies passes in a fixed order — each later pass relies on the structure normalized by the earlier ones:

  1. RemoveTrailingWhitespaceVisitor — strip trailing spaces/tabs
  2. BlankLinesVisitor — collapse blank-line runs
  3. TabsAndIndentsVisitor — re-indent post-newline whitespace
  4. SpacesVisitor — normalize intra-line spacing

Pass-1 runs first because pass-3 (re-indent) only touches the post- newline portion of a Whitespace; if pass-1 ran later, the trailing space/tabs of an earlier line could survive. Pass-2 runs before pass-3 because collapsing blank lines doesn't touch indents — it just removes whole `\n` characters — so pass-3 still has the right post-newline section to rewrite. Pass-4 runs last because changes within a binary/assignment don't affect whether a line carries a newline; spacing fixes can't disturb prior passes.

stopAfter is forwarded to every member visitor; pass nil to format the entire visited subtree.

func NewAutoFormatVisitor

func NewAutoFormatVisitor(stopAfter java.Tree) *AutoFormatVisitor

NewAutoFormatVisitor returns a composer visitor that, on its first Visit, queues the four per-responsibility passes via DoAfterVisit. The recipe runner's after-visit drain runs them in order. Each pass sees the partially-normalized tree from its predecessors.

func (*AutoFormatVisitor) Visit

func (v *AutoFormatVisitor) Visit(t java.Tree, p any) java.Tree

type BlankLinesVisitor

type BlankLinesVisitor struct {
	visitor.GoVisitor
	// contains filtered or unexported fields
}

BlankLinesVisitor enforces gofmt's blank-line rules:

  • Any run of >1 blank line collapses to one (anywhere in the compilation unit — gofmt's `1 blank line max` rule applies uniformly inside blocks AND between top-level decls).
  • Block.End loses any leading blank line so the closing brace sits flush against the last statement.
  • The first statement of a block has no blank line above it.

The first-statement rule reaches through the leftmost spine of the statement node — the parser places inter-statement whitespace on the *leftmost descendant* (Variable.Prefix, not Assignment.Prefix), so transformLeftmostPrefix walks down to find it.

func NewBlankLinesVisitor

func NewBlankLinesVisitor(stopAfter java.Tree) *BlankLinesVisitor

NewBlankLinesVisitor returns a visitor configured with the given stopAfter bound. Pass nil to format the entire visited tree.

func (*BlankLinesVisitor) Visit

func (v *BlankLinesVisitor) Visit(t java.Tree, p any) java.Tree

func (*BlankLinesVisitor) VisitBlock

func (v *BlankLinesVisitor) VisitBlock(block *java.Block, p any) java.J

func (*BlankLinesVisitor) VisitSpace

func (v *BlankLinesVisitor) VisitSpace(s java.Space, p any) java.Space

type RemoveTrailingWhitespaceVisitor

type RemoveTrailingWhitespaceVisitor struct {
	visitor.GoVisitor
	// contains filtered or unexported fields
}

RemoveTrailingWhitespaceVisitor strips trailing space/tab characters from the end of each line inside `Space.Whitespace` fields. Indent whitespace at the start of the next line is preserved.

Input: "foo \t\n bar" Output: "foo\n bar"

func NewRemoveTrailingWhitespaceVisitor

func NewRemoveTrailingWhitespaceVisitor(stopAfter java.Tree) *RemoveTrailingWhitespaceVisitor

NewRemoveTrailingWhitespaceVisitor returns a visitor configured with the given stopAfter bound. Pass nil to format the entire visited tree.

func (*RemoveTrailingWhitespaceVisitor) Visit

func (*RemoveTrailingWhitespaceVisitor) VisitSpace

type SpacesVisitor

type SpacesVisitor struct {
	visitor.GoVisitor
	// contains filtered or unexported fields
}

SpacesVisitor enforces gofmt's intra-line spacing rules:

  • One space around binary operators (`a + b`, not `a+b`).
  • No space around unary operators (`!x`, `-y`).
  • One space after commas in argument/parameter lists (RightPadded.After fields don't get touched here — they precede the comma, not follow it).
  • One space around `=` and `:=` (Assignment / VariableDeclarator).

Non-trivial whitespace (containing newlines) is preserved on the theory that it was authored deliberately. SpacesVisitor only fixes "0 spaces" and "2+ spaces" in single-line contexts; multi-line expressions are left to the author and the indent visitor.

func NewSpacesVisitor

func NewSpacesVisitor(stopAfter java.Tree) *SpacesVisitor

NewSpacesVisitor returns a visitor configured with the given stopAfter bound. Pass nil to format the entire visited tree.

func (*SpacesVisitor) Visit

func (v *SpacesVisitor) Visit(t java.Tree, p any) java.Tree

func (*SpacesVisitor) VisitAssignment

func (v *SpacesVisitor) VisitAssignment(a *java.Assignment, p any) java.J

func (*SpacesVisitor) VisitAssignmentOperation

func (v *SpacesVisitor) VisitAssignmentOperation(ao *java.AssignmentOperation, p any) java.J

func (*SpacesVisitor) VisitBinary

func (v *SpacesVisitor) VisitBinary(bin *java.Binary, p any) java.J

func (*SpacesVisitor) VisitUnary

func (v *SpacesVisitor) VisitUnary(u *java.Unary, p any) java.J

type TabsAndIndentsVisitor

type TabsAndIndentsVisitor struct {
	visitor.GoVisitor
	// contains filtered or unexported fields
}

TabsAndIndentsVisitor re-indents block-level whitespace to gofmt's `\t × depth` convention.

Strategy: rather than touching every Space in the tree (which would rewrite continuation alignments inside multi-line argument lists), the visitor drives indentation from VisitBlock explicitly:

  • For each `Block.Statements[i].Element`, the leftmost leaf's Prefix carries the inter-statement whitespace; we rewrite its indent (the post-newline portion) to `\t × (depth+1)`.
  • `Block.End` (the whitespace before `}`) is re-indented to `\t × depth`.
  • VisitCase decrements depth around the case-clause Prefix so `case` keywords align with the enclosing `switch` (gofmt convention) while body statements remain at body depth.

Whitespace that doesn't carry a newline, or whitespace inside an expression context (continuations, alignments) is left untouched.

func NewTabsAndIndentsVisitor

func NewTabsAndIndentsVisitor(stopAfter java.Tree) *TabsAndIndentsVisitor

NewTabsAndIndentsVisitor returns a visitor configured with the given stopAfter bound. Pass nil to format the entire visited tree.

func (*TabsAndIndentsVisitor) Visit

func (v *TabsAndIndentsVisitor) Visit(t java.Tree, p any) java.Tree

func (*TabsAndIndentsVisitor) VisitBlock

func (v *TabsAndIndentsVisitor) VisitBlock(block *java.Block, p any) java.J

VisitBlock dispatches the body at depth+1 and re-indents each statement's leftmost-leaf Prefix and the closing-brace `End`.

func (*TabsAndIndentsVisitor) VisitCase

func (v *TabsAndIndentsVisitor) VisitCase(c *java.Case, p any) java.J

VisitCase aligns the case keyword with the enclosing switch (one tab less than the switch body's depth) while keeping the case body statements at body depth. Also explicitly visits Body so nested blocks inside a case get their own indent fixes (the default GoVisitor.VisitCase doesn't recurse into Body).

Jump to

Keyboard shortcuts

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