package gorules
import "github.com/quasilyte/go-ruleguard/dsl"
// It's possible to compute the expression value if operands are constant expressions:
// literals, named constants and some other special kinds of constexprs.
func replaceAll(m dsl.Matcher) {
// Do you remember our older strings.Replace -> strings.ReplaceAll rules?
// We matched $n argument as -1 literal.
//
// This is not exhaustive as any $n that is less than 0 will work identically.
// So what we really want to do is to tell whether it's less than 0.
m.Match(`strings.Replace($s, $old, $replacement, $n)`).
Where(m["n"].Value.Int() < 0).
Suggest(`strings.ReplaceAll($s, $old, $replacement)`)
}
func badCond(m dsl.Matcher) {
// If we use Value.Int() on the right-hand-side, we can achieve even more
// and compare how constexpr values compare to each other.
m.Match(`$x < $a && $x > $b`).
Where(m["a"].Value.Int() <= m["b"].Value.Int()).
Report("the condition is always false because $a <= $b")
m.Match(`$x > $a && $x < $b`).
Where(m["a"].Value.Int() >= m["b"].Value.Int()).
Report("the condition is always false because $a >= $b")
}
package main
import "strings"
func main() {
var s, toReplace, replacement string
const negativeConst = -2
_ = strings.Replace(s, toReplace, replacement, 1) // Not matched
_ = strings.Replace(s, toReplace, replacement, -1)
_ = strings.Replace(s, toReplace, replacement, -10)
_ = strings.Replace(s, " ", "", 10-11) // Const-folded and matched
_ = strings.Replace(s, "/", `\`, negativeConst)
badCond(1, 2)
}
func badCond(x, y int) {
if x < -10 && x > 10 {
}
const ten = 10
if x > ten+1 && x < -10 {
}
// Don't know what value `y` have.
if x < y && x > 10 {
}
if x < -10 && y > 10 {
}
}
Notes:
Value.Int()
filter will fail and reject the match