From a7018b1da9d0736adc2598eab8623daedcf9a367 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Sun, 4 May 2025 16:58:25 +0100 Subject: [PATCH 01/12] Initial commit --- .../Sniffs/Commenting/FunctionCommentSniff.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php index 7bd1f178..c499dbde 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php @@ -78,6 +78,7 @@ public function process(File $phpcsFile, $stackPtr) $ignore = (Tokens::$methodPrefixes + Tokens::$phpcsCommentTokens); $ignore[T_WHITESPACE] = T_WHITESPACE; $functionCodeStart = $stackPtr; + $phpstanCommentLines = 0; for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { @@ -95,6 +96,15 @@ public function process(File $phpcsFile, $stackPtr) continue; } + // If there is a phpstan-ignore inline comment disregard it and continue searching backwards + // to find the function comment. + if ($tokens[$commentEnd]['code'] === T_COMMENT + && preg_match('/\@xphpstan-ignore/', $tokens[$commentEnd]['content']) + ) { + $phpstanCommentLines += 1; + continue; + } + break; } @@ -166,7 +176,7 @@ public function process(File $phpcsFile, $stackPtr) } }//end foreach - if ($tokens[$commentEnd]['line'] !== ($tokens[$functionCodeStart]['line'] - 1)) { + if ($tokens[$commentEnd]['line'] !== ($tokens[$functionCodeStart]['line'] - 1 - $phpstanCommentLines)) { $error = 'There must be no blank lines after the function comment'; $fix = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter'); if ($fix === true) { From 457f77340774279a601425d98f6f1488c4416490 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Sun, 4 May 2025 17:16:58 +0100 Subject: [PATCH 02/12] Fix 2 x phpcs --- .../Drupal/Sniffs/Commenting/FunctionCommentSniff.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php index c499dbde..22e99b5f 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php @@ -99,14 +99,14 @@ public function process(File $phpcsFile, $stackPtr) // If there is a phpstan-ignore inline comment disregard it and continue searching backwards // to find the function comment. if ($tokens[$commentEnd]['code'] === T_COMMENT - && preg_match('/\@xphpstan-ignore/', $tokens[$commentEnd]['content']) + && preg_match('/\@xphpstan-ignore/', $tokens[$commentEnd]['content']) === true ) { $phpstanCommentLines += 1; continue; } break; - } + }//end for // Constructor methods are exempt from requiring a docblock. // @see https://www.drupal.org/project/coder/issues/3400560. From 87d0940964a79d6954cdf29ba42df08b99e26271 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Sun, 4 May 2025 17:21:20 +0100 Subject: [PATCH 03/12] remove x --- coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php index 22e99b5f..c903a8f7 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php @@ -99,7 +99,7 @@ public function process(File $phpcsFile, $stackPtr) // If there is a phpstan-ignore inline comment disregard it and continue searching backwards // to find the function comment. if ($tokens[$commentEnd]['code'] === T_COMMENT - && preg_match('/\@xphpstan-ignore/', $tokens[$commentEnd]['content']) === true + && preg_match('/\@phpstan-ignore/', $tokens[$commentEnd]['content']) === true ) { $phpstanCommentLines += 1; continue; From 30eac2a4009421b5b20dfb8f285cb2e8a403e00f Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Sun, 4 May 2025 17:24:16 +0100 Subject: [PATCH 04/12] change true to 1 --- coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php index c903a8f7..a175aa9a 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php @@ -99,7 +99,7 @@ public function process(File $phpcsFile, $stackPtr) // If there is a phpstan-ignore inline comment disregard it and continue searching backwards // to find the function comment. if ($tokens[$commentEnd]['code'] === T_COMMENT - && preg_match('/\@phpstan-ignore/', $tokens[$commentEnd]['content']) === true + && preg_match('/\@phpstan-ignore/', $tokens[$commentEnd]['content']) === 1 ) { $phpstanCommentLines += 1; continue; From e912b6f183b3d74f96904c43ed3e090a83f133e0 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Mon, 5 May 2025 10:18:19 +0100 Subject: [PATCH 05/12] Simplify by using same tactic as phpcs comments --- .../Drupal/Sniffs/Commenting/FunctionCommentSniff.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php index a175aa9a..eaeb1ac5 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php @@ -78,7 +78,6 @@ public function process(File $phpcsFile, $stackPtr) $ignore = (Tokens::$methodPrefixes + Tokens::$phpcsCommentTokens); $ignore[T_WHITESPACE] = T_WHITESPACE; $functionCodeStart = $stackPtr; - $phpstanCommentLines = 0; for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { @@ -101,7 +100,7 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$commentEnd]['code'] === T_COMMENT && preg_match('/\@phpstan-ignore/', $tokens[$commentEnd]['content']) === 1 ) { - $phpstanCommentLines += 1; + $functionCodeStart = $commentEnd; continue; } @@ -176,7 +175,7 @@ public function process(File $phpcsFile, $stackPtr) } }//end foreach - if ($tokens[$commentEnd]['line'] !== ($tokens[$functionCodeStart]['line'] - 1 - $phpstanCommentLines)) { + if ($tokens[$commentEnd]['line'] !== ($tokens[$functionCodeStart]['line'] - 1)) { $error = 'There must be no blank lines after the function comment'; $fix = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter'); if ($fix === true) { From a150c02942a93fdf8b7bca652e63037d08bc1c5f Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Sun, 18 May 2025 16:59:16 +0100 Subject: [PATCH 06/12] Add first case to good.php --- tests/Drupal/good/good.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index 357ba614..99f897f3 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -1124,7 +1124,7 @@ public function test8() {} } -t('Some long mulit-line +t('Some long mulit-line text is weird, but allowed.'); // Anonymous functions should not throw indentation errors here. @@ -1986,3 +1986,19 @@ protected function getFallbackPluginId($plugin_id, array $configuration = []) { } } + +/** + * Test for @phpstan-ignore-next-line. + * + * Coder issue https://www.drupal.org/project/coder/issues/3516489 + */ +class TestPhpstanIgnore1 extends BaseMySqlSchema { + + /** + * This is the function docblock comment. + */ + // @phpstan-ignore-next-line missingType.return + public function addField($table, $field, $spec, $keys_new = []) { + } + +} From c445c99116e43413b87a7d361cb1d5b33565e3f5 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Sun, 18 May 2025 22:11:16 +0100 Subject: [PATCH 07/12] add tokenIsPhpstanComment() function --- .../Sniffs/Commenting/FunctionCommentSniff.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php index eaeb1ac5..27117a7a 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php @@ -97,9 +97,7 @@ public function process(File $phpcsFile, $stackPtr) // If there is a phpstan-ignore inline comment disregard it and continue searching backwards // to find the function comment. - if ($tokens[$commentEnd]['code'] === T_COMMENT - && preg_match('/\@phpstan-ignore/', $tokens[$commentEnd]['content']) === 1 - ) { + if ($this->tokenIsPhpstanComment($tokens[$commentEnd]) === true) { $functionCodeStart = $commentEnd; continue; } @@ -191,6 +189,20 @@ public function process(File $phpcsFile, $stackPtr) }//end process() + /** + * Determine if a token is a '@phpstan-' control comment. + * + * @param array $token The token to be checked. + * + * @return bool True if the token contains a @phpstan comment. + */ + public static function tokenIsPhpstanComment($token) + { + return ($token['code'] === T_COMMENT && strpos($token['content'], ' @phpstan-') !== false); + + }//end tokenIsPhpstanComment() + + /** * Process the return comment of this function comment. * From 23d37a55500b2222f1efb3f870f6c8158df6aa76 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Mon, 19 May 2025 09:20:36 +0100 Subject: [PATCH 08/12] Simplify the example in good.php --- tests/Drupal/good/good.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index 33580541..8e2c4003 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -2009,13 +2009,6 @@ public function &get($instance_id) { * * Coder issue https://www.drupal.org/project/coder/issues/3516489 */ -class TestPhpstanIgnore1 extends BaseMySqlSchema { - - /** - * This is the function docblock comment. - */ - // @phpstan-ignore-next-line missingType.return - public function addField($table, $field, $spec, $keys_new = []) { - } - +// @phpstan-ignore-next-line missingType.return +public function ignore_phpstan_comment() { } From 53963f63c77fb1d968a4532263f5c3d6c41a4996 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Mon, 19 May 2025 09:38:34 +0100 Subject: [PATCH 09/12] Add array value type to fix phpstan --- coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php index 27117a7a..95f43253 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/FunctionCommentSniff.php @@ -192,7 +192,7 @@ public function process(File $phpcsFile, $stackPtr) /** * Determine if a token is a '@phpstan-' control comment. * - * @param array $token The token to be checked. + * @param array $token The token to be checked. * * @return bool True if the token contains a @phpstan comment. */ From 8e93fa1dc61f604a63bcde1a5474979a06a6d613 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Thu, 22 May 2025 16:03:54 +0100 Subject: [PATCH 10/12] revert unintended trailing-blank change --- tests/Drupal/good/good.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index 8e2c4003..cd61b6e0 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -1124,7 +1124,7 @@ public function test8() {} } -t('Some long mulit-line +t('Some long mulit-line text is weird, but allowed.'); // Anonymous functions should not throw indentation errors here. From b752a4be05bf603d675c06f77d01664c78815dba Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Fri, 23 May 2025 13:59:23 +0100 Subject: [PATCH 11/12] Add two more test cases --- tests/Drupal/good/good.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index cd61b6e0..17a39e1f 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -2012,3 +2012,19 @@ public function &get($instance_id) { // @phpstan-ignore-next-line missingType.return public function ignore_phpstan_comment() { } + +/** + * Test for @phpstan-ignore with attribute before. + */ +#[ExampleAttribute('foo', 'bar')] +// @phpstan-ignore-next-line missingType.return +public function ignore_phpstan_comment_with_attribute_before() { +} + +/** + * Test for @phpstan-ignore with attribute after. + */ +// @phpstan-ignore-next-line missingType.return +#[ExampleAttribute('foo', 'bar')] +public function ignore_phpstan_comment_with_attribute_after() { +} From 34981a1c3a2c17dbdedd7c3bb813e6688d7ac748 Mon Sep 17 00:00:00 2001 From: Jonathan Smith Date: Fri, 23 May 2025 14:11:09 +0100 Subject: [PATCH 12/12] Remove 3rd test example --- tests/Drupal/good/good.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index 17a39e1f..c72c5685 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -2020,11 +2020,3 @@ public function ignore_phpstan_comment() { // @phpstan-ignore-next-line missingType.return public function ignore_phpstan_comment_with_attribute_before() { } - -/** - * Test for @phpstan-ignore with attribute after. - */ -// @phpstan-ignore-next-line missingType.return -#[ExampleAttribute('foo', 'bar')] -public function ignore_phpstan_comment_with_attribute_after() { -}