Completed
Pull Request — master (#19)
by
unknown
06:03
created

DocSummaryHelper::getCommentSummaryPointer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 11
nc 2
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BestIt\CodeSniffer\Helper;
6
7
use BestIt\CodeSniffer\File;
8
use BestIt\Sniffs\Commenting\AbstractDocSniff;
9
10
/**
11
 * Class DocSummaryHelper
12
 *
13
 * @package BestIt\Helper
14
 * @author Nick Lubisch <[email protected]>
15
 */
16
class DocSummaryHelper
17
{
18
    /**
19
     * The php cs file.
20
     *
21
     * @var File
22
     */
23
    private $file;
24
25
    /**
26
     * The doc comment helper.
27
     *
28
     * @var DocHelper
29
     */
30
    private $docHelper;
31
32
    /**
33
     * Token stack of the current file.
34
     *
35
     * @var array
36
     */
37
    private $tokens;
38
39
    /**
40
     * DocSummaryHelper constructor.
41
     *
42
     * @param File $file The php cs file
43
     * @param DocHelper $docHelper The doc comment helper
44
     */
45 109
    public function __construct(File $file, DocHelper $docHelper)
46
    {
47 109
        $this->file = $file;
48 109
        $this->tokens = $file->getTokens();
49 109
        $this->docHelper = $docHelper;
50 109
    }
51
52
    /**
53
     * Returns pointer to the comment summary.
54
     *
55
     * @return int Pointer to the token or -1
56
     */
57 101
    public function getCommentSummaryPointer(): int
58
    {
59 101
        $commentStartPtr = $this->docHelper->getCommentStartPointer();
60 101
        $commentEndPtr = $this->docHelper->getCommentEndPointer();
61
62 101
        $summaryPtr = $this->file->findNext(
63
            [
64 101
                T_DOC_COMMENT_WHITESPACE,
65 101
                T_DOC_COMMENT_STAR
66
            ],
67 101
            $commentStartPtr + 1,
68 101
            $commentEndPtr,
69 101
            true
70
        );
71
72 101
        $summaryToken = $this->tokens[$summaryPtr];
73
74 101
        return $summaryToken['code'] === T_DOC_COMMENT_STRING ? $summaryPtr : -1;
75
    }
76
77
    /**
78
     * Returns comment summary token.
79
     *
80
     * @return array Summary token array
81
     */
82 97
    public function getCommentSummaryToken(): array
83
    {
84 97
        return $this->tokens[$this->getCommentSummaryPointer()];
85
    }
86
87
    /**
88
     * Check class comment summary.
89
     *
90
     * @return void
91
     */
92 101
    public function checkCommentSummary(): void
93
    {
94 101
        $commentEndPtr = $this->docHelper->getCommentEndPointer();
95 101
        $commentStartPtr = $this->docHelper->getCommentStartPointer();
96 101
        $commentStartToken = $this->docHelper->getCommentStartToken();
97
98 101
        $summaryPtr = $this->getCommentSummaryPointer();
99
100 101
        if ($summaryPtr === -1) {
101 4
            $this->file->addError(
102 4
                AbstractDocSniff::MESSAGE_NO_SUMMARY,
103 4
                $commentStartPtr,
104 4
                AbstractDocSniff::CODE_NO_SUMMARY
105
            );
106
107 4
            return;
108
        }
109
110 97
        $summaryToken = $this->tokens[$summaryPtr];
111
112 97
        $this->checkSummaryIsFirstLine($commentStartToken, $summaryToken, $summaryPtr);
113 97
        $this->checkSummaryCapitalLetter($summaryToken, $summaryPtr);
114 97
        $this->checkSummaryLineLength($summaryToken, $summaryPtr);
115 97
        $this->checkLineAfterSummary($summaryPtr, $commentEndPtr);
116 97
    }
117
118
    /**
119
     * Checks that the first character of the summary is upper case.
120
     *
121
     * @param array $summaryToken Token of the summary
122
     * @param int $summaryPtr Pointer to the summary
123
     *
124
     * @return void
125
     */
126 97 View Code Duplication
    private function checkSummaryCapitalLetter(array $summaryToken, int $summaryPtr): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
    {
128 97
        $summaryText = $summaryToken['content'];
129
130 97
        if (ucfirst($summaryText) === $summaryText) {
131 93
            return;
132
        }
133
134 8
        $fixUcFirst = $this->file->addFixableError(
135 8
            AbstractDocSniff::MESSAGE_SUMMARY_UC_FIRST,
136 8
            $summaryPtr,
137 8
            AbstractDocSniff::CODE_SUMMARY_UC_FIRST
138
        );
139
140 8
        if ($fixUcFirst) {
141 4
            $this->fixSummaryUcFirst($summaryToken, $summaryPtr);
142
        }
143 8
    }
144
145
    /**
146
     * Checks if the line length of the summary is maximum 120 chars.
147
     *
148
     * @param array $summaryToken Token array of the summary
149
     * @param int $summaryPtr Pointer of the summary
150
     *
151
     * @return void
152
     */
153 97
    private function checkSummaryLineLength(array $summaryToken, int $summaryPtr): void
154
    {
155 97
        $summaryLineLength = $summaryToken['column'] + $summaryToken['length'];
156
157 97
        if ($summaryLineLength > AbstractDocSniff::MAX_LINE_LENGTH) {
158 4
            $this->file->addError(
159 4
                AbstractDocSniff::MESSAGE_SUMMARY_TOO_LONG,
160 4
                $summaryPtr,
161 4
                AbstractDocSniff::CODE_SUMMARY_TOO_LONG
162
            );
163
        }
164 97
    }
165
166
    /**
167
     * Checks if the summary is the first line of the comment.
168
     *
169
     * @param array $commentStartToken Token array of the comment start
170
     * @param array $summaryToken Token of the summary
171
     * @param int $summaryPtr Pointer to the summary
172
     *
173
     * @return void
174
     */
175 97
    private function checkSummaryIsFirstLine(array $commentStartToken, array $summaryToken, int $summaryPtr): void
176
    {
177 97
        if ($summaryToken['line'] !== $commentStartToken['line'] + 1) {
178 8
            $fixSummaryNotFirst = $this->file->addFixableError(
179 8
                AbstractDocSniff::MESSAGE_SUMMARY_NOT_FIRST,
180 8
                $summaryPtr,
181 8
                AbstractDocSniff::CODE_SUMMARY_NOT_FIRST
182
            );
183
184 8
            if ($fixSummaryNotFirst) {
185 4
                $this->fixSummaryNotFirst();
186
            }
187
        }
188 97
    }
189
190
    /**
191
     * Checks the line after the summary.
192
     *
193
     * @param int $summaryPtr Pointer to the summary
194
     * @param int $commentEndPtr Pointer to the end of the doc comment
195
     *
196
     * @return void
197
     */
198 97
    private function checkLineAfterSummary(int $summaryPtr, int $commentEndPtr): void
199
    {
200 97
        $summaryToken = $this->getCommentSummaryToken();
201
202 97
        $nextRelevantPtr = $this->file->findNext(
203
            [
204 97
                T_DOC_COMMENT_WHITESPACE,
205 97
                T_DOC_COMMENT_STAR
206
            ],
207 97
            $summaryPtr + 1,
208 97
            $commentEndPtr,
209 97
            true
210
        );
211
212 97
        if ($nextRelevantPtr === -1) {
213
            return;
214
        }
215
216 97
        $nextRelevantToken = $this->tokens[$nextRelevantPtr];
217
218 97
        if (($nextRelevantToken['line'] - $summaryToken['line']) === 1) {
219 8
            $fixLineAfterSummary = $this->file->addFixableError(
220 8
                AbstractDocSniff::MESSAGE_NO_LINE_AFTER_SUMMARY,
221 8
                $summaryPtr,
222 8
                AbstractDocSniff::CODE_NO_LINE_AFTER_SUMMARY
223
            );
224
225 8
            if ($fixLineAfterSummary) {
226 4
                $this->fixNoLineAfterSummary();
227
            }
228
        }
229 97
    }
230
231
    /**
232
     * Fixes no line after summary.
233
     *
234
     * @return void
235
     */
236 4 View Code Duplication
    private function fixNoLineAfterSummary(): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
237
    {
238 4
        $summaryPtr = $this->getCommentSummaryPointer();
239 4
        $summaryToken = $this->getCommentSummaryToken();
240
241 4
        $this->file->getFixer()->beginChangeset();
242
243 4
        $this->file->getFixer()->addContent(
244 4
            $summaryPtr,
245 4
            $this->file->getEolChar() . str_repeat('    ', $summaryToken['level']) . ' *'
246
        );
247
248 4
        $this->file->getFixer()->endChangeset();
249 4
    }
250
251
    /**
252
     * Fixes summary not first statement.
253
     *
254
     * @return void
255
     */
256 4
    private function fixSummaryNotFirst(): void
257
    {
258 4
        $commentStartToken = $this->docHelper->getCommentStartToken();
259 4
        $summaryStartToken = $this->getCommentSummaryToken();
260
261 4
        $startLine = $commentStartToken['line'] + 1;
262 4
        $endLine = $summaryStartToken['line'] - 1;
263
264 4
        $this->file->getFixer()->beginChangeset();
265 4
        $this->file->getFixer()->removeLines($startLine, $endLine);
266 4
        $this->file->getFixer()->endChangeset();
267 4
    }
268
269
    /**
270
     * Fixes the first letter of the summary to be uppercase.
271
     *
272
     * @param array $summaryToken Token array of the summary
273
     * @param int $summaryPtr Pointer to the summary
274
     *
275
     * @return void
276
     */
277 4 View Code Duplication
    private function fixSummaryUcFirst(array $summaryToken, int $summaryPtr): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
278
    {
279 4
        $this->file->getFixer()->beginChangeset();
280
281 4
        $this->file->getFixer()->replaceToken($summaryPtr, ucfirst($summaryToken['content']));
282
283 4
        $this->file->getFixer()->endChangeset();
284 4
    }
285
}
286