|
6 | 6 | */
|
7 | 7 | namespace Magento2\Sniffs\Commenting;
|
8 | 8 |
|
| 9 | +use PHP_CodeSniffer\Files\File; |
| 10 | + |
9 | 11 | /**
|
10 | 12 | * Helper class for common DocBlock validations
|
11 | 13 | */
|
12 | 14 | class PHPDocFormattingValidator
|
13 | 15 | {
|
| 16 | + /** |
| 17 | + * Finds matching PHPDoc for current pointer |
| 18 | + * |
| 19 | + * @param int $startPtr |
| 20 | + * @param File $phpcsFile |
| 21 | + * @return int |
| 22 | + */ |
| 23 | + public function findPHPDoc($startPtr, $phpcsFile) |
| 24 | + { |
| 25 | + $tokens = $phpcsFile->getTokens(); |
| 26 | + |
| 27 | + $commentStartPtr = $phpcsFile->findPrevious( |
| 28 | + [ |
| 29 | + T_WHITESPACE, |
| 30 | + T_DOC_COMMENT_STAR, |
| 31 | + T_DOC_COMMENT_WHITESPACE, |
| 32 | + T_DOC_COMMENT_TAG, |
| 33 | + T_DOC_COMMENT_STRING, |
| 34 | + T_DOC_COMMENT_CLOSE_TAG |
| 35 | + ], |
| 36 | + $startPtr - 1, |
| 37 | + null, |
| 38 | + true, |
| 39 | + null, |
| 40 | + true |
| 41 | + ); |
| 42 | + |
| 43 | + if ($tokens[$commentStartPtr]['code'] !== T_DOC_COMMENT_OPEN_TAG) { |
| 44 | + return -1; |
| 45 | + } |
| 46 | + |
| 47 | + return $commentStartPtr; |
| 48 | + } |
| 49 | + |
14 | 50 | /**
|
15 | 51 | * Determines if the comment identified by $commentStartPtr provides additional meaning to origin at $namePtr
|
16 | 52 | *
|
@@ -81,44 +117,49 @@ public function providesMeaning($namePtr, $commentStartPtr, $tokens)
|
81 | 117 | */
|
82 | 118 | public function hasDeprecatedWellFormatted($commentStartPtr, $tokens)
|
83 | 119 | {
|
84 |
| - $commentCloserPtr = $tokens[$commentStartPtr]['comment_closer']; |
| 120 | + $deprecatedPtr = $this->getTagPosition('@deprecated', $commentStartPtr, $tokens); |
| 121 | + if ($deprecatedPtr === -1) { |
| 122 | + return true; |
| 123 | + } |
| 124 | + |
| 125 | + if ($tokens[$deprecatedPtr + 2]['code'] !== T_DOC_COMMENT_STRING) { |
| 126 | + return false; |
| 127 | + } |
85 | 128 |
|
86 |
| - $hasDeprecated = false; |
87 |
| - $hasSee = false; |
| 129 | + $seePtr = $this->getTagPosition('@see', $commentStartPtr, $tokens); |
| 130 | + if ($seePtr === -1) { |
| 131 | + return true; |
| 132 | + } |
| 133 | + if ($tokens[$seePtr + 2]['code'] !== T_DOC_COMMENT_STRING) { |
| 134 | + return false; |
| 135 | + } |
| 136 | + |
| 137 | + return true; |
| 138 | + } |
| 139 | + |
| 140 | + /** |
| 141 | + * Searches for tag within comment |
| 142 | + * |
| 143 | + * @param string $tag |
| 144 | + * @param int $commentStartPtr |
| 145 | + * @param array $tokens |
| 146 | + * @return int |
| 147 | + */ |
| 148 | + private function getTagPosition($tag, $commentStartPtr, $tokens) |
| 149 | + { |
| 150 | + $commentCloserPtr = $tokens[$commentStartPtr]['comment_closer']; |
88 | 151 |
|
89 | 152 | for ($i = $commentStartPtr; $i <= $commentCloserPtr; $i++) {
|
90 | 153 | $token = $tokens[$i];
|
91 | 154 |
|
92 | 155 | // Not interesting
|
93 |
| - if ($token['code'] !== T_DOC_COMMENT_TAG) { |
| 156 | + if ($token['code'] !== T_DOC_COMMENT_TAG || $token['content'] !== $tag) { |
94 | 157 | continue;
|
95 | 158 | }
|
96 | 159 |
|
97 |
| - $tag = $token['content']; |
98 |
| - |
99 |
| - // Not an interesting tag |
100 |
| - if ($tag !== '@deprecated' && $tag !== '@see') { |
101 |
| - continue; |
102 |
| - } |
103 |
| - |
104 |
| - if ($tag === '@deprecated') { |
105 |
| - $hasDeprecated = true; |
106 |
| - } |
107 |
| - |
108 |
| - if ($tag === '@see') { |
109 |
| - $hasSee = true; |
110 |
| - } |
111 |
| - |
112 |
| - // Tag not followed by description |
113 |
| - if ($tokens[$i + 2]['code'] !== T_DOC_COMMENT_STRING) { |
114 |
| - return false; |
115 |
| - } |
| 160 | + return $i; |
116 | 161 | }
|
117 | 162 |
|
118 |
| - if ($hasDeprecated === true && $hasSee !== true) { |
119 |
| - return false; |
120 |
| - } |
121 |
| - |
122 |
| - return true; |
| 163 | + return -1; |
123 | 164 | }
|
124 | 165 | }
|
0 commit comments