http://www.mediawiki.org/wiki/Special:Code/MediaWiki/76205
Revision: 76205
Author: platonides
Date: 2010-11-06 18:28:08 +0000 (Sat, 06 Nov 2010)
Log Message:
-----------
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: trunk/tools/code-utils/check-vars.php
===================================================================
--- trunk/tools/code-utils/check-vars.php 2010-11-06 18:24:50 UTC (rev
76204)
+++ trunk/tools/code-utils/check-vars.php 2010-11-06 18:28:08 UTC (rev
76205)
@@ -47,9 +47,17 @@
var $mDebug = false;
static $mDefaultSettingsGlobals = null;
static $mRequireKnownClasses = array();
+ static $mRequireKnownFunctions = array();
static $mRequireKnownConstants = array();
+ static $mKnownFileClassesDefault = array();
+ static $mKnownFunctionsDefault = array();
+ static $mConstantsDefault = array();
+
static $constantIgnorePrefixes = array( "PGSQL_", "OCI_", "SQLT_BLOB",
"DB2_", "XMLREADER_", "SQLSRV_" ); # Ignore constants with these prefixes
+ static $functionIgnorePrefixes = array( "pg_", "oci_", "db2_", "gmp_",
"sqlsrv_", "exif_", "fss_", "tidy_",
+ "apc_", "eaccelerator_", "xcache_", "wincache_",
"apache_", "xdiff_", "wikidiff2_", "parsekit_",
+ "wddx_", "setproctitle", "utf8_", "normalizer_" ); #
Ignore functions with these prefixes
protected $generateDeprecatedList = false;
/* Values for status */
@@ -154,29 +162,16 @@
file_put_contents( $filename, $data );
}
+ private function initVars() {
+ $this->mProblemCount = 0;
- function load( $file, $shortcircuit = true ) {
- $this->mProblemCount = 0;
- $this->mFilename = $file;
-
/* These are used even if it's shortcircuited */
- $this->mKnownFileClasses = array();
+ $this->mKnownFileClasses = self::$mKnownFileClassesDefault;
$this->mUnknownClasses = array();
- $this->mConstants = array();
+ $this->mUnknownFunctions = array();
+ $this->mKnownFunctions = self::$mKnownFunctionsDefault;
+ $this->mConstants = self::$mConstantsDefault;
- $source = file_get_contents( $file );
- if ( substr( $source, 0, 3 ) == "\xEF\xBB\xBF" ) {
- $this->warning( "$file has an UTF-8 BOM" );
- }
- $source = rtrim( $source );
- if ( substr( $source, -2 ) == '?>' ) {
- $this->warning( "?> at end of file is deprecated in
MediaWiki code" );
- }
- if ( $shortcircuit && !preg_match( "/^[^'\"#*]*function
[^\"']*\$/m", $source ) ) {
- $this->mTokens = array();
- return;
- }
- $this->mTokens = token_get_all( $source );
$this->mStatus = self::WAITING_FUNCTION;
$this->mFunctionQualifiers = array();
@@ -191,9 +186,28 @@
'FILEINFO_MIME', 'FILEINFO_MIME_TYPE', 'MHASH_ADLER32',
'SIGTERM', 'SIG_DFL',
'SVN_REVISION_HEAD', 'SVN_REVISION_INITIAL',
- ) ;
+ ) ;
}
+
+ function load( $file, $shortcircuit = true ) {
+ $this->initVars();
+ $this->mFilename = $file;
+ $source = file_get_contents( $file );
+ if ( substr( $source, 0, 3 ) == "\xEF\xBB\xBF" ) {
+ $this->warning( "$file has an UTF-8 BOM" );
+ }
+ $source = rtrim( $source );
+ if ( substr( $source, -2 ) == '?>' ) {
+ $this->warning( "?> at end of file is deprecated in
MediaWiki code" );
+ }
+ if ( $shortcircuit && !preg_match( "/^[^'\"#*]*function
[^\"']*\$/m", $source ) ) {
+ $this->mTokens = array();
+ return;
+ }
+ $this->mTokens = token_get_all( $source );
+ }
+
static $functionQualifiers = array( T_ABSTRACT, T_PRIVATE, T_PUBLIC,
T_PROTECTED, T_STATIC );
function execute() {
@@ -288,6 +302,7 @@
$this->mInSwitch = 0;
$this->mFunctionGlobals =
array();
$currentToken[0] =
self::FUNCTION_DEFINITION;
+ $this->mKnownFunctions[] =
$this->mFunction;
if (
$this->generateDeprecatedList && in_array( self::FUNCTION_DEPRECATED,
$this->mFunctionQualifiers ) ) {
if ( ( substr(
$this->mFunction, 0, 2 ) != "__" ) ) {
@@ -398,6 +413,7 @@
if ( $lastMeaningfulToken[0] ==
T_STRING ) {
$lastMeaningfulToken[0]
= self::FUNCTION_NAME;
$this->checkDeprecation( $lastMeaningfulToken );
+
$this->checkFunctionName( $lastMeaningfulToken );
} else if (
$lastMeaningfulToken[0] == self::CLASS_MEMBER ) {
$this->checkDeprecation( $lastMeaningfulToken );
}
@@ -411,7 +427,7 @@
$this->checkClassName(
$lastMeaningfulToken );
} else {
- if ( !defined(
$lastMeaningfulToken[1] ) && !in_array( $lastMeaningfulToken[1],
$this->mConstants ) && !self::isIgnoreConstant( $lastMeaningfulToken[1] ) ) {
+ if ( !defined(
$lastMeaningfulToken[1] ) && !in_array( $lastMeaningfulToken[1],
$this->mConstants ) && !self::inIgnoreList( $lastMeaningfulToken[1],
self::$constantIgnorePrefixes ) ) {
$this->warning(
"Use of undefined constant $lastMeaningfulToken[1] in line
$lastMeaningfulToken[2]" );
}
}
@@ -480,6 +496,10 @@
$this->mStatus =
$this->mStatus - self::IN_REQUIRE_WAITING;
continue;
}
+ if ( $requirePath == "Mail.php"
) { # PEAR mail
+ $this->mStatus =
$this->mStatus - self::IN_REQUIRE_WAITING;
+ continue;
+ }
if ( ( $requirePath == '' ) ||
( !file_exists( $requirePath ) && $requirePath[0] != '/' ) ) {
/* Try prepending the
script folder, for maintenance scripts (but see Maintenance.php:758) */
@@ -491,6 +511,7 @@
}
} else if ( isset(
self::$mRequireKnownClasses[$requirePath] ) ) {
$this->mKnownFileClasses = array_merge( $this->mKnownFileClasses,
self::$mRequireKnownClasses[$requirePath] );
+ $this->mKnownFunctions
= array_merge( $this->mKnownFunctions,
self::$mRequireKnownFunctions[$requirePath] );
$this->mConstants =
array_merge( $this->mConstants, self::$mRequireKnownConstants[$requirePath] );
} else {
$newCheck = new
CheckVars;
@@ -498,8 +519,10 @@
$newCheck->execute();
/* Get the classes
defined there */
$this->mKnownFileClasses = array_merge( $this->mKnownFileClasses,
$newCheck->mKnownFileClasses );
+ $this->mKnownFunctions
= array_merge( $this->mKnownFunctions, $newCheck->mKnownFunctions );
$this->mConstants =
array_merge( $this->mConstants, $newCheck->mConstants );
self::$mRequireKnownClasses[$requirePath] = $newCheck->mKnownFileClasses;
+
self::$mRequireKnownFunctions[$requirePath] = $newCheck->mKnownFunctions;
self::$mRequireKnownConstants[$requirePath] = $newCheck->mConstants;
}
$this->mStatus = $this->mStatus
- self::IN_REQUIRE_WAITING;
@@ -562,6 +585,7 @@
}
$this->checkPendingClasses();
+ $this->checkPendingFunctions();
}
function checkDeprecation( $token ) {
@@ -580,7 +604,48 @@
}
}
}
+
+ function checkFunctionName( $token, $warn = 'defer' ) {
+ if ( !isset( $token['base'] ) ) {
+ // Local function
+
+ if ( substr( $token[1], 0, 2 ) == 'wf' ) {
+ // MediaWiki function
+ // TODO: List them.
+ return;
+ }
+ if ( $token[1] == 'dieout' && in_array(
$this->mFunction, array( 'setup_database', 'initial_setup', 'setup_plpgsql' ) )
) {
+ return;
+ }
+
+ if ( function_exists( $token[1] ) ) {
+ return;
+ }
+ if ( in_array( $token[1], $this->mKnownFunctions ) ) {
+ return;
+ }
+
+ if ( self::inIgnoreList( $token[1],
self::$functionIgnorePrefixes ) ) {
+ return;
+ }
+
+ if ( $warn == 'now' ) {
+ $this->warning( "Unavailable function
{$token[1]} in line {$token[2]}" );
+ } else if ( $warn == 'defer' ) {
+ // Defer to the end of the file
+ $this->mUnknownFunctions[] = $token;
+ }
+
+ }
+ }
+ function checkPendingFunctions() {
+ foreach ( $this->mUnknownFunctions as $functionToken ) {
+ $this->checkFunctionName( $functionToken, 'now' );
+ }
+ $this->mUnknownFunctions = array();
+ }
+
/* Returns a class name, or null if it couldn't guess */
function guessClassName( $token ) {
static $wellKnownVars = array(
@@ -736,6 +801,7 @@
if ( substr( $token[1], 0, 12 ) == "Net_Gearman_" ) return
$token[1]; # phase3/maintenance/gearman/gearman.inc
if ( $token[1] == "PEAR_Error" ) return $token[1]; #
Services_JSON.php
if ( $token[1] == "PHP_Timer" ) return $token[1]; # From PEAR,
used in ParserHelpers.php
+ if ( substr( $token[1], 0, 7 ) == "Imagick" ) return $token[1];
# Imagick extension, can be used by
phpunit/includes/api/RandomImageGenerator.php
if ( !isset( $wgAutoloadLocalClasses[$token[1]] ) && !in_array(
$token[1], $this->mKnownFileClasses ) ) {
if ( $warn == 'now' ) {
@@ -757,8 +823,8 @@
$this->mUnknownClasses = array();
}
- static function isIgnoreConstant( $name ) {
- foreach ( self::$constantIgnorePrefixes as $prefix ) {
+ static function inIgnoreList( $name, $list ) {
+ foreach ( $list as $prefix ) {
if ( substr( $name, 0, strlen( $prefix ) ) == $prefix )
return true;
}
@@ -773,6 +839,26 @@
return "-";
}
+ /**
+ * Sets a number of files which are considered as having always been
+ * loaded before any loaded one. Any functions/classes defined there
+ * will be assumed to be available.
+ */
+ function preloadFiles( $files ) {
+ $this->initVars();
+ $this->mFilename = '__preload';
+ $this->mTokens = array( T_OPEN_TAG, '<?php', 0 );
+
+ for ( $i = 1; $i <= count( $files ); $i++ ) {
+ $this->mTokens[] = array( T_REQUIRE, 'require', $i );
+ $this->mTokens[] = array( T_CONSTANT_ENCAPSED_STRING,
"'" . $files[$i - 1] . "'", $i );
+ $this->mTokens[] = ';';
+ }
+ $this->execute();
+ self::$mKnownFileClassesDefault = $this->mKnownFileClasses;
+ self::$mKnownFunctionsDefault = $this->mKnownFunctions;
+ self::$mConstantsDefault = $this->mConstants;
+ }
}
if( $argc < 2 ) {
@@ -786,6 +872,8 @@
$cv->setGenerateDeprecatedList( true );
array_shift( $argv );
}
+$cv->preloadFiles( array( $IP . '/includes/GlobalFunctions.php' ) );
+
foreach ( $argv as $arg ) {
$cv->load( $arg );
$cv->execute();
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs