.phan/config.php
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/
$cfg = require __DIR__ . '/../vendor/mediawiki/mediawiki-phan-config/src/config.php';
// Whilst MediaWiki is still supporting PHP 7.4+, this lets us run phan on higher versions of PHP
// like 8.0 without phan trying to get us to make PHP 7.4-incompatible changes. This value should
// match the PHP version specified in composer.json and PHPVersionCheck.php.
$cfg['minimum_target_php_version'] = '7.4.3';
$cfg['file_list'] = array_merge(
$cfg['file_list'],
class_exists( Socket::class ) ? [] : [ '.phan/stubs/Socket.php' ],
class_exists( AllowDynamicProperties::class ) ? [] : [ '.phan/stubs/AllowDynamicProperties.php' ],
class_exists( WeakMap::class ) ? [] : [ '.phan/stubs/WeakMap.php' ],
[
// This makes constants and globals known to Phan before processing all other files.
// You can check the parser order with --dump-parsed-file-list
'includes/Defines.php',
// @todo This isn't working yet, see globals_type_map below
// 'includes/Setup.php',
'tests/phpunit/MediaWikiIntegrationTestCase.php',
'tests/phpunit/includes/TestUser.php',
]
);
$cfg['exclude_file_list'] = array_merge(
$cfg['exclude_file_list'],
[
// Avoid microsoft/tolerant-php-parser dependency
'maintenance/findDeprecated.php',
'maintenance/CodeCleanerGlobalsPass.php',
// Avoid nikic/php-parser dependency
'maintenance/shell.php',
]
);
if ( PHP_VERSION_ID >= 80000 ) {
// Exclude PHP 8.0 polyfills if PHP 8.0+ is running
$cfg['exclude_file_list'] = array_merge(
$cfg['exclude_file_list'],
[
'vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php',
]
);
}
$cfg['autoload_internal_extension_signatures'] = [
'excimer' => '.phan/internal_stubs/excimer.phan_php',
'imagick' => '.phan/internal_stubs/imagick.phan_php',
'memcached' => '.phan/internal_stubs/memcached.phan_php',
'pcntl' => '.phan/internal_stubs/pcntl.phan_php',
'pgsql' => '.phan/internal_stubs/pgsql.phan_php',
'redis' => '.phan/internal_stubs/redis.phan_php',
'sockets' => '.phan/internal_stubs/sockets.phan_php',
'tideways_xhprof' => '.phan/internal_stubs/tideways_xhprof.phan_php',
'wikidiff2' => '.phan/internal_stubs/wikidiff.php'
];
$cfg['directory_list'] = [
'includes/',
'languages/',
'maintenance/',
'mw-config/',
'resources/',
'tests/common/',
'tests/parser/',
'tests/phan',
'tests/phpunit/mocks/',
// Do NOT add .phan/stubs/ here: stubs are conditionally loaded in file_list
];
// Include only direct production dependencies in vendor/
// Omit dev dependencies and most indirect dependencies
$composerJson = json_decode(
file_get_contents( __DIR__ . '/../composer.json' ),
true
);
$directDeps = [];
foreach ( $composerJson['require'] as $dep => $version ) {
$parts = explode( '/', $dep );
if ( count( $parts ) === 2 ) {
$directDeps[] = $dep;
}
}
// This is a list of all composer packages that are referenced by core but
// are not listed as requirements in composer.json.
$indirectDeps = [
'composer/spdx-licenses',
'doctrine/dbal',
'doctrine/sql-formatter',
'guzzlehttp/psr7',
'pear/net_url2',
'pear/pear-core-minimal',
'phpunit/phpunit',
'psr/http-message',
'seld/jsonlint',
'wikimedia/testing-access-wrapper',
'wikimedia/zest-css',
];
foreach ( [ ...$directDeps, ...$indirectDeps ] as $dep ) {
$cfg['directory_list'][] = "vendor/$dep";
}
$cfg['exclude_analysis_directory_list'] = [
'vendor/',
'.phan/',
'tests/phpunit/',
// The referenced classes are not available in vendor, only when
// included from composer.
'includes/composer/',
// Directly references classes that only exist in Translate extension
'maintenance/language/',
// External class
'includes/libs/objectcache/utils/MemcachedClient.php',
// File may be valid, but may contain numerous "errors" such as iterating over an
// empty array due to the version checking in T246594 not being currently used.
'includes/PHPVersionCheck.php',
];
// TODO: Ideally we'd disable this in core, given we don't need backwards compatibility here and aliases
// should not be used. However, that would have unwanted side effects such as being unable to test
// taint-check (T321806).
$cfg['enable_class_alias_support'] = true;
$cfg['ignore_undeclared_variables_in_global_scope'] = true;
// @todo It'd be great if we could just make phan read these from config-schema.php, to avoid
// duplicating the types. config-schema.php has JSON types though, not PHP types.
// @todo As we are removing access to global variables from the code base,
// remove them from here as well, so phan complains when something tries to use them.
$cfg['globals_type_map'] = array_merge( $cfg['globals_type_map'], [
'IP' => 'string',
'wgTitle' => \MediaWiki\Title\Title::class,
'wgGalleryOptions' => 'array',
'wgDirectoryMode' => 'int',
'wgDummyLanguageCodes' => 'string[]',
'wgNamespaceProtection' => 'array<int,string|string[]>',
'wgNamespaceAliases' => 'array<string,int>',
'wgLockManagers' => 'array[]',
'wgForeignFileRepos' => 'array[]',
'wgDefaultUserOptions' => 'array',
'wgSkipSkins' => 'string[]',
'wgLogTypes' => 'string[]',
'wgLogNames' => 'array<string,string>',
'wgLogHeaders' => 'array<string,string>',
'wgLogActionsHandlers' => 'array<string,class-string>',
'wgPasswordPolicy' => 'array<string,array<string,string|array>>',
'wgVirtualRestConfig' => 'array<string,array>',
'wgLocalInterwikis' => 'string[]',
'wgDebugLogGroups' => 'string|false|array{destination:string,sample?:int,level:int}',
'wgCookiePrefix' => 'string|false',
'wgOut' => \MediaWiki\Output\OutputPage::class,
'wgExtraNamespaces' => 'string[]',
'wgRequest' => \MediaWiki\Request\WebRequest::class,
] );
// Include a local config file if it exists
if ( file_exists( __DIR__ . '/local-config.php' ) ) {
require __DIR__ . '/local-config.php';
}
return $cfg;