Create linter rules with go-ruleguard
Linters, the tools that help me write better source code. The first Linter was developed in 1978, as a means to analyse source code. Since then, Linters have evolved to perform tasks beyond its original specification. Nowadays, Linters can “perform Static Analysis, enforce configuration flags, check for compliance with a given style-guide or security rule, and a lot more.” Go’s standard library ships with command
gofmt performs static analysis on specified source code. The command can also rewrite source code to improve formatting.
gofmt is a Go Linter. The OSS community offers its set of Go Linters as well. One of my favorite OSS projects is
go-ruleguard . I find it useful because the rules are defined dynamically, with Go code.
go-ruleguard has a custom command to perform source code analysis. To run the command, you will need to specify the go source with the rules, and the files to analyse. If used correctly,
go-ruleguardis a powerful tool to master.
Writing a linter rule
The first rule I wrote detects if strings are being appended together with the
+ operator. Joining strings this way is not efficient on a large scale, hence my motivation for writing this. I began by writing source code that would break the rule on purpose. Here is the content of file
Next, I’ll create a file named
rules.go , it’ll house my Linter rules :
This is the interesting part, the powerful syntax available in
go-ruleguard . The analysis operates in a similar manner compared to tests. You, the developer, would define a function that is invoked by a command. In this case, the command is
ruleguard . The rule above looks for patterns similar to
$x + $v and
$x += $v .
$v represent possible string typed variables or literals. They also become variables, accessible to chained methods. I’ve added a clause within method
Where to make sure the linter doesn’t confuse number addition with string concat. This is done by checking if variable x is of type string. Lastly, I’ll chain method
Report to write the error out to the console. This is my console output after running the linter defined above :
It is as simple as that. I wanted my next use to wow people. I wrote a linter to detect infinite recursion.
Writing a complex rule
I wrote a rule to detect infinite recursion. It is a rule you would refer to as a “toy.” In the sense that it is using a weak pattern to find matches. The rule searches for a function that invokes itself, the function won’t be flagged if it has conditional return statements. Here is how
main.go would look like :
The second function,
infWorkBad will violate the rule, as it has no conditional return statements. I defined the rule to detect recursion with the following code :
With this example, we are using a combination of regexp and pattern matching. I devised a clever idea to check if a function invoking itself. I assigned the function name to variable
$name , and look for a similar text value next to a pair parentheses. Variable body is prefixed by an asterisk, denoting a wildcard pattern. This will get all the text between the first curly brace and the function invocation. A regexp search is performed on variable body. The search happens on invocation of chained method
Where . The search checks if keyword return is present within an if statement. If not, the function will break the rule. The following output will be generated when I perform the analysis :
As expected, infWorkBad will run until the end of time.
go-ruleguard is a great source code analysis tool. The ability to define Linter rules with Go code is unprecedented. As shown with the examples above, it accommodates to the “out-of-the-box” thinker. The documentation is great, with code samples showing its use cases. As a newbie to
go-ruleguard , this is my initial understanding of the library. So forgive me if my post missed an important concept. For my next post on the topic, I’ll write about complex use cases. For people developing frameworks,
go-ruleguard is an ideal tool to help developers implement your framework correctly.
Do you have a cool Go OSS library? Comment it below and I’ll write about it.
What is a linter and why your team should use it? - SourceLevel
More and more teams have adopted linters and other static tools in their development process. Some integrated them in…
GitHub - quasilyte/go-ruleguard: Define and run pattern-based custom linting rules.
analysis-based Go linter that runs dynamically loaded rules. You write the rules, ruleguard checks whether they are…