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