jenkins-bot has submitted this change and it was merged. Change subject: Add support for anonymous functions (closures). ......................................................................
Add support for anonymous functions (closures). http://php.net/manual/en/functions.anonymous.php Change-Id: If5617e1b5c0d05ef21fe88af633922d63f2c98ac --- M check-vars.php 1 file changed, 68 insertions(+), 3 deletions(-) Approvals: Demon: Looks good to me, approved jenkins-bot: Verified diff --git a/check-vars.php b/check-vars.php index dfe9bc3..5db3b65 100755 --- a/check-vars.php +++ b/check-vars.php @@ -324,6 +324,7 @@ private function initVars() { $this->mProblemCount = 0; + $this->anonymousFunction = false; /* These are used even if it's shortcircuited */ $this->mKnownFileClasses = self::$mKnownFileClassesDefault; @@ -371,6 +372,7 @@ $source = preg_replace( '/if \( isset\( \$_SERVER\[\'MW_COMPILED\'\] \) \) {\\s+require *\( \'core\/.*\' \);\\s+} else {/', 'if ( true ) {', $source ); $this->mTokens = token_get_all( $source ); + $this->queuedFunctions = array(); } static $functionQualifiers = array( T_ABSTRACT, T_PRIVATE, T_PUBLIC, T_PROTECTED, T_STATIC ); @@ -380,6 +382,7 @@ $currentToken = null; $runningQueuedFunctions = false; + do { foreach ( $this->mTokens as $token ) { if ( self::isMeaningfulToken( $currentToken ) ) $lastMeaningfulToken = $currentToken; @@ -418,6 +421,59 @@ // FIXME: Should be marked as defined only inside this T_IF $this->mConstants[] = trim( $token[1], "'\"" ); + } + + if ( $this->anonymousFunction ) { + switch ( $this->anonymousFunction[0] ) { + case 1: // After 'function' + if ( $token[0] == '(' ) { + $this->anonymousFunction[1] .= " ("; + $this->anonymousFunction[0] = 2; + } + break; + case 2: // In function parameters + $this->anonymousFunction[1] .= is_array( $token ) ? $token[1] : $token; + if ( $token[0] == ')' ) { + $this->anonymousFunction[0] = 3; + } + break; + case 3: // After function parameters + if ( $token[0] == T_USE ) { + $this->anonymousFunction[0] = 4; + $this->anonymousFunction[1] = rtrim( $this->anonymousFunction[1], ') ' ); + } elseif ( $token[0] == '{' ) { + $this->anonymousFunction[0] = 5; + $this->anonymousFunction[1] .= " {"; + $this->anonymousFunction[2] = 1; + } + break; + case 4: // In USE + if ( $token[0] != '(' ) { + $this->anonymousFunction[1] .= is_array( $token ) ? $token[1] : $token; + } + if ( $token[0] == T_VARIABLE ) { + // TODO: Check that it exists + } elseif ( $token[0] == '{' ) { + $this->anonymousFunction[0] = 5; + $this->anonymousFunction[2] = 1; + } + break; + case 5: + $this->anonymousFunction[1] .= is_array( $token ) ? $token[1] : $token; + if ( $token[0] == '{' || $token[0] == T_CURLY_OPEN || $token[0] == T_DOLLAR_OPEN_CURLY_BRACES ) { + $this->anonymousFunction[2]++; + } elseif ( $token[0] == '}' ) { + $this->anonymousFunction[2]--; + + if ( $this->anonymousFunction[2] == 0 ) { + $this->queuedFunctions[] = $this->anonymousFunction[1]; + $this->anonymousFunction = false; + } + } + break; + } + + continue; } switch ( $this->mStatus ) { @@ -578,7 +634,7 @@ } elseif ( $this->shouldBeGlobal( $token[1] ) ) { if ( $this->mStatus == self::IN_FUNCTION_PARAMETERS && $runningQueuedFunctions ) { // It will be a global passed in the use clause of the anonymous function - $this->mFunctionGlobals[ $token[1] ] = array( 0, 0, $token[2] ); + $this->mFunctionGlobals[ $token[1] ] = array( 0, 0, $token[2] ); // Register as global } else { $this->warning( 'global-as-local', "{$token[1]} is used as local variable in line $token[2], function {$this->mFunction}" ); } @@ -591,8 +647,9 @@ $this->warning( 'profileout', "$token[1] in line $token[2] is not preceded by wfProfileOut" ); } } elseif ( $token[0] == T_FUNCTION ) { - $this->warning( 'function-function', "Uh? Function inside function? A lambda function? (line $token[2])" ); - return; + // We are already inside a function, so we must be entering an anonymous function + $this->anonymousFunction = array( 1, "function __anonymous_function_line" . $token[2] ); + continue; } elseif ( $token[0] == T_SWITCH ) { if ( !$this->mInSwitch ) $this->mInSwitch = $this->mBraces; @@ -861,6 +918,14 @@ } } + if ( count( $this->queuedFunctions ) > 0 ) { + $this->mTokens = token_get_all( "<?php " . array_shift( $this->queuedFunctions ) ); + $runningQueuedFunctions = true; + continue; + } + break; + } while (1); + $this->checkPendingClasses(); $this->checkPendingFunctions(); } -- To view, visit https://gerrit.wikimedia.org/r/37510 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If5617e1b5c0d05ef21fe88af633922d63f2c98ac Gerrit-PatchSet: 8 Gerrit-Project: mediawiki/tools/code-utils Gerrit-Branch: master Gerrit-Owner: Platonides <[email protected]> Gerrit-Reviewer: Demon <[email protected]> Gerrit-Reviewer: Platonides <[email protected]> Gerrit-Reviewer: Thehansmeet <[email protected]> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
