Skip to content

Commit 7420ad3

Browse files
committed
Illustrate DocBlock source recovery
1 parent f2e61af commit 7420ad3

1 file changed

Lines changed: 35 additions & 15 deletions

File tree

‎lib/runner.php‎

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,21 @@ function export_docblock( $element, array $inherited_setup_blueprints = array(),
266266

267267
/*
268268
* phpDocumentor can split one fenced block across its short and long
269-
* descriptions, alter its line structure, and parse `@` code as tags. If
270-
* either description contains a possible fence, recover the original
271-
* DocBlock before tokenizing it below. File reflectors require slicing the
272-
* comment from the file contents; node-backed reflectors use the raw comment
273-
* captured above.
269+
* descriptions, alter its line structure, and parse `@` code as tags. For
270+
* example, this source:
271+
*
272+
* ```php interactive
273+
* <?php
274+
*
275+
* echo 'before';
276+
* @unlink( '/tmp/example' );
277+
* ```
278+
*
279+
* can leave the opening lines in the short description, the `echo` line in the
280+
* long description, and `@unlink` in the tag list. If either description
281+
* contains a possible fence, recover the original DocBlock before tokenizing
282+
* it below. File reflectors require slicing the comment from the file contents;
283+
* node-backed reflectors use the raw comment captured above.
274284
*/
275285
if ( false !== strpos( $short_description, '```' ) || false !== strpos( $raw_long_description, '```' ) ) {
276286
if ( $element instanceof File_Reflector ) {
@@ -300,13 +310,19 @@ function export_docblock( $element, array $inherited_setup_blueprints = array(),
300310
}
301311

302312
if ( null !== $source_docblock ) {
303-
// phpDocumentor treats any line beginning with `@` as a tag, even
304-
// inside a fenced block, and splits its short description at paragraph
305-
// boundaries inside fences. Recover the description directly from the
306-
// source comment so runnable code retains its source line structure. Stop
307-
// at the first real tag outside a fence. Keep track of tag-looking code
308-
// lines so the parsed DocBlock tags below can omit phpDocumentor's false
309-
// positives without hiding real tags with the same name.
313+
/*
314+
* Recover exact description lines from source and stop at the first tag
315+
* outside a fence. For example:
316+
*
317+
* ```php
318+
* @since( 'inside-fence' );
319+
* ```
320+
* @since 1.0.0
321+
*
322+
* The first `@since` remains snippet code; the second ends the description.
323+
* Record the first name so only phpDocumentor's false in-fence tag is
324+
* removed from the parsed tags, leaving the real `@since 1.0.0` tag.
325+
*/
310326
$source_docblock = preg_replace( "/\r\n?/", "\n", $source_docblock );
311327
$source_docblock = preg_replace( '/\A[ \t]*\/\*\*[ \t]?/', '', $source_docblock );
312328
$source_docblock = preg_replace( '/[ \t]*\*\/[ \t]*\z/', '', $source_docblock );
@@ -320,9 +336,6 @@ function export_docblock( $element, array $inherited_setup_blueprints = array(),
320336
$source_fences = tokenize_docblock_code_fences( implode( "\n", $source_lines ) );
321337
$source_fence_index = 0;
322338
$description_lines = array();
323-
// phpDocumentor starts its tag block at an optionally indented @ followed
324-
// by a letter. Once started, only a column-zero @ with any valid tag name
325-
// opens another tag; indented lines extend the preceding tag instead.
326339
$parsed_tag_block_started = false;
327340
foreach ( $source_lines as $source_line_number => $source_line ) {
328341
while (
@@ -334,6 +347,13 @@ function export_docblock( $element, array $inherited_setup_blueprints = array(),
334347
$is_in_fence = isset( $source_fences[ $source_fence_index ] ) &&
335348
$source_line_number > $source_fences[ $source_fence_index ]['start'];
336349

350+
/*
351+
* Before tag parsing starts, `^[ \t]*` permits indentation and `\pL`
352+
* requires a Unicode letter: ` @since` matches, while `@_before` does not.
353+
* Once started, `^@` requires column zero and the broader name class permits
354+
* an initial underscore or digit: `@_same` and `@2inside` match, while
355+
* ` @author` remains part of the preceding tag.
356+
*/
337357
$tag_pattern = $parsed_tag_block_started
338358
? '/^@([\w\-_\\\\]+)/u'
339359
: '/^[ \t]*@([\pL][\w\-_\\\\]*)/u';

0 commit comments

Comments
 (0)