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