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

loomcheck

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: BSD-2-Clause Imports: 7 Imported by: 0

Documentation

Overview

Package loomcheck enforces "import the loom combinator instead of hand-rolling it" through a syntax-only AST check.

The failure mode it targets is subtle: an author loads the fp-go style skills, writes a small `func(x T) bool { return ... }` inline, and ships code that looks perfectly idiomatic while silently reinventing a combinator this module already exports. Nothing in the compiler, the formatter, or golangci-lint objects, so the duplication survives review.

The rule flags a function literal that

  1. takes one parameter and returns a single bool, and
  2. has a body of exactly one return statement whose expression matches a shape loom already covers.

Condition 2 keeps the signal high: by default only recognized shapes are reported, each with the exact loom replacement named in the message. Set Config.StrictAllPredicates to also flag single-return bool literals whose shape is not recognized, which surfaces candidates for new loom combinators.

Opt out per function with a doc comment carrying the directive and a non-empty reason:

// fp-go:allow-hand-rolled-predicate SDK fixes this callback shape
func adapter() { ... }

Usage mirrors pipelinecheck — drop a thin test into any package:

func TestNoHandRolledPredicates(t *testing.T) {
	loomcheck.Require(t, loomcheck.Config{Roots: []string{".."}})
}

Index

Constants

View Source
const DefaultAllowDirective = "fp-go:allow-hand-rolled-predicate"

DefaultAllowDirective exempts a function from the hand-rolled predicate rule. It must be followed by a non-empty reason.

Variables

This section is empty.

Functions

func Require

func Require(r Reporter, cfg Config)

Require fails r when Check reports any violation.

Types

type Config

type Config struct {
	// Roots are directories scanned recursively for non-test .go
	// files. Defaults to []string{"."} when empty.
	Roots []string

	// AllowDirective exempts a function from the rule. Defaults to
	// DefaultAllowDirective when empty.
	AllowDirective string

	// SkipDirs are directory base names skipped during the walk, in
	// addition to .git, testdata, vendor and node_modules.
	SkipDirs []string

	// StrictAllPredicates also reports single-return bool literals
	// whose shape has no known loom replacement. Off by default.
	StrictAllPredicates bool
}

Config configures a Check run.

type Reporter

type Reporter interface {
	Helper()
	Errorf(format string, args ...any)
	Fatalf(format string, args ...any)
}

Reporter is the subset of *testing.T that Require needs.

type Violation

type Violation struct {
	Position token.Position
	Function string
	Message  string
}

Violation is a single rule failure.

func Check

func Check(cfg Config) ([]Violation, error)

Check scans cfg.Roots and returns every hand-rolled predicate that lacks a valid exemption.

func (Violation) String

func (v Violation) String() string

String formats a violation as "position: function: message".

Jump to

Keyboard shortcuts

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