From 56fdc4715eba743feb6f3228553b255bdee466d7 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 5 Sep 2019 17:58:07 +0100 Subject: [PATCH] docs: Factor out MWDoxygenFilter from mwdoc-filter.php with tests Bug: T232104 Change-Id: I591f44678cff4adb8863ce5c6ce231a8d3e162d7 --- autoload.php | 1 + maintenance/includes/MWDoxygenFilter.php | 107 ++++++++++++++ maintenance/mwdoc-filter.php | 77 +---------- .../maintenance/MWDoxygenFilterTest.php | 130 ++++++++++++++++++ 4 files changed, 244 insertions(+), 71 deletions(-) create mode 100644 maintenance/includes/MWDoxygenFilter.php create mode 100644 tests/phpunit/maintenance/MWDoxygenFilterTest.php diff --git a/autoload.php b/autoload.php index eb54f7c592..0255a237df 100644 --- a/autoload.php +++ b/autoload.php @@ -829,6 +829,7 @@ $wgAutoloadLocalClasses = [ 'MWCryptRand' => __DIR__ . '/includes/utils/MWCryptRand.php', 'MWDebug' => __DIR__ . '/includes/debug/MWDebug.php', 'MWDocGen' => __DIR__ . '/maintenance/mwdocgen.php', + 'MWDoxygenFilter' => __DIR__ . '/maintenance/includes/MWDoxygenFilter.php', 'MWException' => __DIR__ . '/includes/exception/MWException.php', 'MWExceptionHandler' => __DIR__ . '/includes/exception/MWExceptionHandler.php', 'MWExceptionRenderer' => __DIR__ . '/includes/exception/MWExceptionRenderer.php', diff --git a/maintenance/includes/MWDoxygenFilter.php b/maintenance/includes/MWDoxygenFilter.php new file mode 100644 index 0000000000..30cb97d4a9 --- /dev/null +++ b/maintenance/includes/MWDoxygenFilter.php @@ -0,0 +1,107 @@ + https://virtualtee.blogspot.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @ingroup Maintenance + * @phan-file-suppress PhanInvalidCommentForDeclarationType False negative about about `@var` + * @phan-file-suppress PhanUnextractableAnnotation False negative about about `@var` + */ + +/** + * Doxygen filter to show correct member variable types in documentation. + * + * Based on + * + * + * Improved to resolve various bugs and better MediaWiki PHPDoc conventions: + * + * - Insert variable name after typehint instead of at end of line so that + * documentation text may follow after `@var Type`. + * - Insert typehint into source code before $variable instead of inside the comment + * so that Doxygen interprets it. + * - Strip the text after `@var` from the output to avoid Doxygen warnings about bogus + * symbols being documented but not declared or defined. + * + * @internal For use by maintenance/mwdoc-filter.php + * @ingroup Maintenance + */ +class MWDoxygenFilter { + /** + * @param string $source Original source code + * @return string Filtered source code + */ + public static function filter( $source ) { + $tokens = token_get_all( $source ); + $buffer = $bufferType = null; + $output = ''; + foreach ( $tokens as $token ) { + if ( is_string( $token ) ) { + if ( $buffer !== null && $token === ';' ) { + // If we still have a buffer and the statement has ended, + // flush it and move on. + $output .= $buffer; + $buffer = $bufferType = null; + } + $output .= $token; + continue; + } + list( $id, $content ) = $token; + switch ( $id ) { + case T_DOC_COMMENT: + // Escape slashes so that references to namespaces are not + // wrongly interpreted as a Doxygen "\command". + $content = addcslashes( $content, '\\' ); + // Look for instances of "@var Type" not followed by $name. + if ( preg_match( '#@var\s+([^\s]+)\s+([^\$]+)#s', $content ) ) { + $buffer = preg_replace_callback( + // Strip the "@var Type" part and remember the type + '#(@var\s+)([^\s]+)#s', + function ( $matches ) use ( &$bufferType ) { + $bufferType = $matches[2]; + return ''; + }, + $content + ); + } else { + $output .= $content; + } + break; + + case T_VARIABLE: + if ( $buffer !== null ) { + $output .= $buffer; + $output .= "$bufferType $content"; + $buffer = $bufferType = null; + } else { + $output .= $content; + } + break; + + default: + if ( $buffer !== null ) { + $buffer .= $content; + } else { + $output .= $content; + } + break; + } + } + return $output; + } +} diff --git a/maintenance/mwdoc-filter.php b/maintenance/mwdoc-filter.php index 1da805e927..cabf48937e 100644 --- a/maintenance/mwdoc-filter.php +++ b/maintenance/mwdoc-filter.php @@ -1,22 +1,9 @@ - * - * Improved to resolve various bugs and better MediaWiki PHPDoc conventions: - * - * - Insert variable name after typehint instead of at end of line so that - * documentation text may follow after "@var Type". - * - Insert typehint into source code before $variable instead of inside the comment - * so that Doxygen interprets it. - * - Strip the text after @var from the output to avoid Doxygen warnings aboug bogus - * symbols being documented but not declared or defined. - * - * Copyright (C) 2012 Tamas Imrei https://virtualtee.blogspot.com/ + * This CLI script is intended to be configured as the INPUT_FILTER + * script in a Doxyfile, e.g. like "php mwdoc-filter.php". * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the "Software"), @@ -42,59 +29,7 @@ if ( PHP_SAPI != 'cli' && PHP_SAPI != 'phpdbg' ) { die( "This filter can only be run from the command line.\n" ); } -$source = file_get_contents( $argv[1] ); -$tokens = token_get_all( $source ); +require_once __DIR__ . '/includes/MWDoxygenFilter.php'; -$buffer = $bufferType = null; -foreach ( $tokens as $token ) { - if ( is_string( $token ) ) { - if ( $buffer !== null && $token === ';' ) { - // If we still have a buffer and the statement has ended, - // flush it and move on. - echo $buffer; - $buffer = $bufferType = null; - } - echo $token; - continue; - } - list( $id, $content ) = $token; - switch ( $id ) { - case T_DOC_COMMENT: - // Escape slashes so that references to namespaces are not - // wrongly interpreted as a Doxygen "\command". - $content = addcslashes( $content, '\\' ); - // Look for instances of "@var Type" not followed by $name. - if ( preg_match( '#@var\s+([^\s]+)\s+([^\$]+)#s', $content ) ) { - $buffer = preg_replace_callback( - // Strip the "@var Type" part and remember the type - '#(@var\s+)([^\s]+)#s', - function ( $matches ) use ( &$bufferType ) { - $bufferType = $matches[2]; - return ''; - }, - $content - ); - } else { - echo $content; - } - break; - - case T_VARIABLE: - if ( $buffer !== null ) { - echo $buffer; - echo "$bufferType $content"; - $buffer = $bufferType = null; - } else { - echo $content; - } - break; - - default: - if ( $buffer !== null ) { - $buffer .= $content; - } else { - echo $content; - } - break; - } -} +$source = file_get_contents( $argv[1] ); +echo MWDoxygenFilter::filter( $source ); diff --git a/tests/phpunit/maintenance/MWDoxygenFilterTest.php b/tests/phpunit/maintenance/MWDoxygenFilterTest.php new file mode 100644 index 0000000000..2e06d6f5c7 --- /dev/null +++ b/tests/phpunit/maintenance/MWDoxygenFilterTest.php @@ -0,0 +1,130 @@ + [ + <<<'CODE' + [ + <<<'CODE' + [ + <<<'CODE' + [ + // In this full form, Doxygen understands it just fine. + // No changes made. + <<<'CODE' + [ + <<<'CODE' + [ + <<<'CODE' + [ + <<<'CODE' +assertSame( $expected, MWDoxygenFilter::filter( $source ), 'Source code' ); + } +} -- 2.20.1