Conditions | 26 |
Paths | 124 |
Total Lines | 156 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | <?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase |
||
121 | public function parse( $changelog ) { |
||
122 | $ret = new Changelog(); |
||
123 | |||
124 | $bullet = $this->bullet . ' '; |
||
125 | $len = strlen( $bullet ); |
||
126 | $indent = str_repeat( ' ', $len ); |
||
127 | |||
128 | // Fix newlines and expand tabs. |
||
129 | $changelog = strtr( $changelog, array( "\r\n" => "\n" ) ); |
||
130 | $changelog = strtr( $changelog, array( "\r" => "\n" ) ); |
||
131 | while ( strpos( $changelog, "\t" ) !== false ) { |
||
132 | $changelog = preg_replace_callback( |
||
133 | '/^([^\t\n]*)\t/m', |
||
134 | function ( $m ) { |
||
135 | return $m[1] . str_repeat( ' ', 4 - ( mb_strlen( $m[1] ) % 4 ) ); |
||
136 | }, |
||
137 | $changelog |
||
138 | ); |
||
139 | } |
||
140 | |||
141 | // Extract link definitions. |
||
142 | $links = array(); |
||
143 | $usedlinks = array(); |
||
144 | while ( ( $m = $this->endsInLink( $changelog ) ) ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition |
||
145 | $links[ $m['id'] ] = $m['link']; |
||
146 | $usedlinks[ $m['id'] ] = false; |
||
147 | $changelog = (string) substr( $changelog, 0, -strlen( $m['match'] ) ); |
||
148 | } |
||
149 | $links = array_reverse( $links ); |
||
150 | |||
151 | // Everything up to the first level-2 ATX heading is the prologue. |
||
152 | list( $prologue, $changelog ) = $this->split( "\n$changelog", "\n## " ); |
||
153 | $ret->setPrologue( $prologue ); |
||
154 | |||
155 | // Entries make up the rest of the document. |
||
156 | $entries = array(); |
||
157 | while ( '' !== $changelog ) { |
||
158 | // Extract the first entry from the changelog file, then extract the heading from it. |
||
159 | list( $content, $changelog ) = $this->split( $changelog, "\n## " ); |
||
160 | list( $heading, $content ) = $this->split( $content, "\n" ); |
||
161 | |||
162 | // Parse the heading and create a ChangelogEntry for it. |
||
163 | if ( ! preg_match( '/^## +(\[?[^] ]+\]?) - (.+?) *$/', $heading, $m ) ) { |
||
164 | throw new InvalidArgumentException( "Invalid heading: $heading" ); |
||
165 | } |
||
166 | $link = null; |
||
167 | $version = $m[1]; |
||
168 | $timestamp = $m[2]; |
||
169 | if ( '[' === $version[0] && ']' === substr( $version, -1 ) ) { |
||
170 | $version = substr( $version, 1, -1 ); |
||
171 | if ( ! isset( $links[ $version ] ) ) { |
||
172 | throw new InvalidArgumentException( "Heading seems to have a linked version, but link was not found: $heading" ); |
||
173 | } |
||
174 | $link = $links[ $version ]; |
||
175 | $usedlinks[ $version ] = true; |
||
176 | } |
||
177 | try { |
||
178 | $timestamp = new DateTime( $timestamp, new DateTimeZone( 'UTC' ) ); |
||
179 | } catch ( \Exception $ex ) { |
||
180 | throw new InvalidArgumentException( "Heading has an invalid timestamp: $heading", 0, $ex ); |
||
181 | } |
||
182 | if ( strtotime( $m[2], 0 ) !== strtotime( $m[2], 1000000000 ) ) { |
||
183 | throw new InvalidArgumentException( "Heading has a relative timestamp: $heading" ); |
||
184 | } |
||
185 | $entry = $this->newChangelogEntry( |
||
186 | $version, |
||
187 | array( |
||
188 | 'link' => $link, |
||
189 | 'timestamp' => $timestamp, |
||
190 | ) |
||
191 | ); |
||
192 | $entries[] = $entry; |
||
193 | |||
194 | // Extract the prologue, if any. |
||
195 | list( $prologue, $content ) = $this->split( "\n$content", "\n### ", "\n$bullet" ); |
||
196 | $entry->setPrologue( $prologue ); |
||
197 | |||
198 | if ( '' === $content ) { |
||
199 | // Huh, no changes. |
||
200 | continue; |
||
201 | } |
||
202 | |||
203 | // Inject an empty heading if necessary so the change parsing can be more straightforward. |
||
204 | if ( '#' !== $content[0] ) { |
||
205 | $content = "### \n$content"; |
||
206 | } |
||
207 | |||
208 | // Now parse all the subheadings and changes. |
||
209 | while ( '' !== $content ) { |
||
210 | list( $section, $content ) = $this->split( $content, "\n### " ); |
||
211 | list( $subheading, $section ) = $this->split( $section, "\n" ); |
||
212 | $subheading = trim( substr( $subheading, 4 ) ); |
||
213 | $changes = array(); |
||
214 | $cur = ''; |
||
215 | $section = explode( "\n", $section ); |
||
216 | while ( $section ) { |
||
217 | $line = array_shift( $section ); |
||
218 | $prefix = substr( $line, 0, $len ); |
||
219 | if ( $prefix === $bullet ) { |
||
220 | $cur = trim( $cur ); |
||
221 | if ( '' !== $cur ) { |
||
222 | $changes[] = $cur; |
||
223 | } |
||
224 | $cur = substr( $line, $len ) . "\n"; |
||
225 | } elseif ( $prefix === $indent ) { |
||
226 | $cur .= substr( $line, $len ) . "\n"; |
||
227 | } elseif ( '' === $line ) { |
||
228 | $cur .= "\n"; |
||
229 | } else { |
||
230 | // If there are no more subsections and the rest of the lines don't contain |
||
231 | // bullets, assume it's an epilogue. Otherwise, assume it's an error. |
||
232 | $section = $line . "\n" . implode( "\n", $section ); |
||
233 | if ( '' === $content && strpos( $section, "\n$bullet" ) === false ) { |
||
234 | $entry->setEpilogue( $section ); |
||
235 | break; |
||
236 | } else { |
||
237 | throw new InvalidArgumentException( "Malformatted changes list near \"$line\"" ); |
||
238 | } |
||
239 | } |
||
240 | } |
||
241 | $cur = trim( $cur ); |
||
242 | if ( '' !== $cur ) { |
||
243 | $changes[] = $cur; |
||
244 | } |
||
245 | foreach ( $changes as $change ) { |
||
246 | $author = ''; |
||
247 | if ( $this->parseAuthors && preg_match( '/ \(([^()\n]+)\)$/', $change, $m ) ) { |
||
248 | $author = $m[1]; |
||
249 | $change = substr( $change, 0, -strlen( $m[0] ) ); |
||
250 | } |
||
251 | $entry->appendChange( |
||
252 | $this->newChangeEntry( |
||
253 | array( |
||
254 | 'subheading' => $subheading, |
||
255 | 'author' => $author, |
||
256 | 'content' => $change, |
||
257 | 'timestamp' => $timestamp, |
||
258 | ) |
||
259 | ) |
||
260 | ); |
||
261 | } |
||
262 | } |
||
263 | } |
||
264 | $ret->setEntries( $entries ); |
||
265 | |||
266 | // Append any unused links to the epilogue. |
||
267 | $epilogue = $ret->getEpilogue(); |
||
268 | foreach ( $links as $id => $content ) { |
||
269 | if ( empty( $usedlinks[ $id ] ) ) { |
||
270 | $epilogue .= "\n[$id]: $content"; |
||
271 | } |
||
272 | } |
||
273 | $ret->setEpilogue( $epilogue ); |
||
274 | |||
275 | return $ret; |
||
276 | } |
||
277 | |||
357 |
This check looks for
@param
annotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive.
Most often this is a case of a parameter that can be null in addition to its declared types.