Ruleguard by example: Local functions

package gorules

import "github.com/quasilyte/go-ruleguard/dsl"

// Sometimes we find ourselves repeating the parts of Where()
// clause in several rules.
// Other times we use some conditions that may be
// more clear if we would give them a better name.
// In normal Go, we use functions for that.

func exposedMutex(m dsl.Matcher) {
	// isExported reports whether bound matcher var
	// represents exported Go identifier.
	isExported := func(v dsl.Var) bool {
		return v.Text.Matches(`^\p{Lu}`)
	}

	// isExported() is more readable than `^\p{Lu}`
	// regular expression itself.

	m.Match(`type $name struct { $*_; sync.Mutex; $*_ }`).
		Where(isExported(m["name"])).
		Report("do not embed sync.Mutex")

	m.Match(`type $name struct { $*_; sync.RWMutex; $*_ }`).
		Where(isExported(m["name"])).
		Report("don not embed sync.RWMutex")
}
package main

import "sync"

type EmbedsMutex struct {
	key int
	sync.Mutex
}

type unexportedEmbedsMutex struct {
	sync.Mutex
}

func main() {}

Notes: