Completed
Pull Request — master (#19)
by
unknown
08:16
created

AbstractDocSniff   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 439
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 96.3%

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 6
dl 0
loc 439
ccs 26
cts 27
cp 0.963
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 4 1
B process() 0 37 5
A getTagHelper() 0 4 1
getListenedTokens() 0 1 ?
getTagMetadata() 0 1 ?
getDisallowedTags() 0 1 ?
1
<?php
2
3
namespace BestIt;
4
5
use BestIt\Helper\DocDescriptionHelper;
6
use BestIt\Helper\DocHelper;
7
use BestIt\Helper\DocSummaryHelper;
8
use BestIt\Helper\DocTagHelper;
9
use BestIt\Helper\PropertyHelper;
10
use PHP_CodeSniffer_File;
11
use PHP_CodeSniffer_Sniff;
12
13
/**
14
 * Class AbstractDocSniff
15
 *
16
 * @package BestIt
17
 * @author Nick Lubisch <[email protected]>
18
 */
19
abstract class AbstractDocSniff implements PHP_CodeSniffer_Sniff
20
{
21
    /**
22
     * Defines the maximum line length.
23
     *
24
     * @var int
25
     */
26
    const MAX_LINE_LENGTH = 120;
27
28
    /**
29
     * Code that there is no immediate doc comment found before class.
30
     *
31
     * @var string
32
     */
33
    const CODE_NO_IMMEDIATE_DOC_FOUND = 'NoImmediateDocFound';
34
35
    /**
36
     * Message that there is no immediate doc comment found before class.
37
     *
38
     * @var string
39
     */
40
    const MESSAGE_NO_IMMEDIATE_DOC_FOUND = 'No immediate doc comment found before class.';
41
42
    /**
43
     * Code that there is no summary in doc comment.
44
     *
45
     * @var string
46
     */
47
    const CODE_NO_SUMMARY = 'NoSummary';
48
49
    /**
50
     * Message that there is no summary in doc comment.
51
     *
52
     * @var string
53
     */
54
    const MESSAGE_NO_SUMMARY = 'There must be a summary for the doc comment.';
55
56
    /**
57
     * Code that there is no summary in doc comment.
58
     *
59
     * @var string
60
     */
61
    const CODE_SUMMARY_NOT_FIRST = 'SummaryNotFirst';
62
63
    /**
64
     * Message that there is no summary in doc comment.
65
     *
66
     * @var string
67
     */
68
    const MESSAGE_SUMMARY_NOT_FIRST = 'The summary must be the first statement in a comment.';
69
70
    /**
71
     * Code that the summary is too long.
72
     *
73
     * @var string
74
     */
75
    const CODE_SUMMARY_TOO_LONG = 'SummaryTooLong';
76
77
    /**
78
     * Message that there is no summary in doc comment.
79
     *
80
     * @var string
81
     */
82
    const MESSAGE_SUMMARY_TOO_LONG = 'The summary line must not be longer than 120 chars.';
83
84
    /**
85
     * Code that the summary is not multi line.
86
     *
87
     * @var string
88
     */
89
    const CODE_COMMENT_NOT_MULTI_LINE = 'CommentNotMultiLine';
90
91
    /**
92
     * Message that comment is not multi line.
93
     *
94
     * @var string
95
     */
96
    const MESSAGE_COMMENT_NOT_MULTI_LINE = 'Comment is not multi line.';
97
98
    /**
99
     * Code that there is no line after summary.
100
     *
101
     * @var string
102
     */
103
    const CODE_NO_LINE_AFTER_SUMMARY = 'NoLineAfterSummary';
104
105
    /**
106
     * Message that there is no line after summary.
107
     *
108
     * @var string
109
     */
110
    const MESSAGE_NO_LINE_AFTER_SUMMARY = 'There is no empty line after the summary.';
111
112
    /**
113
     * Code that the line after the summary is not empty.
114
     *
115
     * @var string
116
     */
117
    const CODE_LINE_AFTER_SUMMARY_NOT_EMPTY = 'LineAfterSummaryNotEmpty';
118
119
    /**
120
     * Message that the line after the summary is not empty.
121
     *
122
     * @var string
123
     */
124
    const MESSAGE_LINE_AFTER_SUMMARY_NOT_EMPTY = 'The line after the summary is not empty.';
125
126
    /**
127
     * Code that no comment description is found.
128
     *
129
     * @var string
130
     */
131
    const CODE_DESCRIPTION_NOT_FOUND = 'DescriptionNotFound';
132
133
    /**
134
     * Message that no comment description is found.
135
     *
136
     * @var string
137
     */
138
    const MESSAGE_DESCRIPTION_NOT_FOUND = 'There must be an comment description.';
139
140
    /**
141
     * Code that there is no empty line after description.
142
     *
143
     * @var string
144
     */
145
    const CODE_NO_LINE_AFTER_DESCRIPTION = 'NoLineAfterDescription';
146
147
    /**
148
     * Message that there is no empty line after description.
149
     *
150
     * @var string
151
     */
152
    const MESSAGE_NO_LINE_AFTER_DESCRIPTION = 'There must be an empty line after description.';
153
154
    /**
155
     * Code that there is no empty line after description.
156
     *
157
     * @var string
158
     */
159
    const CODE_MUCH_LINES_AFTER_DESCRIPTION = 'MuchLinesAfterDescription';
160
161
    /**
162
     * Message that there is no empty line after description.
163
     *
164
     * @var string
165
     */
166
    const MESSAGE_MUCH_LINES_AFTER_DESCRIPTION = 'There must be exactly one empty line after description.';
167
168
    /**
169
     * Code that the description line is too long.
170
     *
171
     * @var string
172
     */
173
    const CODE_DESCRIPTION_TOO_LONG = 'DescriptionTooLong';
174
175
    /**
176
     * Message that the description line is too long.
177
     *
178
     * @var string
179
     */
180
    const MESSAGE_DESCRIPTION_TOO_LONG = 'The description exceeds the maximum length of 120 chars.';
181
182
    /**
183
     * Code that comment tag is not allowed.
184
     *
185
     * @var string
186
     */
187
    const CODE_TAG_NOT_ALLOWED = 'TagNotAllowed';
188
189
    /**
190
     * Message that comment tag is not allowed.
191
     *
192
     * @var string
193
     */
194
    const MESSAGE_TAG_NOT_ALLOWED = 'The comment tag "%s" is not allowed.';
195
196
    /**
197
     * Code that comment tag must appear minimum x times.
198
     *
199
     * @var string
200
     */
201
    const CODE_TAG_OCCURENCE_MIN = 'TagOccurenceMin';
202
203
    /**
204
     * Message that comment tag must appear minimum x times.
205
     *
206
     * @var string
207
     */
208
    const MESSAGE_TAG_OCCURENCE_MIN = 'The comment tag "%s" must appear minimum %d times.';
209
210
    /**
211
     * Code that comment tag must appear maximum x times.
212
     *
213
     * @var string
214
     */
215
    const CODE_TAG_OCCURENCE_MAX = 'TagOccurenceMax';
216
217
    /**
218
     * Message that comment tag must appear maximum x times.
219
     *
220
     * @var string
221
     */
222
    const MESSAGE_TAG_OCCURENCE_MAX = 'The comment tag "%s" must appear maximum %d times.';
223
224
    /**
225
     * Code that comment tag has the wrong position.
226
     *
227
     * @var string
228
     */
229
    const CODE_TAG_WRONG_POSITION = 'TagWrongPosition';
230
231
    /**
232
     * Message that comment tag has the wrong position.
233
     *
234
     * @var string
235
     */
236
    const MESSAGE_TAG_WRONG_POSITION = 'This tag has the wrong position. Expected "%s"';
237
238
    /**
239
     * Code that the summary starts with an capital letter.
240
     *
241
     * @var string
242
     */
243
    const CODE_SUMMARY_UC_FIRST = 'SummaryUcFirst';
244
245
    /**
246
     * Message that the summary starts with an capital letter.
247
     *
248
     * @var string
249
     */
250
    const MESSAGE_SUMMARY_UC_FIRST = 'The first letter of the summary is not uppercase';
251
252
    /**
253
     * Code that the description starts with an capital letter.
254
     *
255
     * @var string
256
     */
257
    const CODE_DESCRIPTION_UC_FIRST = 'DescriptionUcFirst';
258
259
    /**
260
     * Message that the description starts with an capital letter.
261
     *
262
     * @var string
263
     */
264
    const MESSAGE_DESCRIPTION_UC_FIRST = 'The first letter of the description is not uppercase';
265
266
    /**
267
     * Code that there is no line after given tag.
268
     *
269
     * @var string
270
     */
271
    const CODE_NO_LINE_AFTER_TAG = 'NoLineAfterTag';
272
273
    /**
274
     * Message that there is no line after given tag.
275
     *
276
     * @var string
277
     */
278
    const MESSAGE_NO_LINE_AFTER_TAG = 'There is no blank line after tag %s';
279
280
    /**
281
     * Code that there are too much lines after given tag.
282
     *
283
     * @var string
284
     */
285
    const CODE_MUCH_LINES_AFTER_TAG = 'MuchLinesAfterTag';
286
287
    /**
288
     * Message that there are too much lines after given tag.
289
     *
290
     * @var string
291
     */
292
    const MESSAGE_MUCH_LINES_AFTER_TAG = 'There are too much blank lines after tag %s';
293
294
    /**
295
     * Code that the tag content format is invalid.
296
     *
297
     * @var string
298
     */
299
    const CODE_TAG_CONTENT_FORMAT_INVALID = 'TagFormatContentInvalid';
300
301
    /**
302
     * Message that the tag content format is invalid.
303
     *
304
     * @var string
305
     */
306
    const MESSAGE_TAG_CONTENT_FORMAT_INVALID = '"%s"-Tag format is invalid. Expected: "%s"';
307
308
    /**
309
     * The PHP_CodeSniffer file where the token was found.
310
     *
311
     * @var PHP_CodeSniffer_File CodeSniffer file.
312
     */
313
    private $file;
314
315
    /**
316
     * The cs file token stack.
317
     *
318
     * @var array
319
     */
320
    private $tokens;
321
322
    /**
323
     * Pointer of the listened token.
324
     *
325
     * @var int
326
     */
327
    private $listenerPtr;
328
329
    /**
330
     * Token data of the listened token.
331
     *
332
     * @var int
333
     */
334
    private $listenerToken;
335
336
    /**
337
     * DocHelper for comment
338
     *
339
     * @var DocHelper
340
     */
341
    private $docHelper;
342
343
    /**
344
     * Helper for comment summary.
345
     *
346
     * @var DocSummaryHelper
347
     */
348
    protected $summaryHelper;
349
350
    /**
351
     * The doc comment description helper.
352
     *
353
     * @var DocDescriptionHelper
354
     */
355
    private $descriptionHelper;
356
357
    /**
358
     * The doc comment helper
359
     *
360
     * @var DocTagHelper
361
     */
362
    private $tagHelper;
363
364
    /**
365
     * Indicator if a description is required.
366
     *
367
     * @var bool
368
     */
369
    public $descriptionRequired = false;
370
371
    /**
372
     * Registers the tokens that this sniff wants to listen for.
373
     *
374
     * @return int[] List of tokens to listen for
375
     */
376 109
    public function register()
377
    {
378 109
        return $this->getListenedTokens();
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->getListenedTokens(); of type array|integer adds the type integer to the return on line 378 which is incompatible with the return type declared by the interface PHP_CodeSniffer_Sniff::register of type integer[].
Loading history...
379
    }
380
381
    /**
382
     * Called when one of the token types that this sniff is listening for is found.
383
     *
384
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where the token was found.
385
     * @param int $stackPtr The position in the PHP_CodeSniffer file's token stack where the token was found.
386
     *
387
     * @return void|int Optionally returns a stack pointer.
388
     */
389 109
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
390
    {
391 109
        $this->file = $phpcsFile;
392 109
        $this->tokens = $phpcsFile->getTokens();
393 109
        $this->listenerPtr = $stackPtr;
394 109
        $this->listenerToken = $this->tokens[$stackPtr];
395
396 109
        if (in_array(T_VARIABLE, $this->getListenedTokens(), true)
397 109
            && !PropertyHelper::isProperty($this->file, $this->listenerPtr)
398
        ) {
399
            return;
400
        }
401
402 109
        $this->docHelper = new DocHelper($phpcsFile, $stackPtr);
403 109
        $this->summaryHelper = new DocSummaryHelper($phpcsFile, $this->docHelper);
404 109
        $this->descriptionHelper = new DocDescriptionHelper($phpcsFile, $this->docHelper, $this->summaryHelper);
405 109
        $this->tagHelper = new DocTagHelper($phpcsFile, $this->docHelper, $stackPtr);
406
407 109
        if (!$this->docHelper->checkCommentExists($this->listenerPtr)) {
408 4
            return;
409
        }
410
411 105
        if (!$this->docHelper->checkCommentMultiLine()) {
412 4
            return;
413
        }
414
415 101
        $this->summaryHelper->checkCommentSummary();
416
417 101
        $this->descriptionHelper->checkCommentDescription(
418 101
            $this->descriptionRequired
419
        );
420
421 101
        $this->tagHelper->checkCommentTags(
422 101
            $this->getTagMetadata(),
423 101
            $this->getDisallowedTags()
424
        );
425 101
    }
426
427
    /**
428
     * Returns TagHelper
429
     *
430
     * @return DocTagHelper Returns doc comment tag helper for callable function
431
     */
432 53
    public function getTagHelper()
433
    {
434 53
        return $this->tagHelper;
435
    }
436
437
    /**
438
     * Returns which tokens should be listened to.
439
     *
440
     * @return array|int List of tokens to listen for
441
     */
442
    abstract public function getListenedTokens();
443
444
    /**
445
     * Returns allowed tag occurences.
446
     *
447
     * @return array List of tag metadata
448
     */
449
    abstract public function getTagMetadata();
450
451
    /**
452
     * Returns an array of disallowed tags.
453
     *
454
     * @return array List of disallowed tags
455
     */
456
    abstract public function getDisallowedTags();
457
}
458