Unsuppress phan issues, part 8
authorDaimona Eaytoy <daimona.wiki@gmail.com>
Sun, 1 Sep 2019 12:45:11 +0000 (14:45 +0200)
committerKrinkle <krinklemail@gmail.com>
Wed, 4 Sep 2019 01:02:06 +0000 (01:02 +0000)
And also clean up the config.

Bug: T231636
Depends-On: Ie6233561de78457cae5e4e44e220feec2d1272d8
Change-Id: I82a279e1f7b0fdefd3bb712e46c7d0665429d065

15 files changed:
.phan/config.php
.phan/internal_stubs/pgsql.phan_php [new file with mode: 0644]
includes/Rest/EntryPoint.php
includes/Rest/Router.php
includes/Revision.php
includes/Revision/RevisionStoreFactory.php
includes/ServiceWiring.php
includes/Setup.php
includes/libs/lockmanager/PostgreSqlLockManager.php
includes/media/ExifBitmapHandler.php
includes/page/WikiPage.php
includes/parser/Preprocessor.php
includes/session/SessionManager.php
includes/user/User.php
maintenance/Maintenance.php

index fe63e47..47f4512 100644 (file)
@@ -32,21 +32,36 @@ $cfg['file_list'] = array_merge(
        class_exists( PHPUnit_TextUI_Command::class ) ? [] : [ '.phan/stubs/phpunit4.php' ],
        class_exists( ProfilerExcimer::class ) ? [] : [ '.phan/stubs/excimer.php' ],
        [
-               'maintenance/cleanupTable.inc',
-               'maintenance/CodeCleanerGlobalsPass.inc',
-               'maintenance/commandLine.inc',
-               'maintenance/sqlite.inc',
-               'maintenance/userDupes.inc',
-               'maintenance/language/checkLanguage.inc',
-               'maintenance/language/languages.inc',
+               // 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/DefaultSettings.php',
+               // 'includes/Setup.php',
        ]
 );
 
+$cfg['exclude_file_list'] = array_merge(
+       $cfg['exclude_file_list'],
+       [
+               // This file has invalid PHP syntax
+               'vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc',
+       ]
+);
+
+$cfg['analyzed_file_extensions'] = array_merge(
+       $cfg['analyzed_file_extensions'] ?? [ 'php' ],
+       [ 'inc' ]
+);
+
 $cfg['autoload_internal_extension_signatures'] = [
+       'dom' => '.phan/internal_stubs/dom.phan_php',
        'imagick' => '.phan/internal_stubs/imagick.phan_php',
+       'intl' => '.phan/internal_stubs/intl.phan_php',
        'memcached' => '.phan/internal_stubs/memcached.phan_php',
        'oci8' => '.phan/internal_stubs/oci8.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',
        'sqlsrv' => '.phan/internal_stubs/sqlsrv.phan_php',
@@ -65,7 +80,7 @@ $cfg['directory_list'] = [
 
 $cfg['exclude_analysis_directory_list'] = [
        'vendor/',
-       '.phan/stubs/',
+       '.phan/',
        // The referenced classes are not available in vendor, only when
        // included from composer.
        'includes/composer/',
@@ -77,14 +92,11 @@ $cfg['exclude_analysis_directory_list'] = [
 
 $cfg['suppress_issue_types'] = array_merge( $cfg['suppress_issue_types'], [
        // approximate error count: 19
-       "PhanParamReqAfterOpt", // False positives with nullables, ref phan issue #3159
+       "PhanParamReqAfterOpt", // False positives with nullables (phan issue #3159). Use real nullables
+       //after dropping HHVM
        // approximate error count: 110
        "PhanParamTooMany", // False positives with variargs. Unsuppress after dropping HHVM
 
-       // approximate error count: 22
-       "PhanAccessMethodInternal",
-       // approximate error count: 36
-       "PhanUndeclaredConstant",
        // approximate error count: 60
        "PhanTypeMismatchArgument",
        // approximate error count: 752
@@ -92,6 +104,8 @@ $cfg['suppress_issue_types'] = array_merge( $cfg['suppress_issue_types'], [
 ] );
 
 $cfg['ignore_undeclared_variables_in_global_scope'] = true;
+// @todo It'd be great if we could just make phan read these from DefaultSettings, to avoid
+// duplicating the types.
 $cfg['globals_type_map'] = array_merge( $cfg['globals_type_map'], [
        'IP' => 'string',
        'wgGalleryOptions' => 'array',
@@ -110,6 +124,7 @@ $cfg['globals_type_map'] = array_merge( $cfg['globals_type_map'], [
        'wgVirtualRestConfig' => 'array<string,array>',
        'wgWANObjectCaches' => 'array[]',
        'wgLocalInterwikis' => 'string[]',
+       'wgDebugLogGroups' => 'string|false|array{destination:string,sample?:int,level:int}',
 ] );
 
 return $cfg;
diff --git a/.phan/internal_stubs/pgsql.phan_php b/.phan/internal_stubs/pgsql.phan_php
new file mode 100644 (file)
index 0000000..c8a2b25
--- /dev/null
@@ -0,0 +1,189 @@
+<?php
+// These stubs were generated by the phan stub generator.
+// @phan-stub-for-extension pgsql@7.3.4
+
+namespace {
+function pg_affected_rows($result) {}
+function pg_cancel_query($connection) {}
+function pg_client_encoding($connection = null) {}
+function pg_clientencoding($connection = null) {}
+function pg_close($connection = null) {}
+function pg_cmdtuples($result) {}
+function pg_connect($connection_string, $connect_type = null, $host = null, $port = null, $options = null, $tty = null, $database = null) {}
+function pg_connect_poll($connection = null) {}
+function pg_connection_busy($connection) {}
+function pg_connection_reset($connection) {}
+function pg_connection_status($connection) {}
+function pg_consume_input($connection) {}
+function pg_convert($db, $table, $values, $options = null) {}
+function pg_copy_from($connection, $table_name, $rows, $delimiter = null, $null_as = null) {}
+function pg_copy_to($connection, $table_name, $delimiter = null, $null_as = null) {}
+function pg_dbname($connection = null) {}
+function pg_delete($db, $table, $ids, $options = null) {}
+function pg_end_copy($connection = null) {}
+function pg_errormessage($connection = null) {}
+function pg_escape_bytea($connection = null, $data = null) {}
+function pg_escape_identifier($connection = null, $data = null) {}
+function pg_escape_literal($connection = null, $data = null) {}
+function pg_escape_string($connection = null, $data = null) {}
+function pg_exec($connection = null, $query = null) {}
+function pg_execute($connection = null, $stmtname = null, $params = null) {}
+function pg_fetch_all($result, $result_type = null) {}
+function pg_fetch_all_columns($result, $column_number = null) {}
+function pg_fetch_array($result, $row = null, $result_type = null) {}
+function pg_fetch_assoc($result, $row = null) {}
+function pg_fetch_object($result, $row = null, $class_name = null, $l = null, $ctor_params = null) {}
+function pg_fetch_result($result, $row_number = null, $field_name = null) {}
+function pg_fetch_row($result, $row = null, $result_type = null) {}
+function pg_field_is_null($result, $row = null, $field_name_or_number = null) {}
+function pg_field_name($result, $field_number) {}
+function pg_field_num($result, $field_name) {}
+function pg_field_prtlen($result, $row = null, $field_name_or_number = null) {}
+function pg_field_size($result, $field_number) {}
+function pg_field_table($result, $field_number, $oid_only = null) {}
+function pg_field_type($result, $field_number) {}
+function pg_field_type_oid($result, $field_number) {}
+function pg_fieldisnull($result, $row = null, $field_name_or_number = null) {}
+function pg_fieldname($result, $field_number) {}
+function pg_fieldnum($result, $field_name) {}
+function pg_fieldprtlen($result, $row = null, $field_name_or_number = null) {}
+function pg_fieldsize($result, $field_number) {}
+function pg_fieldtype($result, $field_number) {}
+function pg_flush($connection) {}
+function pg_free_result($result) {}
+function pg_freeresult($result) {}
+function pg_get_notify($connection = null, $e = null) {}
+function pg_get_pid($connection = null) {}
+function pg_get_result($connection) {}
+function pg_getlastoid($result) {}
+function pg_host($connection = null) {}
+function pg_insert($db, $table, $values, $options = null) {}
+function pg_last_error($connection = null) {}
+function pg_last_notice($connection, $option = null) {}
+function pg_last_oid($result) {}
+function pg_lo_close($large_object) {}
+function pg_lo_create($connection = null, $large_object_id = null) {}
+function pg_lo_export($connection = null, $objoid = null, $filename = null) {}
+function pg_lo_import($connection = null, $filename = null, $large_object_oid = null) {}
+function pg_lo_open($connection = null, $large_object_oid = null, $mode = null) {}
+function pg_lo_read($large_object, $len = null) {}
+function pg_lo_read_all($large_object) {}
+function pg_lo_seek($large_object, $offset, $whence = null) {}
+function pg_lo_tell($large_object) {}
+function pg_lo_truncate($large_object, $size = null) {}
+function pg_lo_unlink($connection = null, $large_object_oid = null) {}
+function pg_lo_write($large_object, $buf, $len = null) {}
+function pg_loclose($large_object) {}
+function pg_locreate($connection = null, $large_object_id = null) {}
+function pg_loexport($connection = null, $objoid = null, $filename = null) {}
+function pg_loimport($connection = null, $filename = null, $large_object_oid = null) {}
+function pg_loopen($connection = null, $large_object_oid = null, $mode = null) {}
+function pg_loread($large_object, $len = null) {}
+function pg_loreadall($large_object) {}
+function pg_lounlink($connection = null, $large_object_oid = null) {}
+function pg_lowrite($large_object, $buf, $len = null) {}
+function pg_meta_data($db, $table) {}
+function pg_num_fields($result) {}
+function pg_num_rows($result) {}
+function pg_numfields($result) {}
+function pg_numrows($result) {}
+function pg_options($connection = null) {}
+function pg_parameter_status($connection, $param_name = null) {}
+function pg_pconnect($connection_string, $host = null, $port = null, $options = null, $tty = null, $database = null) {}
+function pg_ping($connection = null) {}
+function pg_port($connection = null) {}
+function pg_prepare($connection = null, $stmtname = null, $query = null) {}
+function pg_put_line($connection = null, $query = null) {}
+function pg_query($connection = null, $query = null) {}
+function pg_query_params($connection = null, $query = null, $params = null) {}
+function pg_result($connection) {}
+function pg_result_error($result) {}
+function pg_result_error_field($result, $fieldcode) {}
+function pg_result_seek($result, $offset) {}
+function pg_result_status($result, $result_type = null) {}
+function pg_select($db, $table, $ids, $options = null, $result_type = null) {}
+function pg_send_execute($connection, $stmtname, $params) {}
+function pg_send_prepare($connection, $stmtname, $query) {}
+function pg_send_query($connection, $query) {}
+function pg_send_query_params($connection, $query, $params) {}
+function pg_set_client_encoding($connection = null, $encoding = null) {}
+function pg_set_error_verbosity($connection = null, $verbosity = null) {}
+function pg_setclientencoding($connection = null, $encoding = null) {}
+function pg_socket($connection) {}
+function pg_trace($filename, $mode = null, $connection = null) {}
+function pg_transaction_status($connection) {}
+function pg_tty($connection = null) {}
+function pg_unescape_bytea($data) {}
+function pg_untrace($connection = null) {}
+function pg_update($db, $table, $fields, $ids, $options = null) {}
+function pg_version($connection = null) {}
+const PGSQL_ASSOC = 1;
+const PGSQL_BAD_RESPONSE = 5;
+const PGSQL_BOTH = 3;
+const PGSQL_COMMAND_OK = 1;
+const PGSQL_CONNECTION_AUTH_OK = 5;
+const PGSQL_CONNECTION_AWAITING_RESPONSE = 4;
+const PGSQL_CONNECTION_BAD = 1;
+const PGSQL_CONNECTION_MADE = 3;
+const PGSQL_CONNECTION_OK = 0;
+const PGSQL_CONNECTION_SETENV = 6;
+const PGSQL_CONNECTION_STARTED = 2;
+const PGSQL_CONNECT_ASYNC = 4;
+const PGSQL_CONNECT_FORCE_NEW = 2;
+const PGSQL_CONV_FORCE_NULL = 4;
+const PGSQL_CONV_IGNORE_DEFAULT = 2;
+const PGSQL_CONV_IGNORE_NOT_NULL = 8;
+const PGSQL_COPY_IN = 4;
+const PGSQL_COPY_OUT = 3;
+const PGSQL_DIAG_COLUMN_NAME = 99;
+const PGSQL_DIAG_CONSTRAINT_NAME = 110;
+const PGSQL_DIAG_CONTEXT = 87;
+const PGSQL_DIAG_DATATYPE_NAME = 100;
+const PGSQL_DIAG_INTERNAL_POSITION = 112;
+const PGSQL_DIAG_INTERNAL_QUERY = 113;
+const PGSQL_DIAG_MESSAGE_DETAIL = 68;
+const PGSQL_DIAG_MESSAGE_HINT = 72;
+const PGSQL_DIAG_MESSAGE_PRIMARY = 77;
+const PGSQL_DIAG_SCHEMA_NAME = 115;
+const PGSQL_DIAG_SEVERITY = 83;
+const PGSQL_DIAG_SEVERITY_NONLOCALIZED = 86;
+const PGSQL_DIAG_SOURCE_FILE = 70;
+const PGSQL_DIAG_SOURCE_FUNCTION = 82;
+const PGSQL_DIAG_SOURCE_LINE = 76;
+const PGSQL_DIAG_SQLSTATE = 67;
+const PGSQL_DIAG_STATEMENT_POSITION = 80;
+const PGSQL_DIAG_TABLE_NAME = 116;
+const PGSQL_DML_ASYNC = 1024;
+const PGSQL_DML_ESCAPE = 4096;
+const PGSQL_DML_EXEC = 512;
+const PGSQL_DML_NO_CONV = 256;
+const PGSQL_DML_STRING = 2048;
+const PGSQL_EMPTY_QUERY = 0;
+const PGSQL_ERRORS_DEFAULT = 1;
+const PGSQL_ERRORS_TERSE = 0;
+const PGSQL_ERRORS_VERBOSE = 2;
+const PGSQL_FATAL_ERROR = 7;
+const PGSQL_LIBPQ_VERSION = '9.6.9';
+const PGSQL_LIBPQ_VERSION_STR = 'PostgreSQL 9.6.9 (win32)';
+const PGSQL_NONFATAL_ERROR = 6;
+const PGSQL_NOTICE_ALL = 2;
+const PGSQL_NOTICE_CLEAR = 3;
+const PGSQL_NOTICE_LAST = 1;
+const PGSQL_NUM = 2;
+const PGSQL_POLLING_ACTIVE = 4;
+const PGSQL_POLLING_FAILED = 0;
+const PGSQL_POLLING_OK = 3;
+const PGSQL_POLLING_READING = 1;
+const PGSQL_POLLING_WRITING = 2;
+const PGSQL_SEEK_CUR = 1;
+const PGSQL_SEEK_END = 2;
+const PGSQL_SEEK_SET = 0;
+const PGSQL_STATUS_LONG = 1;
+const PGSQL_STATUS_STRING = 2;
+const PGSQL_TRANSACTION_ACTIVE = 1;
+const PGSQL_TRANSACTION_IDLE = 0;
+const PGSQL_TRANSACTION_INERROR = 3;
+const PGSQL_TRANSACTION_INTRANS = 2;
+const PGSQL_TRANSACTION_UNKNOWN = 4;
+const PGSQL_TUPLES_OK = 2;
+}
index a4959d1..f28b4ea 100644 (file)
@@ -47,6 +47,7 @@ class EntryPoint {
                        'cookiePrefix' => $conf->get( 'CookiePrefix' )
                ] );
 
+               // @phan-suppress-next-line PhanAccessMethodInternal
                $authorizer = new MWBasicAuthorizer( $context->getUser(),
                        $services->getPermissionManager() );
 
index 14b4c9c..961da01 100644 (file)
@@ -263,6 +263,7 @@ class Router {
         * @return ResponseInterface
         */
        private function executeHandler( $handler ): ResponseInterface {
+               // @phan-suppress-next-line PhanAccessMethodInternal
                $authResult = $this->basicAuth->authorize( $handler->getRequest(), $handler );
                if ( $authResult ) {
                        return $this->responseFactory->createHttpError( 403, [ 'error' => $authResult ] );
index de3c299..c6e727e 100644 (file)
@@ -89,6 +89,7 @@ class Revision implements IDBAccessObject {
         * @return SqlBlobStore
         */
        protected static function getBlobStore( $wiki = false ) {
+               // @phan-suppress-next-line PhanAccessMethodInternal
                $store = MediaWikiServices::getInstance()
                        ->getBlobStoreFactory()
                        ->newSqlBlobStore( $wiki );
index 0475557..acecee1 100644 (file)
@@ -125,6 +125,7 @@ class RevisionStoreFactory {
 
                $store = new RevisionStore(
                        $this->dbLoadBalancerFactory->getMainLB( $dbDomain ),
+                       // @phan-suppress-next-line PhanAccessMethodInternal
                        $this->blobStoreFactory->newSqlBlobStore( $dbDomain ),
                        $this->cache, // Pass local cache instance; Leave cache sharing to RevisionStore.
                        $this->commentStore,
index b53011f..740377c 100644 (file)
@@ -362,6 +362,7 @@ return [
 
        'MessageFormatterFactory' =>
        function ( MediaWikiServices $services ) : IMessageFormatterFactory {
+               // @phan-suppress-next-line PhanAccessMethodInternal
                return new MessageFormatterFactory();
        },
 
@@ -829,6 +830,7 @@ return [
        },
 
        '_SqlBlobStore' => function ( MediaWikiServices $services ) : SqlBlobStore {
+               // @phan-suppress-next-line PhanAccessMethodInternal
                return $services->getBlobStoreFactory()->newSqlBlobStore();
        },
 
index 1e65f52..cc9a3f9 100644 (file)
@@ -618,6 +618,7 @@ if ( $wgPHPSessionHandling !== 'enable' &&
 if ( defined( 'MW_NO_SESSION' ) ) {
        // If the entry point wants no session, force 'disable' here unless they
        // specifically set it to the (undocumented) 'warn'.
+       // @phan-suppress-next-line PhanUndeclaredConstant
        $wgPHPSessionHandling = MW_NO_SESSION === 'warn' ? 'warn' : 'disable';
 }
 
index fd3ffa5..5530eed 100644 (file)
@@ -7,6 +7,8 @@ use Wikimedia\Rdbms\DBError;
  * All locks are non-blocking, which avoids deadlocks.
  *
  * @ingroup LockManager
+ * @phan-file-suppress PhanUndeclaredConstant Phan doesn't read constants in LockManager
+ *   when accessed via self::
  */
 class PostgreSqlLockManager extends DBLockManager {
        /** @var array Mapping of lock types to the type actually used */
index 9058340..874e872 100644 (file)
@@ -26,6 +26,8 @@
  * All metadata related, since both JPEG and TIFF support Exif.
  *
  * @ingroup Media
+ * @phan-file-suppress PhanUndeclaredConstant Phan doesn't read constants in MediaHandler
+ *   when accessed via self::
  */
 class ExifBitmapHandler extends BitmapHandler {
        const BROKEN_FILE = '-1'; // error extracting metadata
index 4f0f2e2..9c5c4e0 100644 (file)
@@ -41,6 +41,8 @@ use Wikimedia\Rdbms\LoadBalancer;
  *
  * Some fields are public only for backwards-compatibility. Use accessors.
  * In the past, this class was part of Article.php and everything was public.
+ *
+ * @phan-file-suppress PhanAccessMethodInternal Due to the use of DerivedPageDataUpdater
  */
 class WikiPage implements Page, IDBAccessObject {
        // Constants for $mDataLoadedFrom and related
index b321078..99ca1be 100644 (file)
@@ -76,6 +76,7 @@ abstract class Preprocessor {
 
                $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
                $key = $cache->makeKey(
+                       // @phan-suppress-next-line PhanUndeclaredConstant
                        defined( 'static::CACHE_PREFIX' ) ? static::CACHE_PREFIX : static::class,
                        md5( $text ),
                        $flags
@@ -108,6 +109,7 @@ abstract class Preprocessor {
                $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
 
                $key = $cache->makeKey(
+                       // @phan-suppress-next-line PhanUndeclaredConstant
                        defined( 'static::CACHE_PREFIX' ) ? static::CACHE_PREFIX : static::class,
                        md5( $text ),
                        $flags
index fcc428d..1da0ceb 100644 (file)
@@ -321,6 +321,7 @@ final class SessionManager implements SessionManagerInterface {
 
        public function getVaryHeaders() {
                // @codeCoverageIgnoreStart
+               // @phan-suppress-next-line PhanUndeclaredConstant
                if ( defined( 'MW_NO_SESSION' ) && MW_NO_SESSION !== 'warn' ) {
                        return [];
                }
@@ -341,6 +342,7 @@ final class SessionManager implements SessionManagerInterface {
 
        public function getVaryCookies() {
                // @codeCoverageIgnoreStart
+               // @phan-suppress-next-line PhanUndeclaredConstant
                if ( defined( 'MW_NO_SESSION' ) && MW_NO_SESSION !== 'warn' ) {
                        return [];
                }
@@ -815,6 +817,7 @@ final class SessionManager implements SessionManagerInterface {
        public function getSessionFromInfo( SessionInfo $info, WebRequest $request ) {
                // @codeCoverageIgnoreStart
                if ( defined( 'MW_NO_SESSION' ) ) {
+                       // @phan-suppress-next-line PhanUndeclaredConstant
                        if ( MW_NO_SESSION === 'warn' ) {
                                // Undocumented safety case for converting existing entry points
                                $this->logger->error( 'Sessions are supposed to be disabled for this entry point', [
index 82f2ddc..ad6b5b8 100644 (file)
@@ -1752,6 +1752,7 @@ class User implements IDBAccessObject, UserIdentity {
                // overwriting mBlockedby, surely?
                $this->load();
 
+               // @phan-suppress-next-line PhanAccessMethodInternal It's the only allowed use
                $block = MediaWikiServices::getInstance()->getBlockManager()->getUserBlock(
                        $this,
                        $fromReplica
index 81bee4c..d899590 100644 (file)
@@ -1235,6 +1235,7 @@ abstract class Maintenance {
         */
        protected function afterFinalSetup() {
                if ( defined( 'MW_CMDLINE_CALLBACK' ) ) {
+                       // @phan-suppress-next-line PhanUndeclaredConstant
                        call_user_func( MW_CMDLINE_CALLBACK );
                }
        }