Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ruleguard: add support for local functions #298

Merged
merged 1 commit into from Nov 7, 2021
Merged

Conversation

quasilyte
Copy link
Owner

This feature is useful for rule filters readability improvements.

Instead of copying a complex Where() expression several times,
one can now use a local function literal to define that filter
operation and use it inside Where() expressions.

Here is an example:

func preferFprint(m dsl.Matcher) {
	isFmtPackage := func(v dsl.Var) bool {
		return v.Text == "fmt" && v.Object.Is(`PkgName`)
	}

	m.Match(`$w.Write([]byte($fmt.Sprint($*args)))`).
		Where(m["w"].Type.Implements("io.Writer") && isFmtPackage(m["fmt"])).
		Suggest("fmt.Fprint($w, $args)").
		Report(`fmt.Fprint($w, $args) should be preferred to the $$`)

	m.Match(`$w.Write([]byte($fmt.Sprintf($*args)))`).
		Where(m["w"].Type.Implements("io.Writer") && isFmtPackage(m["fmt"])).
		Suggest("fmt.Fprintf($w, $args)").
		Report(`fmt.Fprintf($w, $args) should be preferred to the $$`)

	// ...etc
}

Note that we used isFmtPackage in more than 1 rule.

Functions can accept almost arbitrary params, but there are some
restrictions on what kinds of arguments they can receive right now.

These arguments work:

  • Matcher var expressions like m["varname"]
  • Basic literals like "foo", 104, 5.2
  • Constants

@quasilyte quasilyte force-pushed the quasilyte/localfunc branch 6 times, most recently from 0eabce5 to e36eeaf Compare November 7, 2021 00:22
This feature is useful for rule filters readability improvements.

Instead of copying a complex `Where()` expression several times,
one can now use a local function literal to define that filter
operation and use it inside `Where()` expressions.

Here is an example:

```go
func preferFprint(m dsl.Matcher) {
	isFmtPackage := func(v dsl.Var) bool {
		return v.Text == "fmt" && v.Object.Is(`PkgName`)
	}

	m.Match(`$w.Write([]byte($fmt.Sprint($*args)))`).
		Where(m["w"].Type.Implements("io.Writer") && isFmtPackage(m["fmt"])).
		Suggest("fmt.Fprint($w, $args)").
		Report(`fmt.Fprint($w, $args) should be preferred to the $$`)

	m.Match(`$w.Write([]byte($fmt.Sprintf($*args)))`).
		Where(m["w"].Type.Implements("io.Writer") && isFmtPackage(m["fmt"])).
		Suggest("fmt.Fprintf($w, $args)").
		Report(`fmt.Fprintf($w, $args) should be preferred to the $$`)

	// ...etc
}
```

Note that we used `isFmtPackage` in more than 1 rule.

Functions can accept almost arbitrary params, but there are some
restrictions on what kinds of arguments they can receive right now.

These arguments work:

* Matcher var expressions like `m["varname"]`
* Basic literals like `"foo"`, `104`, `5.2`
* Constants
@quasilyte quasilyte merged commit 319908c into master Nov 7, 2021
@quasilyte quasilyte deleted the quasilyte/localfunc branch November 7, 2021 01:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant