Skip to content

Add license checker and fixer #293

Open
@jaapio

Description

@jaapio

Is your feature request related to a problem?

In many of my projects I require each file to have a file level license docblock. PHP_codeSniffer has 2 sniffs that are able to check the presence of a file level comment however it cannot strictly check the comment.

Describe the solution you'd like

As a bunch of code does say more than a thousand words:

<?php

declare(strict_types=1);

namespace CodingStandard\Sniffs\Commenting;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;

class LicenseDocBlockSniff implements Sniff
{
    const LICENSE = <<<LICENSE
This file is part of phpDocumentor.
 
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
 
@link https://phpdoc.org
LICENSE;

    public function register(): array
    {
        return [T_OPEN_TAG];
    }

    public function process(File $phpcsFile, $stackPtr): void
    {
        $tokens = $phpcsFile->getTokens();
        $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);

        // Allow declare() statements at the top of the file.
        if ($tokens[$commentStart]['code'] === T_DECLARE) {
            $semicolon    = $phpcsFile->findNext(T_SEMICOLON, ($commentStart + 1));
            $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), null, true);
        }

        if ($commentStart === false || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG) {
            $phpcsFile->addFixableError('License docblock is missing', $stackPtr, 'Missing');
            return;
        }

        $commentEnd = $tokens[$commentStart]['comment_closer'];
        $licenseContent = '';

        for ($i = $commentStart; $i <= $commentEnd; $i++) {
            if ($tokens[$i]['code'] === T_DOC_COMMENT_STAR || $tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG || $tokens[$i]['code'] === T_DOC_COMMENT_OPEN_TAG) {
                continue;
            }

            $licenseContent .= $tokens[$i]['content'];
        }

        $trimmedLicense = '';
        foreach (explode("\n", $licenseContent) as $line) {
            $trimmedLicense .= trim($line);
        }

        $expectedLicense = '';
        foreach (explode("\n", self::LICENSE) as $line) {
            $expectedLicense .= trim($line);
        }

        if ($trimmedLicense !== $expectedLicense) {
            $phpcsFile->addFixableError('License docblock is invalid', $stackPtr, 'Invalid');
            $this->fix($phpcsFile, $commentStart);
            return;
        }
    }
}

Additional context (optional)

  • I intend to create a pull request to implement this feature.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions