New in Symplify 9: Documentation Generator for PHP CS Fixer, Code Sniffer, PHPStan and Rector Rules

Rector is providing rules, so is PHPStan and PHP CS Fixer, and Code Sniffer. If you use only 5-10 rules and want to share them with the world, you create a README and describe them.

In Rector, we now have over 640 rules, in Symplify 110 rules for PHPStan and 15 rules for PHP CS Fixer. How can we handle documentation for this amount of rules without going crazy?

This post is for rules-based package maintainers.

But the critical question is:

Status Quo: Manual Documentation

Today, we create documentation manually. Add a new rule, new option, update the name or describe an example. Here are 4 examples from such documentations:

There are roughly 1500-2000 rules in the whole rules-ecosystem and growing every day. We don't have time to read about each rule. Nor deduct from the text how it will confront our code.

How do we adapt? We scan. We go quickly through README and look for something we like. When we scan, we look for colors, bold, patterns or pictures.

Have a guess, what does this rule do?

You're right. It makes line-length fit x.

Easy for Maintainers and Sexy for Users?

The diff example above is beautiful, but it requires extra work with diff formatting, precise code indent, and don't even start about maintenance in case of change...

"Give me the tools to solve my problem, and I'll consider it.
Give me extra work, and I'll pass."

...but wait. There might be a way to less work.

In Rector, we have over 640 rules. That would be hell to maintain, so eventually, we came up with a documentation generator. One command line hit, and a whole file with examples, rule names is generated:

bin/rector generate-rule-docs

We already maintained Symplify\CodingStandard documentation with 40 rules manually. There was some itching on every new rule, but we always learned to ignore it. That was about to change.

During summer 2020 a new packaged started to grow - Symplify\PHPStanRules. Just during summer, 50 rules were added, now growing over 110. Constant reminders in pull-request "Could you add it to documentation?" were the last nail in the coffin.

We had to automate it.

Every Rule is the Documentation

The first step to automation is to merge rule documentation and rule into a single place. There is no markdown file, just a PHP code rule.

We got inspired in php-cs-fixer where RuleDefinition is part of every rule.

Add an DocumentedRuleInterface interface and implement getRuleDefinition():

namespace App\CodingStandard\Fixer;

use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\Contract\DocumentedRuleInterface;

final class RemoveCommentedCodeFixer implements DocumentedRuleInterface
    public function getRuleDefinition(): RuleDefinition
        return new RuleDefinition('Remove commented code', [
            new CodeSample(
// $one = 1;
// $two = 2;
// $three = 3;

That's it!

3 steps to Generated Documentation

The Symplify\RuleDocGenerator packages take care of full documentation. There is just one interface to implement for Rector, PHP CS Fixer, CodeSniffer, and PHPStan rules.

  1. Install Package
composer require symplify/rule-doc-generator
  1. Implement DocumentedRuleInterface interface

You can pick from more code sample classes:

For read-only rules, e.g. Sniff or PHPStan, the second argument of CodeSample is for correct code:

use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;

// ...
return new CodeSample('bad code', 'good code');
  1. Generate Documentation in CLI
vendor/bin/rule-doc-generator generate <directories-with-rules>

There is also implicit --output-file docs/ option.

vendor/bin/rule-doc-generator generate src/Rules

You've just created smart documentation with nice and clear design:

Tired of screenshots? See the Real Documentation on GitHub

See our 3 documentations re-generated everyday with GitHub Actions cron:

That's it!

Happy coding!

Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors. I'd really appreciate it!