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:
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
.
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.
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(
<<<'CODE_SAMPLE'
// $one = 1;
// $two = 2;
// $three = 3;
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
CODE_SAMPLE
),
]);
}
}
That's it!
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.
composer require symplify/rule-doc-generator
DocumentedRuleInterface
interfaceYou can pick from more code sample classes:
CodeSample
ConfiguredCodeSample
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');
vendor/bin/rule-doc-generator generate <directories-with-rules>
There is also implicit --output-file docs/rules_overview.md
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-source packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!