PHPCSStandards / PHPCSUtils

A suite of utility functions for use with PHP_CodeSniffer
https://phpcsutils.com/
GNU Lesser General Public License v3.0
54 stars 7 forks source link

Feature suggestion: AbstractDocblockSniff #517

Open jrfnl opened 12 months ago

jrfnl commented 12 months ago

Repost from https://github.com/squizlabs/PHP_CodeSniffer/issues/2222:

Currently, the PEAR and the Squiz standard both contain a number of docblock related sniffs which are not configurable and are opinionated on what tags should be present in the various docblocks. Additionally, the various sniffs contain duplicate code.

External standards can, of course, create their own sniffs for these type of checks, however, that would involve yet more code duplication.

@gsherwood Would there be interest in an AbstractDocblockSniff ?

I imagine that sniff could roughly look like:

abstract class AbstractDocblockSniff implements Sniff
{
    /**
     * Format similar to the format used in the PEAR.Commenting.FileComment sniff.
     *
     * I.e.:
     * `tagname` => array(
     *     'tag_required'     => true/false,
     *     'allow_multiple'   => true/false,
     *     'content_required' => true/false,
     * )
     */
    public $tags = array();

    /**
     * Whether the tag order is important and should be checked.
     *
     * @var bool
     */
    public $checkTagOrder = false;

    abstract public function register();

    public function processToken()
    {
        $docblockOpener = $this->findTargetDocblock();
        if ($docblockOpener === false) {
            $this->MissingDocBlock();
            return;
        }

        $this->examineDocBlockFormat();
        $this->examineTags();
    }

    /**
     * Find the target docblock based on whatever token(s) was registered in the register() method.
     */
    abstract public function findTargetDocblock();

    public function missingDocBlock()
    {
        // Throw error for missing docblock.
    }

    public function examineDocblockFormat()
    {
        // Check for docblock vs comment format.
        // Superfluous empty comment lines etc.
    }

    public function examineTags()
    {
        // Check based on tag_required status
        // Check based on allow_multiple status
        // Check based on content_required status

        // Allow for additional tag specific checks in child sniffs.
        if (method_exists($this, 'examine'.$tagName)) {
            call_user_func(array($this, 'examine'.$tagName), $args);
        }

        // Maybe check tag order.
    }

    // Possibly some examineTagName() methods for common tags.
    // Those can, of course, be overloaded by child sniffs with either a completely different
    // check of with a call to the parent in combination with additional checks.

    // Can be used by child sniffs from the tag specific check methods.
    public function checkPunctuation( $string )
    {
        // Check for capital at start of phrase.
        // Check for valid end of sentence character.
    }
}

This would allow some simplification of the code used in the various current PHPCS sniffs dealing with docblocks and allow for far greater flexibility for external standards which want to check docblocks against their own rules for required/multiple etc.


My thinking about this has evolved a lot since I posted the above in 2018.

For now, this more intended as a reminder, not as an example of the intended implementation.