
Linter GO basado en análisis que ejecuta reglas cargadas dinámicamente.
Usted escribe las reglas, ruleguard verifica si están satisfechos.
ruleguard tiene algunas similitudes con GitHub CodeQL, pero está dedicado a ir solo.
Características:
También se puede integrar fácilmente en otros analizadores estáticos. GO-Criticio se puede usar como ejemplo.
Se recomienda que obtenga un binario de la última versión {Linux/AMD64, Linux/ARM64, Darwin/AMD64, Darwin/ARM64, Windows/AMD64, Windows/ARM64}.
Si desea instalar el RuleGuard desde la fuente, es tan simple como:
# Installs a `ruleguard` binary under your `$(go env GOPATH)/bin`
$ go install -v github.com/quasilyte/go-ruleguard/cmd/ruleguard@latest
# Get the DSL package (needed to execute the ruleguard files)
$ go get -v -u github.com/quasilyte/go-ruleguard/dsl@latestSi dentro de un módulo GO, el paquete
dslse instalará para el módulo actual, de lo contrario instala el paquete en el $ Gopath y estará disponible a nivel mundial.
Si $GOPATH/bin está debajo de su $PATH del sistema, el comando ruleguard debería estar disponible después de eso:
$ ruleguard -help
ruleguard: execute dynamic gogrep-based rules
Usage: ruleguard [-flag] [package]
Flags:
-rules string
comma-separated list of ruleguard file paths
-e string
execute a single rule from a given string
-fix
apply all suggested fixes
-c int
display offending line with this many lines of context (default -1)
-json
emit JSON output Cree un archivo rules.go de prueba.
//go:build ruleguard
// +build ruleguard
package gorules
import "github.com/quasilyte/go-ruleguard/dsl"
func dupSubExpr ( m dsl. Matcher ) {
m . Match ( `$x || $x` ,
`$x && $x` ,
`$x | $x` ,
`$x & $x` ).
Where ( m [ "x" ]. Pure ).
Report ( `suspicious identical LHS and RHS` )
}
func boolExprSimplify ( m dsl. Matcher ) {
m . Match ( `!($x != $y)` ). Suggest ( `$x == $y` )
m . Match ( `!($x == $y)` ). Suggest ( `$x != $y` )
}
func exposedMutex ( m dsl. Matcher ) {
isExported := func ( v dsl. Var ) bool {
return v . Text . Matches ( `^p{Lu}` )
}
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 ( "do not embed sync.RWMutex" )
} Cree un example.go de prueba. Obtenga el archivo de destino:
package main
import "sync"
type EmbedsMutex struct {
key int
sync. Mutex
}
func main () {
var v1 , v2 int
println ( ! ( v1 != v2 ))
println ( ! ( v1 == v2 ))
if v1 == 0 && v1 == 0 {
println ( "hello, world!" )
}
} Ejecute ruleguard en ese archivo de destino:
$ ruleguard -rules rules.go -fix example.go
example.go:5:1: exposedMutex: do not embed sync.Mutex (rules.go:24)
example.go:12:10: boolExprSimplify: suggestion: v1 == v2 (rules.go:15)
example.go:13:10: boolExprSimplify: suggestion: v1 ! = v2 (rules.go:16)
example.go:14:5: dupSubExpr: suspicious identical LHS and RHS (rules.go:7) Desde que ejecutamos ruleguard con el argumento -fix , ambos cambios sugeridos se aplican a example.go .
También hay un modo -e que es útil durante la depuración de patrones:
$ ruleguard -e ' m.Match(`!($x != $y)`) ' example.go
example.go:12:10: ! (v1 ! = v2) Inserta automáticamente Report("$$") en el patrón especificado.
Puede usar la bandera -debug-group <name> para ver explicaciones sobre por qué algunas reglas rechazaron la coincidencia (por ejemplo, Where() condición falló).
La regla generada -e tendrá un nombre e , por lo que también se puede depurar.
Primero, analiza los archivos de reglas (por ejemplo, rules.go ) durante el inicio para cargar el conjunto de reglas.
Las reglas cargadas se utilizan para verificar los objetivos especificados (archivos GO, paquetes).
El archivo rules.go está escrito en términos de API dsl . Los archivos de reglas contienen un conjunto de funciones que sirven como grupos de reglas. Cada función acepta un solo argumento dsl.Matcher que luego se usa para definir y configurar reglas dentro del grupo.
Una definición de regla siempre comienza con la llamada del método de Match(patterns...) y termina con la llamada del método Report(message) .
Puede haber llamadas adicionales entre estos dos. Por ejemplo, una llamada Where(cond) aplica restricciones a una coincidencia para decidir si es aceptada o rechazada. Entonces, incluso si hay una coincidencia para un patrón, no producirá un mensaje de informe a menos que satisfaga una condición Where() .
Para que RuleGuard funcione, el paquete dsl debe estar disponible en tiempo de ejecución . Si no es así, verá un error como:
$ ruleguard -rules rules.go .
ruleguard: load rules: parse rules file: typechecker error: rules.go:6:8: could not import github.com/quasilyte/go-ruleguard/dsl (can't find import: "github.com/quasilyte/go-ruleguard/dsl")
Esto se soluciona agregando el paquete DSL al módulo:
$ ruleguard-test go get github.com/quasilyte/go-ruleguard/dsl
go: downloading github.com/quasilyte/go-ruleguard v0.3.18
go: downloading github.com/quasilyte/go-ruleguard/dsl v0.3.21
go: added github.com/quasilyte/go-ruleguard/dsl v0.3.21
$ ruleguard-test ruleguard -rules rules.go .
.../test.go:6:5: boolExprSimplify: suggestion: 1 == 0 (rules.go:9)
Si ha seguido el asesoramiento pasado de usar una restricción de compilación en el archivo Reglas Rules.go, así:
$ ruleguard-test head -4 rules.go
//go:build ignore
// +build ignore
package gorules
Va a notar que el archivo go.mod enumera el DSL como una dependencia indirecta:
$ grep dsl go.mod
require github.com/quasilyte/go-ruleguard/dsl v0.3.21 // indirect
Si ejecuta go mod tidy ahora, notará que el paquete DSL desaparece del archivo go.mod :
$ go mod tidy
$ grep dsl go.mod
$
Esto se debe a que go mod tidy se comporta como si todas las limitaciones de construcción estuvieran vigentes, con la excepción de ignore . Esto está documentado en el sitio web GO.
Esto se soluciona mediante el uso de una restricción de compilación diferente, como ruleguard o rules .
Nota: go-critic y go-perfguard incrustan las reglas utilizando la función de precompilación IR.