Skip to content

formatter: improve compact formatting for signatures, calls, logs, and composites#2

Open
starius wants to merge 11 commits into
bhandras:masterfrom
starius:loop-fixes
Open

formatter: improve compact formatting for signatures, calls, logs, and composites#2
starius wants to merge 11 commits into
bhandras:masterfrom
starius:loop-fixes

Conversation

@starius
Copy link
Copy Markdown

@starius starius commented May 19, 2026

Summary

This updates the next formatter to handle the formatting shapes found during downstream adoption: compacting simple nested calls, keeping short return/result groups packed, normalizing awkward partial signature splits, improving printf/error formatting, and making elided composite literal formatting more consistent. The examples below are representative of the behavioral changes rather than a commit-by-commit list.

Compact simple nested single-argument calls

Before:

maxPrepayRoutingFee := getMaxRoutingFee(
	btcutil.Amount(
		quote.PrepayAmtSat,
	),
)

After:

maxPrepayRoutingFee := getMaxRoutingFee(
	btcutil.Amount(quote.PrepayAmtSat),
)

Keep blank lines before final returns

After compacting prior calls, the formatter still keeps the generic blank-line-before-return rule.

Before:

err := finalizedHtlcTx.Deserialize(
	bytes.NewReader(
		row.FinalizedHtlcTx,
	),
)
return err

After:

err := finalizedHtlcTx.Deserialize(
	bytes.NewReader(row.FinalizedHtlcTx),
)

return err

Pack simple multi-result returns

Simple nested calls in return values are packed when they fit.

Before:

return args.Get(0).(chan *chainntnfs.TxConfirmation), args.Get(1).(chan error), args.Error(
	2,
)

After:

return args.Get(0).(chan *chainntnfs.TxConfirmation),
	args.Get(1).(chan error), args.Error(2)

Move single named params only in the already-split result shape

The single named parameter compaction is intentionally narrow: it applies to signatures where arguments are already split and the results start after ) (. It does not use this rule to rewrite already-good shapes such as a multiline parameter with inline results.

Before:

func rpcRouteCancel(
	details *outCancelDetails) (
	*veryLongRouteCancelResponseWithAdditionalSuffix, error) {

	return nil, nil
}

After:

func rpcRouteCancel(details *outCancelDetails) (
	*veryLongRouteCancelResponseWithAdditionalSuffix, error) {

	return nil, nil
}

Normalize partial return-list splits

When a partial return-list split is awkward, the formatter moves the parameter down and packs short results.

Before:

func unmarshalFixedPoint2(fp *looprpc.FixedPoint) (*rfqmath.BigIntFixedPoint,
	error) {

	return nil, nil
}

After:

func unmarshalFixedPoint2(
	fp *looprpc.FixedPoint) (*rfqmath.BigIntFixedPoint, error) {

	return nil, nil
}

Split long printf/error format strings while keeping short arguments attached

Before:

return fmt.Errorf("this is a long error message with a couple (%d) place holders", len(things))

After:

return fmt.Errorf("this is a long error message with a couple (%d) "+
	"place holders", len(things))

Keep nested errorf format strings inline when the nested call fits

Before:

return f.HandleError(
	fmt.Errorf(
		"invalid swap invoice hash: expected %x got %x",
		preimage.Hash(), payReq.Hash,
	),
)

After:

return f.HandleError(
	fmt.Errorf("invalid swap invoice hash: expected %x got %x",
		preimage.Hash(), payReq.Hash),
)

Compact single-element composite literals

This is generic and does not special-case any type name. The lntypes.Hash fixture is just a representative type-shaped example.

Before:

SwapHash: lntypes.Hash{
	1,
},
Marker: sampleMarker{
	"ready",
},

After:

SwapHash: lntypes.Hash{1},
Marker:   sampleMarker{"ready"},

Keep simple elided composite elements packed

Before:

hops := []*RouteHop{
	{},
	{},
	{},
}

After:

hops := []*RouteHop{
	{}, {}, {},
}

Expand keyed elided composite values

Adjacent keyed entries no longer share a line.

Before:

requiredOps := map[string][]PermissionOp{
	"/service/Action": {{
		Entity: "swap",
		Action: "execute",
	}, {
		Entity: "service",
		Action: "read",
	}},
}

After:

requiredOps := map[string][]PermissionOp{
	"/service/Action": {
		{
			Entity: "swap",
			Action: "execute",
		},
		{
			Entity: "service",
			Action: "read",
		},
	},
}

Validation

  • make self-check
  • make lint

starius added 11 commits May 19, 2026 04:45
Prefer breaking params before splitting small result lists for methods,
interface methods, and selected function literals. Also balance split
result lists when a signature cannot fit cleanly.

Before:

    ValidateAndTransform(input InputType, rules []ValidationRule,
        transformers []Transformer) (OutputType, []ValidationError,
        error)

After:

    ValidateAndTransform(input InputType, rules []ValidationRule,
        transformers []Transformer) (OutputType,
        []ValidationError, error)
Collapse over-expanded single-argument calls when the compact form fits.
Also pack multi-result returns when their simple expressions fit on
continuation lines.

Before:

    bytes.NewReader(
        row.FinalizedHtlcTx,
    )

After:

    bytes.NewReader(row.FinalizedHtlcTx)

Before:

    return args.Get(0).(chan *chainntnfs.TxConfirmation),
        args.Get(1).(chan error), args.Error(
        2,
    )

After:

    return args.Get(0).(chan *chainntnfs.TxConfirmation),
        args.Get(1).(chan error), args.Error(2)
Use the generic packed call layout for nested fmt.Errorf calls with
multiple value args when they are arguments to another call. This keeps
the format string attached to fmt.Errorf, avoiding a hanging call head.

Before:

    fmt.Errorf(
        "invalid swap invoice hash: expected %x got %x",
        preimage.Hash(), payReq.Hash,
    )

After:

    fmt.Errorf("invalid swap invoice hash: expected %x got %x",
        preimage.Hash(), payReq.Hash)
Keep single-element unkeyed composite literals compact when they fit.
Also split adjacent composite elements that were sharing a line.

Before:

    SwapHash: lntypes.Hash{
        1,
    }

After:

    SwapHash: lntypes.Hash{1}

Before:

    }, {

After:

    },
    {
Move already-split params back onto the func line only when the return
list starts on the next line after `) (` and at least one param fits
there. This fixes over-expanded shapes without changing signatures that
keep inline returns on the param continuation line.

Before:

    func rpcRouteCancel(
        details *outCancelDetails) (
        *RouteCancelResponse, error) {

After:

    func rpcRouteCancel(details *outCancelDetails) (
        *RouteCancelResponse, error) {

Preserved:

    func unmarshalFixedPoint(
        fp *looprpc.FixedPoint) (*rfqmath.BigIntFixedPoint, error) {
Keep value arguments on the final split format-string line when they
fit in a nested fmt.Errorf call.

Before:

    fmt.Errorf("invalid swap invoice hash: expected %x "+
        "got %x",
        preimage.Hash(), payReq.Hash)

After:

    fmt.Errorf("invalid swap invoice hash: expected %x "+
        "got %x", preimage.Hash(), payReq.Hash)
Keep {} and single-value elided elements together when they appear
inside a multiline composite literal.

Before:

    hops := []*RouteHop{
        {},
        {},
        {},
    }

After:

    hops := []*RouteHop{
        {}, {}, {},
    }
Expand outer braces for multiline keyed values made from nontrivial
elided composite elements.

Before:

    requiredOps := map[string][]PermissionOp{
        "/service/Action": {{
            Entity: "swap",
        }, {
            Entity: "service",
        }},
    }

After:

    requiredOps := map[string][]PermissionOp{
        "/service/Action": {
            {
                Entity: "swap",
            },
            {
                Entity: "service",
            },
        },
    }
Pack expanded simple elided composite elements when there is no
existing packed grouping to preserve. Leave simple keyed values
expanded, so a value like hB: { id } is not collapsed as a side
effect.

Before:

    preimages := []SamplePreimage{
        {1},
        {2},
        {3},
    }

After:

    preimages := []SamplePreimage{
        {1}, {2}, {3},
    }
When a regular function has one named parameter inline and a short
return list partially split after ) (, move the parameter to a
continuation line and pack the returns there.

This keeps the result stable when an input already has either bad
shape, while avoiding shared-name parameter groups and function
literals.

Before:

    func unmarshalFixedPoint2(fp *looprpc.FixedPoint) (
        *rfqmath.BigIntFixedPoint,
        error) {

After:

    func unmarshalFixedPoint2(
        fp *looprpc.FixedPoint) (*rfqmath.BigIntFixedPoint, error) {

Before:

    func unmarshalFixedPoint3(fp *looprpc.FixedPoint) (
        *rfqmath.BigIntFixedPoint, error) {

After:

    func unmarshalFixedPoint3(
        fp *looprpc.FixedPoint) (*rfqmath.BigIntFixedPoint, error) {
Apply the repository formatter output to non-golden source files so
make self-check passes its fmt-check step.

Use reflect.Indirect while estimating DSL rewrite iterations so govet
no longer reports the reflect.Ptr constant inline issue under the
Nix-provided golangci-lint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant