2022-02-18 08:05:02 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use PhpParser\Node;
|
|
|
|
|
use PhpParser\Node\Expr;
|
|
|
|
|
use PhpParser\Node\Stmt;
|
|
|
|
|
use PhpParser\ParserFactory;
|
2024-11-11 00:16:49 +00:00
|
|
|
use PhpParser\PhpVersion;
|
2022-02-18 08:05:02 +00:00
|
|
|
|
2022-10-07 00:45:44 +00:00
|
|
|
/**
|
|
|
|
|
* @coversNothing
|
|
|
|
|
*/
|
2022-02-18 08:05:02 +00:00
|
|
|
class ScopeStructureTest extends MediaWikiIntegrationTestCase {
|
|
|
|
|
|
|
|
|
|
public static function provideAutoloadNoFileScope() {
|
|
|
|
|
global $wgAutoloadLocalClasses;
|
|
|
|
|
$files = array_unique( $wgAutoloadLocalClasses );
|
|
|
|
|
$args = [];
|
|
|
|
|
foreach ( $files as $file ) {
|
|
|
|
|
$args[$file] = [ $file ];
|
|
|
|
|
}
|
|
|
|
|
return $args;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Confirm that all files in $wgAutoloadLocalClasses have no file-scope code
|
|
|
|
|
* apart from specific exemptions.
|
|
|
|
|
*
|
|
|
|
|
* This is slow (~15s).
|
|
|
|
|
*
|
|
|
|
|
* @dataProvider provideAutoloadNoFileScope
|
|
|
|
|
*/
|
|
|
|
|
public function testAutoloadNoFileScope( $file ) {
|
2025-06-17 13:47:16 +00:00
|
|
|
// This value should match the PHP version specified in composer.json,
|
|
|
|
|
// PHPVersionCheck.php, and .phan/config.php
|
|
|
|
|
$version = PhpVersion::fromComponents( 8, 1 );
|
|
|
|
|
$parser = ( new ParserFactory )->createForVersion( $version );
|
2022-02-18 08:05:02 +00:00
|
|
|
$ast = $parser->parse( file_get_contents( $file ) );
|
|
|
|
|
foreach ( $ast as $node ) {
|
|
|
|
|
if ( $node instanceof Stmt\ClassLike
|
|
|
|
|
|| $node instanceof Stmt\Namespace_
|
|
|
|
|
|| $node instanceof Stmt\Use_
|
|
|
|
|
|| $node instanceof Stmt\Nop
|
|
|
|
|
|| $node instanceof Stmt\Declare_
|
|
|
|
|
|| $node instanceof Stmt\Function_
|
|
|
|
|
) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ( $node instanceof Stmt\Expression ) {
|
|
|
|
|
$expr = $node->expr;
|
|
|
|
|
if ( $expr instanceof Expr\FuncCall ) {
|
|
|
|
|
if ( $expr->name instanceof Node\Name ) {
|
|
|
|
|
if ( in_array( $expr->name->toString(), [
|
|
|
|
|
'class_alias',
|
|
|
|
|
'define'
|
|
|
|
|
] ) ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} elseif ( $expr instanceof Expr\Include_ ) {
|
|
|
|
|
if ( $expr->type === Expr\Include_::TYPE_REQUIRE_ONCE ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} elseif ( $expr instanceof Expr\Assign ) {
|
|
|
|
|
if ( $expr->var->name === 'maintClass' ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$line = $node->getLine();
|
|
|
|
|
$this->assertNull( $node, "Found file scope code in $file at line $line" );
|
|
|
|
|
}
|
|
|
|
|
$this->assertTrue( true );
|
|
|
|
|
}
|
|
|
|
|
}
|