1 | <?php |
||
22 | abstract class AbstractDocSniff extends AbstractSniff |
||
23 | { |
||
24 | use DocPosProviderTrait; |
||
25 | |||
26 | /** |
||
27 | * Every doc comment block SHOULD start ucfirst. |
||
28 | */ |
||
29 | public const CODE_DOC_COMMENT_UC_FIRST = 'DocCommentUcFirst'; |
||
30 | |||
31 | /** |
||
32 | * Every doc comment block (the summary or a long description paragrah) SHOULD finish with double newline. |
||
33 | */ |
||
34 | public const CODE_NO_LINE_AFTER_DOC_COMMENT = 'NoLineAfterDocComment'; |
||
35 | |||
36 | /** |
||
37 | * There SHOULD be a summary. |
||
38 | */ |
||
39 | public const CODE_NO_SUMMARY = 'NoSummary'; |
||
40 | |||
41 | /** |
||
42 | * The summary SHOULD be in one line. |
||
43 | */ |
||
44 | public const CODE_SUMMARY_TOO_LONG = 'SummaryTooLong'; |
||
45 | |||
46 | /** |
||
47 | * Message that the doc comments does not start with an capital letter. |
||
48 | */ |
||
49 | private const MESSAGE_DOC_COMMENT_UC_FIRST = 'The first letter of the summary/long-description is not uppercase.'; |
||
50 | |||
51 | /** |
||
52 | * Message that there is no line after the doc comment. |
||
53 | */ |
||
54 | private const MESSAGE_NO_LINE_AFTER_DOC_COMMENT = 'There is no empty line after the summary/long-description.'; |
||
55 | |||
56 | /** |
||
57 | * Message that there is no summary in doc comment. |
||
58 | */ |
||
59 | private const MESSAGE_NO_SUMMARY = 'There must be a summary in the doc comment.'; |
||
60 | |||
61 | /** |
||
62 | * The error message if the summary is too long. |
||
63 | */ |
||
64 | private const MESSAGE_SUMMARY_TOO_LONG = 'The summary should fit in one line. If you want more, use the long desc.'; |
||
65 | |||
66 | /** |
||
67 | * The cached position of the summary. |
||
68 | * |
||
69 | * @var int|bool |
||
70 | */ |
||
71 | private $summaryPosition = false; |
||
72 | |||
73 | /** |
||
74 | * Returns true if there is a doc block. |
||
75 | * |
||
76 | * @return bool |
||
77 | */ |
||
78 | protected function areRequirementsMet(): bool |
||
84 | |||
85 | /** |
||
86 | * Fixes the first letter of the doc comment, which must be uppercase. |
||
87 | * |
||
88 | * @param int $position |
||
89 | * @param array $token |
||
90 | * |
||
91 | * @return void |
||
92 | */ |
||
93 | private function fixDocCommentUcFirst(int $position, array $token): void |
||
99 | |||
100 | /** |
||
101 | * Fixes no line after doc comment. |
||
102 | * |
||
103 | * @param int $position |
||
104 | * @param array $token |
||
105 | * |
||
106 | * @return void |
||
107 | */ |
||
108 | private function fixNoLineAfterDocComment(int $position, array $token): void |
||
119 | |||
120 | /** |
||
121 | * Returns the position of the summary or null. |
||
122 | * |
||
123 | * @return int|null |
||
124 | */ |
||
125 | private function getSummaryPosition(): ?int |
||
133 | |||
134 | /** |
||
135 | * Returns true if the next line of the comment is empty. |
||
136 | * |
||
137 | * @param int $startPosition The position where to start the search. |
||
138 | * |
||
139 | * @return bool |
||
140 | */ |
||
141 | private function isNextLineEmpty(int $startPosition): bool |
||
152 | |||
153 | /** |
||
154 | * Returns true if the prev line of the comment is empty. |
||
155 | * |
||
156 | * @param int $startPosition The position where to start the search. |
||
157 | * |
||
158 | * @return bool |
||
159 | */ |
||
160 | private function isPrevLineEmpty(int $startPosition): bool |
||
171 | |||
172 | /** |
||
173 | * Is the given token a simple comment node? |
||
174 | * |
||
175 | * @param array $possCommentToken |
||
176 | * |
||
177 | * @return bool |
||
178 | */ |
||
179 | private function isSimpleText(array $possCommentToken): bool |
||
183 | |||
184 | /** |
||
185 | * Returns the position of the next whitespace or star of the comment for checking the line after that. |
||
186 | * |
||
187 | * @param int $startPosition |
||
188 | * |
||
189 | * @return int|bool |
||
190 | */ |
||
191 | private function loadNextDocBlockContent(int $startPosition) |
||
203 | |||
204 | /** |
||
205 | * Returns the position of the previous whitespace or star of the comment for checking the line after that. |
||
206 | * |
||
207 | * @param int $startPosition |
||
208 | * |
||
209 | * @return int|bool |
||
210 | */ |
||
211 | private function loadPrevDocBlockContent(int $startPosition) |
||
224 | |||
225 | /** |
||
226 | * Loads the position of the summary token if possible. |
||
227 | * |
||
228 | * @return int|null |
||
229 | */ |
||
230 | private function loadSummaryPosition(): ?int |
||
243 | |||
244 | /** |
||
245 | * Checks and registers errors if there are invalid doc comments. |
||
246 | * |
||
247 | * @throws CodeWarning |
||
248 | * |
||
249 | * @return void |
||
250 | */ |
||
251 | protected function processToken(): void |
||
257 | |||
258 | /** |
||
259 | * Resets the sniff after one processing. |
||
260 | * |
||
261 | * @return void |
||
262 | */ |
||
263 | protected function tearDown(): void |
||
268 | |||
269 | /** |
||
270 | * Validates the descriptions in the file. |
||
271 | * |
||
272 | * @return AbstractDocSniff |
||
273 | */ |
||
274 | private function validateDescriptions(): self |
||
307 | |||
308 | /** |
||
309 | * Checks if there is a line break after the comment block.. |
||
310 | * |
||
311 | * @param int $position |
||
312 | * @param array $token |
||
313 | * @param bool $asSingleLine |
||
314 | * |
||
315 | * @return void |
||
316 | */ |
||
317 | private function validateNewLineAfterDocComment(int $position, array $token, bool $asSingleLine = true): void |
||
337 | |||
338 | /** |
||
339 | * Checks if the summary is on line or registers a warning. |
||
340 | * |
||
341 | * @return bool We can skip the new line error, so return true if the one line summary is true. |
||
342 | */ |
||
343 | private function validateOneLineSummary(): bool |
||
344 | { |
||
345 | $isValid = true; |
||
346 | $summaryPos = $this->getSummaryPosition(); |
||
347 | $nextPossiblePos = $this->loadNextDocBlockContent($summaryPos); |
||
348 | |||
349 | 121 | if ($nextPossiblePos !== false && $nextPossiblePos > 0) { |
|
350 | $nextToken = $this->tokens[$nextPossiblePos]; |
||
351 | 121 | ||
352 | if (($nextToken['code'] === T_DOC_COMMENT_STRING) && !$this->isNextLineEmpty($summaryPos)) { |
||
353 | $isValid = false; |
||
354 | |||
355 | $this->file->addWarning( |
||
356 | self::MESSAGE_SUMMARY_TOO_LONG, |
||
357 | $nextPossiblePos, |
||
358 | static::CODE_SUMMARY_TOO_LONG |
||
359 | 121 | ); |
|
360 | } |
||
361 | 121 | } |
|
362 | |||
363 | 121 | return $isValid; |
|
364 | 121 | } |
|
365 | |||
366 | 1 | /** |
|
367 | * Returns position to the comment summary or null. |
||
368 | * |
||
369 | 121 | * @throws CodeWarning If there is no summary. |
|
370 | 121 | * |
|
371 | 121 | * @return $this |
|
372 | 121 | */ |
|
373 | 121 | private function validateSummaryExistence(): self |
|
387 | 113 | ||
388 | /** |
||
389 | * Checks if the first char of the doc comment is ucfirst. |
||
390 | 113 | * |
|
391 | 113 | * @param int $position |
|
392 | 113 | * @param array $token |
|
393 | * |
||
394 | 113 | * @return void |
|
395 | */ |
||
396 | private function validateUCFirstDocComment(int $position, array $token): void |
||
412 | } |
||
413 |
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: