Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
AnnotationFormatValidator.php
Go to the documentation of this file.
1 <?php
6 declare(strict_types=1);
8 
9 use PHP_CodeSniffer\Files\File;
10 
15 {
24  private function getShortDescriptionEndPosition(File $phpcsFile, int $shortPtr, $commentEndPtr) : int
25  {
26  $tokens = $phpcsFile->getTokens();
27  $shortPtrEnd = $shortPtr;
28  for ($i = ($shortPtr + 1); $i < $commentEndPtr; $i++) {
29  if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
30  if ($tokens[$i]['line'] === $tokens[$shortPtrEnd]['line'] + 1) {
31  $shortPtrEnd = $i;
32  } else {
33  break;
34  }
35  }
36  }
37  return $shortPtrEnd;
38  }
39 
47  private function validateMultiLinesInShortDescription(
48  File $phpcsFile,
49  int $shortPtr,
50  int $commentEndPtr
51  ) : void {
52  $tokens = $phpcsFile->getTokens();
53  $shortPtrEnd = $this->getShortDescriptionEndPosition(
54  $phpcsFile,
55  (int) $shortPtr,
56  $commentEndPtr
57  );
58  $shortPtrEndContent = $tokens[$shortPtrEnd]['content'];
59  if (preg_match('/^[a-z]/', $shortPtrEndContent)
60  && $shortPtrEnd != $shortPtr
61  && !preg_match('/\bSee\b/', $shortPtrEndContent)
62  && $tokens[$shortPtr]['line']+1 === $tokens[$shortPtrEnd]['line']
63  && $tokens[$shortPtrEnd]['code'] !== T_DOC_COMMENT_TAG
64  ) {
65  $error = 'Short description should not be in multi lines';
66  $phpcsFile->addFixableError($error, $shortPtrEnd+1, 'MethodAnnotation');
67  }
68  }
69 
78  private function validateSpacingBetweenShortAndLongDescriptions(
79  File $phpcsFile,
80  int $shortPtr,
81  int $commentEndPtr,
82  array $emptyTypeTokens
83  ) : void {
84  $tokens = $phpcsFile->getTokens();
85  $shortPtrEnd = $this->getShortDescriptionEndPosition(
86  $phpcsFile,
87  (int) $shortPtr,
88  $commentEndPtr
89  );
90  $shortPtrEndContent = $tokens[$shortPtrEnd]['content'];
91  if (preg_match('/^[A-Z]/', $shortPtrEndContent)
92  && !preg_match('/\bSee\b/', $shortPtrEndContent)
93  && $tokens[$shortPtr]['line']+1 === $tokens[$shortPtrEnd]['line']
94  && $tokens[$shortPtrEnd]['code'] !== T_DOC_COMMENT_TAG
95  ) {
96  $error = 'There must be exactly one blank line between lines';
97  $phpcsFile->addFixableError($error, $shortPtrEnd + 1, 'MethodAnnotation');
98  }
99  if ($shortPtrEnd != $shortPtr) {
100  $this->validateLongDescriptionFormat($phpcsFile, $shortPtrEnd, $commentEndPtr, $emptyTypeTokens);
101  } else {
102  $this->validateLongDescriptionFormat($phpcsFile, $shortPtr, $commentEndPtr, $emptyTypeTokens);
103  }
104  }
105 
115  private function validateShortDescriptionFormat(
116  File $phpcsFile,
117  int $shortPtr,
118  int $stackPtr,
119  int $commentEndPtr,
120  array $emptyTypeTokens
121  ) : void {
122  $tokens = $phpcsFile->getTokens();
123  if ($tokens[$shortPtr]['line'] !== $tokens[$stackPtr]['line'] + 1) {
124  $error = 'No blank lines are allowed before short description';
125  $phpcsFile->addFixableError($error, $shortPtr, 'MethodAnnotation');
126  }
127  if (strtolower($tokens[$shortPtr]['content']) === '{@inheritdoc}') {
128  $error = 'If the @inheritdoc not inline it shouldn’t have braces';
129  $phpcsFile->addFixableError($error, $shortPtr, 'MethodAnnotation');
130  }
131  $shortPtrContent = $tokens[$shortPtr]['content'];
132  if (preg_match('/^\p{Ll}/u', $shortPtrContent) === 1) {
133  $error = 'Short description must start with a capital letter';
134  $phpcsFile->addFixableError($error, $shortPtr, 'MethodAnnotation');
135  }
136  $this->validateNoExtraNewLineBeforeShortDescription(
137  $phpcsFile,
138  $stackPtr,
139  $commentEndPtr,
140  $emptyTypeTokens
141  );
142  $this->validateSpacingBetweenShortAndLongDescriptions(
143  $phpcsFile,
144  $shortPtr,
145  $commentEndPtr,
146  $emptyTypeTokens
147  );
148  $this->validateMultiLinesInShortDescription(
149  $phpcsFile,
150  $shortPtr,
151  $commentEndPtr
152  );
153  }
154 
163  private function validateLongDescriptionFormat(
164  File $phpcsFile,
165  int $shortPtrEnd,
166  int $commentEndPtr,
167  array $emptyTypeTokens
168  ) : void {
169  $tokens = $phpcsFile->getTokens();
170  $longPtr = $phpcsFile->findNext($emptyTypeTokens, $shortPtrEnd + 1, $commentEndPtr - 1, true);
171  if (strtolower($tokens[$longPtr]['content']) === '{@inheritdoc}') {
172  $error = '{@inheritdoc} imports only short description, annotation must have long description';
173  $phpcsFile->addFixableError($error, $longPtr, 'MethodAnnotation');
174  }
175  if ($longPtr !== false && $tokens[$longPtr]['code'] === T_DOC_COMMENT_STRING) {
176  if ($tokens[$longPtr]['line'] !== $tokens[$shortPtrEnd]['line'] + 2) {
177  $error = 'There must be exactly one blank line between descriptions';
178  $phpcsFile->addFixableError($error, $longPtr, 'MethodAnnotation');
179  }
180  if (preg_match('/^\p{Ll}/u', $tokens[$longPtr]['content']) === 1) {
181  $error = 'Long description must start with a capital letter';
182  $phpcsFile->addFixableError($error, $longPtr, 'MethodAnnotation');
183  }
184  }
185  }
186 
194  public function validateTagsSpacingFormat(File $phpcsFile, int $commentStartPtr, array $emptyTypeTokens) : void
195  {
196  $tokens = $phpcsFile->getTokens();
197  if (isset($tokens[$commentStartPtr]['comment_tags'][0])) {
198  $firstTagPtr = $tokens[$commentStartPtr]['comment_tags'][0];
199  $commentTagPtrContent = $tokens[$firstTagPtr]['content'];
200  $prevPtr = $phpcsFile->findPrevious($emptyTypeTokens, $firstTagPtr - 1, $commentStartPtr, true);
201  if ($tokens[$firstTagPtr]['line'] !== $tokens[$prevPtr]['line'] + 2
202  && strtolower($commentTagPtrContent) !== '@inheritdoc'
203  ) {
204  $error = 'There must be exactly one blank line before tags';
205  $phpcsFile->addFixableError($error, $firstTagPtr, 'MethodAnnotation');
206  }
207  }
208  }
209 
216  public function validateTagGroupingFormat(File $phpcsFile, int $commentStartPtr) : void
217  {
218  $tokens = $phpcsFile->getTokens();
219  $tagGroups = [];
220  $groupId = 0;
221  $paramGroupId = null;
222  foreach ($tokens[$commentStartPtr]['comment_tags'] as $position => $tag) {
223  if ($position > 0) {
224  $prevPtr = $phpcsFile->findPrevious(
225  T_DOC_COMMENT_STRING,
226  $tag - 1,
227  $tokens[$commentStartPtr]['comment_tags'][$position - 1]
228  );
229  if ($prevPtr === false) {
230  $prevPtr = $tokens[$commentStartPtr]['comment_tags'][$position - 1];
231  }
232 
233  if ($tokens[$prevPtr]['line'] !== $tokens[$tag]['line'] - 1) {
234  $groupId++;
235  }
236  }
237 
238  if (strtolower($tokens[$tag]['content']) === '@param') {
239  if ($paramGroupId !== null
240  && $paramGroupId !== $groupId) {
241  $error = 'Parameter tags must be grouped together';
242  $phpcsFile->addFixableError($error, $tag, 'MethodAnnotation');
243  }
244  if ($paramGroupId === null) {
245  $paramGroupId = $groupId;
246  }
247  }
248  $tagGroups[$groupId][] = $tag;
249  }
250  }
251 
260  private function validateNoExtraNewLineBeforeShortDescription(
261  File $phpcsFile,
262  int $commentStartPtr,
263  int $commentEndPtr,
264  array $emptyTypeTokens
265  ) : void {
266  $tokens = $phpcsFile->getTokens();
267  $prevPtr = $phpcsFile->findPrevious($emptyTypeTokens, $commentEndPtr - 1, $commentStartPtr, true);
268  if ($tokens[$prevPtr]['line'] < ($tokens[$commentEndPtr]['line'] - 1)) {
269  $error = 'Additional blank lines found at end of the annotation block';
270  $phpcsFile->addFixableError($error, $commentEndPtr, 'MethodAnnotation');
271  }
272  }
273 
284  File $phpcsFile,
285  int $commentStartPtr,
286  int $shortPtr,
287  int $commentEndPtr,
288  array $emptyTypeTokens
289  ) : void {
290  $tokens = $phpcsFile->getTokens();
291  if (isset($tokens[$commentStartPtr]['comment_tags'][0])
292  ) {
293  $commentTagPtr = $tokens[$commentStartPtr]['comment_tags'][0];
294  $commentTagPtrContent = $tokens[$commentTagPtr]['content'];
295  if ($tokens[$shortPtr]['code'] !== T_DOC_COMMENT_STRING
296  && strtolower($commentTagPtrContent) !== '@inheritdoc'
297  ) {
298  $error = 'Missing short description';
299  $phpcsFile->addFixableError($error, $commentStartPtr, 'MethodAnnotation');
300  } else {
301  $this->validateShortDescriptionFormat(
302  $phpcsFile,
303  (int) $shortPtr,
304  $commentStartPtr,
305  $commentEndPtr,
306  $emptyTypeTokens
307  );
308  }
309  } else {
310  $this->validateShortDescriptionFormat(
311  $phpcsFile,
312  (int) $shortPtr,
313  $commentStartPtr,
314  $commentEndPtr,
315  $emptyTypeTokens
316  );
317  }
318  }
319 }
validateTagsSpacingFormat(File $phpcsFile, int $commentStartPtr, array $emptyTypeTokens)
validateTagGroupingFormat(File $phpcsFile, int $commentStartPtr)
validateDescriptionFormatStructure(File $phpcsFile, int $commentStartPtr, int $shortPtr, int $commentEndPtr, array $emptyTypeTokens)
$i
Definition: gallery.phtml:31
$tokens
Definition: cards_list.phtml:9