Skip to content

Commit

Permalink
Merge pull request #129 from andrewnicols/constantsDocumentedCheck
Browse files Browse the repository at this point in the history
Add sniff to detect missing docs for constants
  • Loading branch information
stronk7 authored Mar 25, 2024
2 parents e514246 + fbe6264 commit 5af7ee0
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 1 deletion.
64 changes: 63 additions & 1 deletion moodle/Sniffs/Commenting/MissingDocblockSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
use PHPCSUtils\Tokens\Collections;
use PHPCSUtils\Utils\ObjectDeclarations;

/**
Expand Down Expand Up @@ -59,6 +60,7 @@ public function register() {
public function process(File $phpcsFile, $stackPtr) {
$this->processScopes($phpcsFile, $stackPtr);
$this->processFunctions($phpcsFile, $stackPtr);
$this->processConstants($phpcsFile, $stackPtr);
}

protected function processScopes(File $phpcsFile, int $stackPtr): void {
Expand Down Expand Up @@ -147,7 +149,11 @@ protected function processFunctions(File $phpcsFile, int $stackPtr): void {
if (count($token['conditions']) > 0) {
// This method has conditions (a Class, Interface, Trait, etc.).
// Check if that container extends or implements anything.
foreach (array_keys($token['conditions']) as $condition) {
foreach ($token['conditions'] as $condition => $conditionCode) {
if ($conditionCode === T_USE) {
// Skip any method inside a USE.
continue 2;
}
if (!array_key_exists($condition, $knownClasses)) {
$extendsOrImplements = $extendsOrImplements || ObjectDeclarations::findExtendedClassName(
$phpcsFile,
Expand Down Expand Up @@ -196,4 +202,60 @@ protected function processFunctions(File $phpcsFile, int $stackPtr): void {
}
}
}

/**
* Process constants.
*
* @param File $phpcsFile The file being scanned.
* @param int $stackPtr The position in the stack.
*/
protected function processConstants(File $phpcsFile, int $stackPtr): void {
$tokens = $phpcsFile->getTokens();

$typePtr = $stackPtr + 1;
while ($typePtr = $phpcsFile->findNext(T_CONST, $typePtr + 1)) {
$token = $tokens[$typePtr];
$containerName = null;

if (count($token['conditions']) > 0) {
foreach ($token['conditions'] as $conditionPtr => $conditionCode) {
// Skip any constant inside a USE.
if ($conditionCode === T_USE) {
continue 2;
}
if (in_array($conditionCode, Collections::closedScopes())) {
$containerName = TokenUtil::getObjectName($phpcsFile, $conditionPtr);
}
}
}

if (Docblocks::getDocBlock($phpcsFile, $typePtr)) {
// This is documented.
continue;
}

// Get the constant name
// We have to find the equals and step back from there.
// PHP 8.3 introduces the concept of typed constants but both the type and name are presented as T_STRING
$equalPtr = $phpcsFile->findNext(T_EQUAL, $typePtr + 1);
$namePtr = $phpcsFile->findPrevious(T_STRING, $equalPtr - 1, $typePtr);
$objectName = $tokens[$namePtr]['content'];

if ($containerName) {
$phpcsFile->addError(
'Missing docblock for constant %s::%s',
$typePtr,
'Missing',
[$containerName, $objectName]
);
} else {
$phpcsFile->addError(
'Missing docblock for constant %s',
$typePtr,
'Missing',
[$objectName]
);
}
}
}
}
21 changes: 21 additions & 0 deletions moodle/Tests/Sniffs/Commenting/MissingDocblockSniffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ public static function docblockCorrectnessProvider(): array {
'errors' => [],
'warnings' => [],
],
'Constants' => [
'fixture' => 'imported_constants',
'fixtureFilename' => null,
'errors' => [
16 => 'Missing docblock for constant UNDOCUMENTED_CONST',
32 => 'Missing docblock for constant example_class::UNDOCUMENTED_CONST',
],
'warnings' => [],
],
'Testcase' => [
'fixture' => 'testcase_class',
'fixtureFilename' => '/lib/tests/example_test.php',
Expand Down Expand Up @@ -182,6 +191,18 @@ public static function docblockCorrectnessProvider(): array {
];
}

if (version_compare(PHP_VERSION, '8.3.0') >= 0) {
$cases['Typed constants'] = [
'fixture' => 'typed_constants',
'fixtureFilename' => null,
'errors' => [
16 => 'Missing docblock for constant UNDOCUMENTED_CONST',
32 => 'Missing docblock for constant example_class::UNDOCUMENTED_CONST',
],
'warnings' => [],
];
}

return $cases;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace MoodleHQ\MoodleCS\moodle\Tests\Sniffs\PHPUnit;

use these\dont\actually\need\to\point\to\anything;
use function ns\fun_1;
use function ns\fun_2 as alias;
use const ns\CONST_1;
use const ns\CONST_2 as ALIAS;

use {
function ns\fun_3,
const ns\const_3
};

const UNDOCUMENTED_CONST = 1;

/** @var bool A documented bool */
const DOCUMENTED_BOOL = true;

/**
* Another documented constant which does things.
*
* @var int
*/
const DOCUMENTED_INT = 1;

/**
* Example class.
*/
class example_class {
const UNDOCUMENTED_CONST = 1;

/** @var bool A documented bool */
const DOCUMENTED_BOOL = true;

/**
* Another documented constant which does things.
*
* @var int
*/
const DOCUMENTED_INT = 1;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace MoodleHQ\MoodleCS\moodle\Tests\Sniffs\PHPUnit;

use these\dont\actually\need\to\point\to\anything;
use function ns\fun_1;
use function ns\fun_2 as alias;
use const ns\CONST_1;
use const ns\CONST_2 as ALIAS;

use {
function ns\fun_3,
const ns\const_3
};

const UNDOCUMENTED_CONST = 1;

/** @var bool A documented bool */
const DOCUMENTED_BOOL = true;

/**
* Another documented constant which does things.
*
* @var int
*/
const DOCUMENTED_INT = 1;

/**
* Example class.
*/
class example_class {
const int UNDOCUMENTED_CONST = 1;

/** @var bool A documented bool */
const bool DOCUMENTED_BOOL = true;

/**
* Another documented constant which does things.
*
* @var int
*/
const int DOCUMENTED_INT = 1;

}

0 comments on commit 5af7ee0

Please sign in to comment.