http://www.mediawiki.org/wiki/Special:Code/MediaWiki/72386
Revision: 72386
Author: platonides
Date: 2010-09-04 18:30:22 +0000 (Sat, 04 Sep 2010)
Log Message:
-----------
Recurse into the requires and improve detection of missing classes.
Also added require checking, but also when there are no variable arguments.
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-09-04 18:13:18 UTC (rev
72385)
+++ trunk/tools/code-utils/check-vars.php 2010-09-04 18:30:22 UTC (rev
72386)
@@ -4,7 +4,7 @@
* Checks a number of syntax conventions on variables from a valid PHP file.
*
* Run as:
- * find phase3/ \( -name \*.php -or -name \*.inc \) -not \( -name
importUseModWiki.php -o -name diffLanguage.php \) -exec php
tools/code-utils/check-vars.php \{\} +
+ * find phase3/ \( -name \*.php -or -name \*.inc \) -not \( -name
importUseModWiki.php -o -name diffLanguage.php -o -name LocalSettings.php \)
-exec php tools/code-utils/check-vars.php \{\} +
*/
require_once( dirname( __FILE__ ) . "/../../phase3/includes/Defines.php" ); #
Faster than parsing
@@ -43,6 +43,8 @@
class CheckVars {
var $mDebug = false;
static $mDefaultSettingsGlobals = null;
+ static $mRequireKnownClasses = array();
+ static $mRequireKnownConstants = array();
static $constantIgnorePrefixes = array( "PGSQL_", "OCI_", "SQLT_BLOB",
"DB2_", "XMLREADER_", "SQLSRV_" ); # Ignore constants with these prefixes
protected $generateDeprecatedList = false;
@@ -53,6 +55,8 @@
const IN_FUNCTION = 2;
const IN_GLOBAL = 3;
const IN_INTERFACE = 4;
+ const IN_REQUIRE_WAITING = 6;
+ const IN_FUNCTION_REQUIRE = 8;
/* Token specializations */
const CLASS_NAME = -4;
@@ -150,6 +154,12 @@
function load( $file, $shortcircuit = true ) {
$this->mProblemCount = 0;
$this->mFilename = $file;
+
+ /* These are used even if it's shortcircuited */
+ $this->mKnownFileClasses = array();
+ $this->mUnknownClasses = array();
+ $this->mConstants = array();
+
$source = file_get_contents( $file );
if ( substr( $source, 0, 3 ) == "\xEF\xBB\xBF" ) {
$this->warning( "$file has an UTF-8 BOM" );
@@ -165,8 +175,6 @@
$this->mTokens = token_get_all( $source );
$this->mStatus = self::WAITING_FUNCTION;
$this->mFunctionQualifiers = array();
- $this->mKnownFileClasses = array();
- $this->mUnknownClasses = array();
$this->mConstants = array( 'PARSEKIT_SIMPLE', 'UNORM_NFC', #
Extensions
@@ -237,6 +245,12 @@
$this->mParent = $token[1];
}
+ if ( in_array( $token[0], array(
T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE ) ) ) {
+ $this->mStatus =
self::IN_REQUIRE_WAITING;
+ $requirePath = "";
+ continue;
+ }
+
if ( $token[0] != T_FUNCTION )
continue;
$this->mStatus = self::IN_FUNCTION_NAME;
@@ -341,6 +355,10 @@
$this->checkClassName(
$token );
$currentToken[0] =
self::CLASS_NAME;
+ } else if ( in_array(
$token[0], array( T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE ) ) ) {
+ $this->mStatus =
self::IN_FUNCTION_REQUIRE;
+ $requirePath = '';
+ continue;
}
}
@@ -391,11 +409,11 @@
if ( is_array( $token ) ) {
if ( $token[0] == T_VARIABLE ) {
if (
!$this->shouldBeGlobal( $token[1] ) && !$this->canBeGlobal( $token[1] ) ) {
- $this->warning(
"Global variable {$token[1]} in line $token[2], function {$this->mFunction}
does not follow coding conventions" );
+ $this->warning(
"Global variable {$token[1]} in line {$token[2]}, function {$this->mFunction}
does not follow coding conventions" );
}
if ( isset(
$this->mFunctionGlobals[ $token[1] ] ) ) {
if (
!$this->mInSwitch ) {
-
$this->warning( $token[1] . " marked as global again in line $token[2],
function {$this->mFunction}" );
+
$this->warning( $token[1] . " marked as global again in line {$token[2]},
function {$this->mFunction}" );
}
} else {
$this->checkGlobalName( $token[1] );
@@ -418,6 +436,100 @@
$this->mStatus =
self::WAITING_FUNCTION;
}
continue;
+
+ case self::IN_REQUIRE_WAITING:
+ case self::IN_FUNCTION_REQUIRE:
+ if ( $token == ';' ) {
+ $requirePath = trim(
$requirePath, ')("' );
+
+ if ( substr( $requirePath, 0, 8
) == "PHPUnit/" ) {
+ $this->mStatus =
$this->mStatus - self::IN_REQUIRE_WAITING;
+ continue;
+ }
+ if ( $requirePath ==
"Testing/Selenium.php" ) {
+ $this->mStatus =
$this->mStatus - self::IN_REQUIRE_WAITING;
+ continue;
+ }
+ if ( substr( $requirePath, 0,
12 ) == "Net/Gearman/" ) {
+ $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) */
+ $requirePath = dirname(
$this->mFilename ) . "/" . $requirePath;
+ }
+ if ( !file_exists( $requirePath
) ) {
+ if ( strpos(
$requirePath, '$' ) === false ) {
+ $this->warning(
"Did not found the expected require of $requirePath" );
+ }
+ } else if ( isset(
self::$mRequireKnownClasses[$requirePath] ) ) {
+
$this->mKnownFileClasses = array_merge( $this->mKnownFileClasses,
self::$mRequireKnownClasses[$requirePath] );
+ $this->mConstants =
array_merge( $this->mConstants, self::$mRequireKnownConstants[$requirePath] );
+ } else {
+ $newCheck = new
CheckVars;
+ $newCheck->load(
$requirePath );
+ $newCheck->execute();
+ /* Get the classes
defined there */
+
$this->mKnownFileClasses = array_merge( $this->mKnownFileClasses,
$newCheck->mKnownFileClasses );
+ $this->mConstants =
array_merge( $this->mConstants, $newCheck->mConstants );
+
self::$mRequireKnownClasses[$requirePath] = $newCheck->mKnownFileClasses;
+
self::$mRequireKnownConstants[$requirePath] = $newCheck->mConstants;
+ }
+ $this->mStatus = $this->mStatus
- self::IN_REQUIRE_WAITING;
+ continue;
+ }
+
+ if ( $token[0] == T_WHITESPACE )
+ continue;
+
+ if ( $token[0] == T_STRING_VARNAME ) {
+ $token[0] = T_VARIABLE;
+ $token[1] = '$' . $token[1];
+ }
+ if ( $token[0] == T_VARIABLE &&
$this->mStatus == self::IN_FUNCTION_REQUIRE ) {
+ if ( isset(
$this->mFunctionGlobals[ $token[1] ] ) ) {
+
$this->mFunctionGlobals[ $token[1] ][0] ++;
+ } elseif (
$this->shouldBeGlobal( $token[1] ) ) {
+ $this->warning(
"{$token[1]} is used as local variable in line $token[2], function
{$this->mFunction}" );
+ }
+ }
+ if ( $token == '.' ) {
+ if ( $requirePath ==
'dirname(__FILE__)' ) {
+ $requirePath = dirname(
$this->mFilename );
+ } elseif ( $requirePath ==
'dirname(dirname(__FILE__))' ) {
+ $requirePath = dirname(
dirname( $this->mFilename ) );
+ }
+ } else if ( $token[0] == T_CURLY_OPEN
|| $token == '}' ) {
+ continue;
+ } else if ( !is_array( $token ) ) {
+ if ( ( $token != '(' ) ||
$requirePath != '' ) {
+ $requirePath .=
$token[0];
+ }
+ } else if ( in_array( $token[0], array(
T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE ) ) ) {
+ $requirePath .= trim(
$token[1], '\'"' );
+ } else if ( $token[0] == T_VARIABLE ) {
+ if ( $token[1] == '$IP' ||
$token[1] == '$mwPath' ) {
+ $requirePath .=
dirname( __FILE__ ) . '/../../phase3';
+ } elseif ( $token[1] == '$dir'
) {
+ // Scripts at
phase3/maintenance/language/
+ $requirePath .=
dirname( $this->mFilename );
+ } elseif ( $token[1] ==
'$wgStyleDirectory' ) {
+ $requirePath .=
dirname( __FILE__ ) . '/../../phase3/skins';
+ } elseif ( in_array( $token[1],
array( '$classFile', '$file', '$_fileName', '$fileName', '$filename' ) ) ) {
+ /* Maintenance.php
lines 374 and 894 */
+ /*
LocalisationCache.php, MessageCache.php, AutoLoader.php */
+ } else {
+ //$this->warning(
"require uses unknown variable {$token[1]} in line {$token[2]}" );
+ $requirePath .=
$token[1];
+ }
+ } elseif ( $token[0] == T_STRING &&
$token[1] == 'DO_MAINTENANCE' ) {
+ $requirePath .= dirname(
__FILE__ ) . '/../../phase3/maintenance/doMaintenance.php';
+ } else {
+ $requirePath .= $token[1];
+ }
+ continue;
+
}
}
@@ -527,6 +639,10 @@
if ( isset( self::$mGlobalsPerFile[$name] ) && in_array(
basename( $this->mFilename ) , self::$mGlobalsPerFile[$name] ) ) {
return true;
}
+ if ( $this->mFunction == 'loadWikimediaSettings' ) {
+ /* Skip the error about $site and $lang in
Maintenance.php */
+ return true;
+ }
return false;
}
@@ -588,7 +704,9 @@
if ( class_exists( $token[1], false ) ) return $token[1]; #
Provided by an extension
if ( substr( $token[1], 0, 8 ) == "PHPUnit_" ) return $token[1];
+ if ( $token[1] == "Testing_Selenium" || $token[1] ==
"Testing_Selenium_Exception" ) return $token[1];
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 ( !isset( $wgAutoloadLocalClasses[$token[1]] ) && !in_array(
$token[1], $this->mKnownFileClasses ) ) {
if ( $warn == 'now' ) {
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs