MediaWiki master
MWDoxygenFilter.php
Go to the documentation of this file.
1<?php
10namespace MediaWiki\Maintenance;
11
35class MWDoxygenFilter {
40 public static function filter( $source ) {
41 $tokens = token_get_all( $source );
42 $buffer = null;
43 $output = '';
44 foreach ( $tokens as $token ) {
45 if ( is_string( $token ) ) {
46 if ( $buffer !== null && $token === ';' ) {
47 // If we still have a buffer and the statement has ended,
48 // flush it and move on.
49 $output .= $buffer['raw'];
50 $buffer = null;
51 }
52 $output .= $token;
53 continue;
54 }
55 [ $id, $content ] = $token;
56 switch ( $id ) {
57 case T_DOC_COMMENT:
58 // Escape slashes so that references to namespaces are not
59 // wrongly interpreted as a Doxygen "\command".
60 $content = addcslashes( $content, '\\' );
61 // Look for instances of "@var SomeType".
62 if ( preg_match( '#@var\s+\S+#', $content ) ) {
63 $buffer = [ 'raw' => $content, 'desc' => null, 'type' => null, 'name' => null ];
64 $buffer['desc'] = preg_replace_callback(
65 // Strip "@var SomeType" part, but remember the type and optional name
66 '#@var\s+(\S+)(\s+)?(\S+)?#',
67 static function ( $matches ) use ( &$buffer ) {
68 $buffer['type'] = $matches[1];
69 $buffer['name'] = $matches[3] ?? null;
70 return ( $matches[2] ?? '' ) . ( $matches[3] ?? '' );
71 },
72 $content
73 );
74 } else {
75 $output .= $content;
76 }
77 break;
78
79 case T_VARIABLE:
80 // Doxygen requires class members to be documented in one of two ways:
81 //
82 // 1. Fully qualified:
83 // /** @var SomeType $name Description here. */
84 //
85 // These result in the creation of a new virtual node called $name
86 // with the specified type and description. The real code doesn't
87 // even need to exist in this case.
88 //
89 // 2. Contextual:
90 // /** Description here. */
91 // private SomeType? $name;
92 //
93 // In MediaWiki, we are mostly like #1 but without the name repeated:
94 // /** @var SomeType Description here. */
95 // private $name;
96 //
97 // These emit a warning in Doxygen because they are missing a variable name.
98 // Convert these to the "Contextual" kind by stripping ""@var", injecting
99 // type into the code, and leaving the description in-place.
100 if ( $buffer !== null ) {
101 if ( $buffer['name'] === $content ) {
102 // Fully qualitied "@var" comment, leave as-is.
103 $output .= $buffer['raw'];
104 $output .= $content;
105 } else {
106 // MW-style "@var" comment. Keep only the description and transplant
107 // the type into the code.
108 $output .= $buffer['desc'];
109 $output .= "{$buffer['type']} $content";
110 }
111 $buffer = null;
112 } else {
113 $output .= $content;
114 }
115 break;
116
117 default:
118 if ( $buffer !== null ) {
119 $buffer['raw'] .= $content;
120 $buffer['desc'] .= $content;
121 } else {
122 $output .= $content;
123 }
124 break;
125 }
126 }
127 return $output;
128 }
129}
130
132class_alias( MWDoxygenFilter::class, 'MWDoxygenFilter' );
$source
Update the CREDITS list by merging in the list of git commit authors.