Ruleguard by example: Submatches

package gorules

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

func dupArg(m dsl.Matcher) {
	// The pattern string can contain *submatch variables*.
	//
	// $_ is an unnamed submatch variable, it matches any kind of AST element.
	// $<name> (e.g. $x) is a named submatch variable; it also matches anything.
	// Repeated named variable requires all submatches to be identical, like in pattern matching.
	//
	// If named submatch is used in Report() argument string, it will be interpolated.
	// $$ will be replaced with an entire match (like $0 in regular expressions).
	m.Match(`strings.ReplaceAll($_, $x, $x)`).
		Report(`suspicious duplicated arg $x`)
}
package main

import "strings"

var path string

func main() {
	s := "Hello, world"
	println(strings.ReplaceAll(s, "_", "_")) // $x="_"
	part := "x"
	println(strings.ReplaceAll(path+"/local/bin/", part, part)) // $x=part

	println(strings.ReplaceAll(s, "_", "")) // Doesn't match
}

Notes: