r76205 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r76204‎ | r76205 | r76206 >
Date:18:28, 6 November 2010
Author:platonides
Status:deferred
Tags:
Comment:
Add check for unknown functions.
This would be nice to use for compatibility checking with PHP 5.1, but this script itself
is not PHP 5.1 compatible due to the changes in the tokenizer in 5.1 to 5.2 on strings
containing variables, where the literals appear as T_STRING instead of T_ENCAPSED_AND_WHITESPACE
as in PHP 5.2+
Modified paths:
  • /trunk/tools/code-utils/check-vars.php (modified) (history)

Diff [purge]

Index: trunk/tools/code-utils/check-vars.php
@@ -47,9 +47,17 @@
4848 var $mDebug = false;
4949 static $mDefaultSettingsGlobals = null;
5050 static $mRequireKnownClasses = array();
 51+ static $mRequireKnownFunctions = array();
5152 static $mRequireKnownConstants = array();
5253
 54+ static $mKnownFileClassesDefault = array();
 55+ static $mKnownFunctionsDefault = array();
 56+ static $mConstantsDefault = array();
 57+
5358 static $constantIgnorePrefixes = array( "PGSQL_", "OCI_", "SQLT_BLOB", "DB2_", "XMLREADER_", "SQLSRV_" ); # Ignore constants with these prefixes
 59+ static $functionIgnorePrefixes = array( "pg_", "oci_", "db2_", "gmp_", "sqlsrv_", "exif_", "fss_", "tidy_",
 60+ "apc_", "eaccelerator_", "xcache_", "wincache_", "apache_", "xdiff_", "wikidiff2_", "parsekit_",
 61+ "wddx_", "setproctitle", "utf8_", "normalizer_" ); # Ignore functions with these prefixes
5462 protected $generateDeprecatedList = false;
5563
5664 /* Values for status */
@@ -154,29 +162,16 @@
155163 file_put_contents( $filename, $data );
156164 }
157165
 166+ private function initVars() {
 167+ $this->mProblemCount = 0;
158168
159 - function load( $file, $shortcircuit = true ) {
160 - $this->mProblemCount = 0;
161 - $this->mFilename = $file;
162 -
163169 /* These are used even if it's shortcircuited */
164 - $this->mKnownFileClasses = array();
 170+ $this->mKnownFileClasses = self::$mKnownFileClassesDefault;
165171 $this->mUnknownClasses = array();
166 - $this->mConstants = array();
 172+ $this->mUnknownFunctions = array();
 173+ $this->mKnownFunctions = self::$mKnownFunctionsDefault;
 174+ $this->mConstants = self::$mConstantsDefault;
167175
168 - $source = file_get_contents( $file );
169 - if ( substr( $source, 0, 3 ) == "\xEF\xBB\xBF" ) {
170 - $this->warning( "$file has an UTF-8 BOM" );
171 - }
172 - $source = rtrim( $source );
173 - if ( substr( $source, -2 ) == '?>' ) {
174 - $this->warning( "?> at end of file is deprecated in MediaWiki code" );
175 - }
176 - if ( $shortcircuit && !preg_match( "/^[^'\"#*]*function [^\"']*\$/m", $source ) ) {
177 - $this->mTokens = array();
178 - return;
179 - }
180 - $this->mTokens = token_get_all( $source );
181176 $this->mStatus = self::WAITING_FUNCTION;
182177 $this->mFunctionQualifiers = array();
183178
@@ -191,9 +186,28 @@
192187 'FILEINFO_MIME', 'FILEINFO_MIME_TYPE', 'MHASH_ADLER32',
193188 'SIGTERM', 'SIG_DFL',
194189 'SVN_REVISION_HEAD', 'SVN_REVISION_INITIAL',
195 - ) ;
 190+ ) ;
196191 }
 192+
 193+ function load( $file, $shortcircuit = true ) {
 194+ $this->initVars();
 195+ $this->mFilename = $file;
197196
 197+ $source = file_get_contents( $file );
 198+ if ( substr( $source, 0, 3 ) == "\xEF\xBB\xBF" ) {
 199+ $this->warning( "$file has an UTF-8 BOM" );
 200+ }
 201+ $source = rtrim( $source );
 202+ if ( substr( $source, -2 ) == '?>' ) {
 203+ $this->warning( "?> at end of file is deprecated in MediaWiki code" );
 204+ }
 205+ if ( $shortcircuit && !preg_match( "/^[^'\"#*]*function [^\"']*\$/m", $source ) ) {
 206+ $this->mTokens = array();
 207+ return;
 208+ }
 209+ $this->mTokens = token_get_all( $source );
 210+ }
 211+
198212 static $functionQualifiers = array( T_ABSTRACT, T_PRIVATE, T_PUBLIC, T_PROTECTED, T_STATIC );
199213
200214 function execute() {
@@ -288,6 +302,7 @@
289303 $this->mInSwitch = 0;
290304 $this->mFunctionGlobals = array();
291305 $currentToken[0] = self::FUNCTION_DEFINITION;
 306+ $this->mKnownFunctions[] = $this->mFunction;
292307
293308 if ( $this->generateDeprecatedList && in_array( self::FUNCTION_DEPRECATED, $this->mFunctionQualifiers ) ) {
294309 if ( ( substr( $this->mFunction, 0, 2 ) != "__" ) ) {
@@ -398,6 +413,7 @@
399414 if ( $lastMeaningfulToken[0] == T_STRING ) {
400415 $lastMeaningfulToken[0] = self::FUNCTION_NAME;
401416 $this->checkDeprecation( $lastMeaningfulToken );
 417+ $this->checkFunctionName( $lastMeaningfulToken );
402418 } else if ( $lastMeaningfulToken[0] == self::CLASS_MEMBER ) {
403419 $this->checkDeprecation( $lastMeaningfulToken );
404420 }
@@ -411,7 +427,7 @@
412428 $this->checkClassName( $lastMeaningfulToken );
413429 } else {
414430
415 - if ( !defined( $lastMeaningfulToken[1] ) && !in_array( $lastMeaningfulToken[1], $this->mConstants ) && !self::isIgnoreConstant( $lastMeaningfulToken[1] ) ) {
 431+ if ( !defined( $lastMeaningfulToken[1] ) && !in_array( $lastMeaningfulToken[1], $this->mConstants ) && !self::inIgnoreList( $lastMeaningfulToken[1], self::$constantIgnorePrefixes ) ) {
416432 $this->warning( "Use of undefined constant $lastMeaningfulToken[1] in line $lastMeaningfulToken[2]" );
417433 }
418434 }
@@ -480,6 +496,10 @@
481497 $this->mStatus = $this->mStatus - self::IN_REQUIRE_WAITING;
482498 continue;
483499 }
 500+ if ( $requirePath == "Mail.php" ) { # PEAR mail
 501+ $this->mStatus = $this->mStatus - self::IN_REQUIRE_WAITING;
 502+ continue;
 503+ }
484504
485505 if ( ( $requirePath == '' ) || ( !file_exists( $requirePath ) && $requirePath[0] != '/' ) ) {
486506 /* Try prepending the script folder, for maintenance scripts (but see Maintenance.php:758) */
@@ -491,6 +511,7 @@
492512 }
493513 } else if ( isset( self::$mRequireKnownClasses[$requirePath] ) ) {
494514 $this->mKnownFileClasses = array_merge( $this->mKnownFileClasses, self::$mRequireKnownClasses[$requirePath] );
 515+ $this->mKnownFunctions = array_merge( $this->mKnownFunctions, self::$mRequireKnownFunctions[$requirePath] );
495516 $this->mConstants = array_merge( $this->mConstants, self::$mRequireKnownConstants[$requirePath] );
496517 } else {
497518 $newCheck = new CheckVars;
@@ -498,8 +519,10 @@
499520 $newCheck->execute();
500521 /* Get the classes defined there */
501522 $this->mKnownFileClasses = array_merge( $this->mKnownFileClasses, $newCheck->mKnownFileClasses );
 523+ $this->mKnownFunctions = array_merge( $this->mKnownFunctions, $newCheck->mKnownFunctions );
502524 $this->mConstants = array_merge( $this->mConstants, $newCheck->mConstants );
503525 self::$mRequireKnownClasses[$requirePath] = $newCheck->mKnownFileClasses;
 526+ self::$mRequireKnownFunctions[$requirePath] = $newCheck->mKnownFunctions;
504527 self::$mRequireKnownConstants[$requirePath] = $newCheck->mConstants;
505528 }
506529 $this->mStatus = $this->mStatus - self::IN_REQUIRE_WAITING;
@@ -562,6 +585,7 @@
563586 }
564587
565588 $this->checkPendingClasses();
 589+ $this->checkPendingFunctions();
566590 }
567591
568592 function checkDeprecation( $token ) {
@@ -580,7 +604,48 @@
581605 }
582606 }
583607 }
 608+
 609+ function checkFunctionName( $token, $warn = 'defer' ) {
 610+ if ( !isset( $token['base'] ) ) {
 611+ // Local function
 612+
 613+ if ( substr( $token[1], 0, 2 ) == 'wf' ) {
 614+ // MediaWiki function
 615+ // TODO: List them.
 616+ return;
 617+ }
 618+ if ( $token[1] == 'dieout' && in_array( $this->mFunction, array( 'setup_database', 'initial_setup', 'setup_plpgsql' ) ) ) {
 619+ return;
 620+ }
 621+
 622+ if ( function_exists( $token[1] ) ) {
 623+ return;
 624+ }
 625+ if ( in_array( $token[1], $this->mKnownFunctions ) ) {
 626+ return;
 627+ }
 628+
 629+ if ( self::inIgnoreList( $token[1], self::$functionIgnorePrefixes ) ) {
 630+ return;
 631+ }
 632+
 633+ if ( $warn == 'now' ) {
 634+ $this->warning( "Unavailable function {$token[1]} in line {$token[2]}" );
 635+ } else if ( $warn == 'defer' ) {
 636+ // Defer to the end of the file
 637+ $this->mUnknownFunctions[] = $token;
 638+ }
 639+
 640+ }
 641+ }
584642
 643+ function checkPendingFunctions() {
 644+ foreach ( $this->mUnknownFunctions as $functionToken ) {
 645+ $this->checkFunctionName( $functionToken, 'now' );
 646+ }
 647+ $this->mUnknownFunctions = array();
 648+ }
 649+
585650 /* Returns a class name, or null if it couldn't guess */
586651 function guessClassName( $token ) {
587652 static $wellKnownVars = array(
@@ -736,6 +801,7 @@
737802 if ( substr( $token[1], 0, 12 ) == "Net_Gearman_" ) return $token[1]; # phase3/maintenance/gearman/gearman.inc
738803 if ( $token[1] == "PEAR_Error" ) return $token[1]; # Services_JSON.php
739804 if ( $token[1] == "PHP_Timer" ) return $token[1]; # From PEAR, used in ParserHelpers.php
 805+ if ( substr( $token[1], 0, 7 ) == "Imagick" ) return $token[1]; # Imagick extension, can be used by phpunit/includes/api/RandomImageGenerator.php
740806
741807 if ( !isset( $wgAutoloadLocalClasses[$token[1]] ) && !in_array( $token[1], $this->mKnownFileClasses ) ) {
742808 if ( $warn == 'now' ) {
@@ -757,8 +823,8 @@
758824 $this->mUnknownClasses = array();
759825 }
760826
761 - static function isIgnoreConstant( $name ) {
762 - foreach ( self::$constantIgnorePrefixes as $prefix ) {
 827+ static function inIgnoreList( $name, $list ) {
 828+ foreach ( $list as $prefix ) {
763829 if ( substr( $name, 0, strlen( $prefix ) ) == $prefix )
764830 return true;
765831 }
@@ -773,6 +839,26 @@
774840 return "-";
775841 }
776842
 843+ /**
 844+ * Sets a number of files which are considered as having always been
 845+ * loaded before any loaded one. Any functions/classes defined there
 846+ * will be assumed to be available.
 847+ */
 848+ function preloadFiles( $files ) {
 849+ $this->initVars();
 850+ $this->mFilename = '__preload';
 851+ $this->mTokens = array( T_OPEN_TAG, '<?php', 0 );
 852+
 853+ for ( $i = 1; $i <= count( $files ); $i++ ) {
 854+ $this->mTokens[] = array( T_REQUIRE, 'require', $i );
 855+ $this->mTokens[] = array( T_CONSTANT_ENCAPSED_STRING, "'" . $files[$i - 1] . "'", $i );
 856+ $this->mTokens[] = ';';
 857+ }
 858+ $this->execute();
 859+ self::$mKnownFileClassesDefault = $this->mKnownFileClasses;
 860+ self::$mKnownFunctionsDefault = $this->mKnownFunctions;
 861+ self::$mConstantsDefault = $this->mConstants;
 862+ }
777863 }
778864
779865 if( $argc < 2 ) {
@@ -786,6 +872,8 @@
787873 $cv->setGenerateDeprecatedList( true );
788874 array_shift( $argv );
789875 }
 876+$cv->preloadFiles( array( $IP . '/includes/GlobalFunctions.php' ) );
 877+
790878 foreach ( $argv as $arg ) {
791879 $cv->load( $arg );
792880 $cv->execute();

Status & tagging log