2
0
forked from Wavyzz/dolibarr
Files
dolibarr-fork/dev/tools/phan/config.php
MDW 7f6c09fc63 Qual: Update baseline, enable PhanTypeMismatchArgument
# Qual: Update baseline, enable PhanTypeMismatchArgument

Update the baseline for fixes.
Enable PhanTypeMismatchArgument as this is being fixed and to avoid
that new cases occur in files where these are fixed.
Only about 3800 cases remain, was more than 12000 when starting with Phan.
2025-02-03 16:05:59 +01:00

504 lines
20 KiB
PHP

<?php
/* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*/
define('DOL_PROJECT_ROOT', __DIR__.'/../../..');
define('DOL_DOCUMENT_ROOT', DOL_PROJECT_ROOT.'/htdocs');
define('PHAN_DIR', __DIR__);
$sanitizeRegex
= '/^(array:)?(?:'.implode(
'|',
array(
// Documented:
'none',
'password',
'array',
'int',
'intcomma',
'alpha',
'alphawithlgt',
'alphanohtml',
'MS',
'aZ',
'aZ09',
'aZ09arobase',
'aZ09comma',
'email',
'san_alpha',
'restricthtml',
'nohtml',
'custom',
// Not documented:
'restricthtmlallowclass',
'restricthtmlallowunvalid',
'restricthtmlnolink',
'restricthtmlallowlinkscript'
)
).')*$/';
/**
* Map deprecated module names to new module names
*/
$DEPRECATED_MODULE_MAPPING = array(
'actioncomm' => 'agenda',
'adherent' => 'member',
'adherent_type' => 'member_type',
'banque' => 'bank',
'categorie' => 'category',
'commande' => 'order',
'contrat' => 'contract',
'entrepot' => 'stock',
'expedition' => 'shipping',
'facture' => 'invoice',
'ficheinter' => 'intervention',
'product_fournisseur_price' => 'productsupplierprice',
'product_price' => 'productprice',
'projet' => 'project',
'propale' => 'propal',
'socpeople' => 'contact',
);
/**
* Map module names to the 'class' name (the class is: mod<CLASSNAME>)
* Value is null when the module is not internal to the default
* Dolibarr setup.
*/
$VALID_MODULE_MAPPING = array(
'accounting' => 'Accounting',
'agenda' => 'Agenda',
'ai' => 'Ai',
'anothermodule' => null,
'api' => 'Api',
'asset' => 'Asset',
'bank' => 'Banque',
'barcode' => 'Barcode',
'blockedlog' => 'BlockedLog',
'bom' => 'Bom',
'bookcal' => 'BookCal',
'bookmark' => 'Bookmark',
'cashdesk' => null, // TODO: fill in proper class
'category' => 'Categorie',
'clicktodial' => 'ClickToDial',
'collab' => 'Collab',
'comptabilite' => 'Comptabilite',
'contact' => null, // TODO: fill in proper class
'contract' => 'Contrat',
'cron' => 'Cron',
'datapolicy' => 'DataPolicy',
'dav' => 'Dav',
'debugbar' => 'DebugBar',
'shipping' => 'Expedition',
'deplacement' => 'Deplacement',
"documentgeneration" => 'DocumentGeneration',
'don' => 'Don',
'dynamicprices' => 'DynamicPrices',
'ecm' => 'ECM',
'ecotax' => null, // TODO: External module ?
'emailcollector' => 'EmailCollector',
'eventorganization' => 'EventOrganization',
'expensereport' => 'ExpenseReport',
'export' => 'Export',
'externalrss' => 'ExternalRss',
'externalsite' => 'ExternalSite',
'fckeditor' => 'Fckeditor',
'fournisseur' => 'Fournisseur',
'ftp' => 'FTP',
'geoipmaxmind' => 'GeoIPMaxmind',
'google' => null, // External ?
'gravatar' => 'Gravatar',
'holiday' => 'Holiday',
'hrm' => 'HRM',
'import' => 'Import',
'incoterm' => 'Incoterm',
'intervention' => 'Ficheinter',
'intracommreport' => 'Intracommreport',
'invoice' => 'Facture',
'knowledgemanagement' => 'KnowledgeManagement',
'label' => 'Label',
'ldap' => 'Ldap',
'loan' => 'Loan',
'mailing' => 'Mailing',
'mailman' => null, // Same module as mailmanspip -> MailmanSpip ??
'mailmanspip' => 'MailmanSpip',
'margin' => 'Margin',
'member' => 'Adherent',
'memcached' => null, // TODO: External module?
'modulebuilder' => 'ModuleBuilder',
'mrp' => 'Mrp',
'multicompany' => null, // Not provided by default, no module tests
'multicurrency' => 'MultiCurrency',
'mymodule' => null, // modMyModule - Name used in module builder (avoid false positives)
'notification' => 'Notification',
'numberwords' => null, // Not provided by default, no module tests
'oauth' => 'OAuth',
'openstreetmap' => null, // External module?
'opensurvey' => 'OpenSurvey',
'order' => 'Commande',
'partnership' => 'Partnership',
'paybox' => 'Paybox',
'paymentbybanktransfer' => 'PaymentByBankTransfer',
'paypal' => 'Paypal',
'paypalplus' => null,
'prelevement' => 'Prelevement',
'printing' => 'Printing',
'product' => 'Product',
'productbatch' => 'ProductBatch',
'productprice' => null,
'productsupplierprice' => null,
'project' => 'Projet',
'propal' => 'Propale',
'receiptprinter' => 'ReceiptPrinter',
'reception' => 'Reception',
'recruitment' => 'Recruitment',
'resource' => 'Resource',
'salaries' => 'Salaries',
'service' => 'Service',
'socialnetworks' => 'SocialNetworks',
'societe' => 'Societe',
'stock' => 'Stock',
'stocktransfer' => 'StockTransfer',
'stripe' => 'Stripe',
'supplier_invoice' => null, // Special case, uses invoice
'supplier_order' => null, // Special case, uses invoice
'supplier_proposal' => 'SupplierProposal',
'syslog' => 'Syslog',
'takepos' => 'TakePos',
'tax' => 'Tax',
'theme_datacolor' => 'array{0:array{0:int,1:int,2:int},1:array{0:int,1:int,2:int},2:array{0:int,1:int,2:int},3:array{0:int,1:int,2:int}}',
'ticket' => 'Ticket',
'user' => 'User',
'variants' => 'Variants',
'webhook' => 'Webhook',
'webportal' => 'WebPortal',
'webservices' => 'WebServices',
'webservicesclient' => 'WebServicesClient',
'website' => 'Website',
'workflow' => 'Workflow',
'workstation' => 'Workstation',
'zapier' => 'Zapier',
);
// From ExtraFields class
$EXTRAFIELDS_TYPE2LABEL = array(
'varchar' => 'String1Line',
'text' => 'TextLongNLines',
'html' => 'HtmlText',
'int' => 'Int',
'double' => 'Float',
'date' => 'Date',
'datetime' => 'DateAndTime',
//'datetimegmt'=>'DateAndTimeUTC',
'boolean' => 'Boolean', // Remove as test
'price' => 'ExtrafieldPrice',
'pricecy' => 'ExtrafieldPriceWithCurrency',
'phone' => 'ExtrafieldPhone',
'mail' => 'ExtrafieldMail',
'url' => 'ExtrafieldUrl',
'ip' => 'ExtrafieldIP',
'icon' => 'Icon',
'password' => 'ExtrafieldPassword',
'select' => 'ExtrafieldSelect',
'sellist' => 'ExtrafieldSelectList',
'radio' => 'ExtrafieldRadio',
'checkbox' => 'ExtrafieldCheckBox',
'chkbxlst' => 'ExtrafieldCheckBoxFromList',
'link' => 'ExtrafieldLink',
'separate' => 'ExtrafieldSeparator',
);
$moduleNameRegex = '/^(?:'.implode('|', array_merge(array_keys($DEPRECATED_MODULE_MAPPING), array_keys($VALID_MODULE_MAPPING), array('\$modulename'))).')$/';
$deprecatedModuleNameRegex = '/^(?!(?:'.implode('|', array_keys($DEPRECATED_MODULE_MAPPING)).')$).*/';
$extraFieldTypeRegex = '/^(?:'.implode('|', array_keys($EXTRAFIELDS_TYPE2LABEL)).')$/';
/**
* This configuration will be read and overlaid on top of the
* default configuration. Command line arguments will be applied
* after this file is read.
*/
return [
// 'processes' => 6,
'backward_compatibility_checks' => false,
'simplify_ast' => true,
'analyzed_file_extensions' => ['php','inc'],
'globals_type_map' => [
'_Avery_Labels' => 'array<string,array{name:string,paper-size:string|array{0:float,1:float},orientation:string,metric:string,marginLeft:float,marginTop:float,NX:int,NY:int,SpaceX:float,SpaceY:float,width:float,height:float,font-size:float,custom_x:float,custom_y:float}>',
'action' => 'string',
'actioncode' => 'string',
'badgeStatus0' => 'string',
'badgeStatus1' => 'string',
'badgeStatus11' => 'string',
'badgeStatus3' => 'string',
'badgeStatus4' => 'string',
'badgeStatus6' => 'string',
'badgeStatus8' => 'string',
'badgeStatus9' => 'string',
'classname' => 'string',
'conf' => '\Conf',
'conffile' => 'string',
'conffiletoshow' => 'string',
'conffiletoshowshort' => 'string',
'dateSelector' => 'int<0,1>',
'db' => '\DoliDB',
'disableedit' => 'int<0,1>',
'disablemove' => 'int<0,1>',
'disableremove' => 'int<0,1>',
'dolibarr_main_authentication' => 'string',
'dolibarr_main_data_root' => 'string',
'dolibarr_main_data_root' => 'string',
'dolibarr_main_db_encrypted_pass' => 'string',
'dolibarr_main_db_host' => 'string',
'dolibarr_main_db_pass' => 'string',
'dolibarr_main_demo' => 'string',
'dolibarr_main_document_root' => 'string',
'dolibarr_main_url_root' => 'string',
'errormsg' => 'string',
'extrafields' => '\ExtraFields',
'filter' => 'string',
'filtert' => 'int',
'forceall' => 'int<0,1>',
'form' => '\Form',
'formcompany' => '\FormCompany',
'hookmanager' => '\HookManager',
'inputalsopricewithtax' => 'int<0,1>',
'langs' => '\Translate',
'leftmenu' => 'string',
'linkedObjectBlock' => '\CommonObject[]', // See htdocs/core/class/html.form.class.php
'mainmenu' => 'string',
'menumanager' => '\MenuManager',
'mysoc' => '\Societe',
'nblines' => '\int',
'objectoffield' => '\CommonObject',
'objsoc' => '\Societe',
'senderissupplier' => 'int<0,2>',
'shmkeys' => 'array<string,int>', // memory.lib
'shmoffset' => 'int', // memory.lib
'user' => '\User',
'website' => 'string', // See discussion https://github.com/Dolibarr/dolibarr/pull/28891#issuecomment-2002268334 // Disable because Phan infers Website type
'websitepage' => '\WebSitePage',
'websitepagefile' => 'string',
// 'object' => '\CommonObject', // Deprecated, not enabled because conflicts with $object assignments
],
// Supported values: `'5.6'`, `'7.0'`, `'7.1'`, `'7.2'`, `'7.3'`, `'7.4'`, `null`.
// If this is set to `null`,
// then Phan assumes the PHP version which is closest to the minor version
// of the php executable used to execute Phan.
//"target_php_version" => null,
"target_php_version" => '8.2',
//"target_php_version" => '7.3',
//"target_php_version" => '5.6',
// A list of directories that should be parsed for class and
// method information. After excluding the directories
// defined in exclude_analysis_directory_list, the remaining
// files will be statically analyzed for errors.
//
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
'htdocs',
PHAN_DIR . '/stubs/',
],
// A directory list that defines files that will be excluded
// from static analysis, but whose class and method
// information should be included.
//
// Generally, you'll want to include the directories for
// third-party code (such as "vendor/") in this list.
//
// n.b.: If you'd like to parse but not analyze 3rd
// party code, directories containing that code
// should be added to the `directory_list` as
// to `exclude_analysis_directory_list`.
"exclude_analysis_directory_list" => [
'htdocs/includes/',
'htdocs/install/doctemplates/websites/',
'htdocs/core/class/lessc.class.php', // External library
PHAN_DIR . '/stubs/',
],
//'exclude_file_regex' => '@^vendor/.*/(tests?|Tests?)/@',
'exclude_file_regex' => '@^(' // @phpstan-ignore-line
.'dummy' // @phpstan-ignore-line
// mymodule seen in cti, but not in git.
.'|htdocs/custom/.*' // Ignore all custom modules @phpstan-ignore-line
.'|htdocs/.*/canvas/.*/tpl/.*.tpl.php' // @phpstan-ignore-line
.'|htdocs/admin/tools/ui/.*' // @phpstan-ignore-line
//.'|htdocs/modulebuilder/template/.*' // @phpstan-ignore-line
// Included as stub (better analysis)
.'|htdocs/includes/nusoap/.*' // @phpstan-ignore-line
// Included as stub (old version + incompatible typing hints)
.'|htdocs/includes/restler/.*' // @phpstan-ignore-line
// Included as stub (did not seem properly analyzed by phan without it)
.'|htdocs/includes/stripe/.*' // @phpstan-ignore-line
.'|htdocs/conf/conf.php' // @phpstan-ignore-line
// .'|htdocs/[^h].*/.*' // For testing @phpstan-ignore-line
.')@', // @phpstan-ignore-line
// A list of plugin files to execute.
// Plugins which are bundled with Phan can be added here by providing their name
// (e.g. 'AlwaysReturnPlugin')
//
// Documentation about available bundled plugins can be found
// at https://github.com/phan/phan/tree/master/.phan/plugins
//
// Alternately, you can pass in the full path to a PHP file
// with the plugin's implementation (e.g. 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php')
'ParamMatchRegexPlugin' => [
'/^GETPOST$/' => [1, $sanitizeRegex, 'GetPostUnknownSanitizeType'],
'/^isModEnabled$/' => [0, $moduleNameRegex, 'UnknownModuleName'],
// Note: trick to have different key for same regex:
'/^isModEnable[d]$/' => [0, $deprecatedModuleNameRegex, "DeprecatedModuleName"],
'/^sanitizeVal$/' => [1, $sanitizeRegex,"UnknownSanitizeType"],
'/^checkVal$/' => [1, $sanitizeRegex,"UnknownCheckValSanitizeType"],
'/^\\\\ExtraFields::addExtraField$/' => [2, $extraFieldTypeRegex,"UnknownExtrafieldTypeBack"],
'/^dol_now$/' => [0, '{^(?:auto|gmt|tz(?:server|ref|user(?:rel)?))$}',"InvalidDolNowArgument"],
'/^dol_mktime$/' => [6, '{^(?:|0|1|auto|gmt|tz(?:server|ref|user(?:rel)?|,[+a-zA-Z-/]+))$}',"InvalidDolMktimeArgument"], // '', 0, 1 match bool and int values
'/^dol_print_date$/' => [2, '{^(?:|0|1|auto|gmt|tz(?:server|user(?:rel)?))$}',"InvalidDolMktimeArgument"], // '', 0, 1 match bool and int values
'/^GETPOSTFLOAT$/' => [1, '{^(?:|M[UTS]|C[UT]|\d+)$}',"InvalidGetPostFloatRounding"],
'/^price2num$/' => [1, '{^(?:|M[UTS]|C[UT]|\d+)$}',"InvalidPrice2NumRounding"],
],
'plugins' => [
__DIR__.'/plugins/NoVarDumpPlugin.php',
__DIR__.'/plugins/ParamMatchRegexPlugin.php',
// checks if a function, closure or method unconditionally returns.
// can also be written as 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'
'DeprecateAliasPlugin',
//'EmptyMethodAndFunctionPlugin',
'InvalidVariableIssetPlugin',
//'MoreSpecificElementTypePlugin',
'NoAssertPlugin',
'NotFullyQualifiedUsagePlugin',
//'PHPDocRedundantPlugin',
'PHPUnitNotDeadCodePlugin',
//'PossiblyStaticMethodPlugin',
'PreferNamespaceUsePlugin',
'PrintfCheckerPlugin',
'RedundantAssignmentPlugin',
'ConstantVariablePlugin', // Warns about values that are actually constant
//'HasPHPDocPlugin', // Requires PHPDoc
// 'InlineHTMLPlugin', // html in PHP file, or at end of file
//'NonBoolBranchPlugin', // Requires test on bool, nont on ints
//'NonBoolInLogicalArithPlugin',
'NumericalComparisonPlugin',
//'PHPDocToRealTypesPlugin',
'PHPDocInWrongCommentPlugin', // Missing /** (/* was used)
//'ShortArrayPlugin', // Checks that [] is used
//'StrictLiteralComparisonPlugin',
'UnknownClassElementAccessPlugin',
'UnknownElementTypePlugin',
'WhitespacePlugin',
//'RemoveDebugStatementPlugin', // Reports echo, print, ...
'SimplifyExpressionPlugin',
//'StrictComparisonPlugin', // Expects ===
'SuspiciousParamOrderPlugin',
'UnsafeCodePlugin',
//'UnusedSuppressionPlugin',
'AlwaysReturnPlugin',
//'DollarDollarPlugin',
'DuplicateArrayKeyPlugin',
'DuplicateExpressionPlugin',
'PregRegexCheckerPlugin',
'PrintfCheckerPlugin',
'SleepCheckerPlugin',
// Checks for syntactically unreachable statements in
// the global scope or function bodies.
'UnreachableCodePlugin',
'UseReturnValuePlugin',
'EmptyStatementListPlugin',
'LoopVariableReusePlugin',
],
// Add any issue types (such as 'PhanUndeclaredMethod')
// here to inhibit them from being reported
'suppress_issue_types' => [
// Dolibarr uses a lot of internal deprecated stuff, not reporting
'PhanDeprecatedProperty',
'PhanCompatibleNegativeStringOffset', // return false positive
'PhanPluginConstantVariableBool', // a lot of false positive, in most cases, we want to keep the code as it is
// 'PhanPluginUnknownArrayPropertyType', // Helps find missing array keys or mismatches, remaining occurrences are likely unused properties
'PhanTypeArraySuspiciousNullable', // About 440 occurrences
// 'PhanTypeInvalidDimOffset', // Helps identify missing array indexes in types or reference to unset indexes
'PhanTypeObjectUnsetDeclaredProperty',
'PhanTypePossiblyInvalidDimOffset', // a lot of false positive, in most cases, we want to keep the code as it is
// 'PhanPluginUnknownArrayFunctionReturnType', // a lot of false positive, in most cases, we want to keep the code as it is
'PhanPluginWhitespaceTab', // Dolibarr uses tabs
'PhanPluginCanUsePHP71Void', // Dolibarr is maintaining 7.0 compatibility
'PhanPluginShortArray', // Dolibarr uses array()
'PhanPluginShortArrayList', // Dolibarr uses array()
// Fixers From PHPDocToRealTypesPlugin:
'PhanPluginCanUseParamType', // Fixer - Report/Add types in the function definition (function abc(string $var) (adds string)
'PhanPluginCanUseReturnType', // Fixer - Report/Add return types in the function definition (function abc(string $var) (adds string)
'PhanPluginCanUseNullableParamType', // Fixer - Report/Add nullable parameter types in the function definition
'PhanPluginCanUseNullableReturnType', // Fixer - Report/Add nullable return types in the function definition
'PhanPluginNonBoolBranch', // Not essential - 31240+ occurrences
'PhanPluginNumericalComparison', // Not essential - 19870+ occurrences
// 'PhanTypeMismatchArgument', // Can detect missing array keys, invalid types, objects being passed when scalar expected - Not all reported by phpstan - <=3800 cases (was: 12300+ before)
'PhanPluginNonBoolInLogicalArith', // Not essential - 11040+ occurrences
'PhanPluginConstantVariableScalar', // Not essential - 5180+ occurrences
'PhanPluginDuplicateAdjacentStatement',
'PhanPluginDuplicateConditionalTernaryDuplication', // 2750+ occurrences
'PhanPluginDuplicateConditionalNullCoalescing', // Not essential - 990+ occurrences
'PhanPluginRedundantAssignmentInGlobalScope', // Not essential, a lot of false warning
'PhanPluginRedundantAssignment', // Not essential, useless
'PhanPluginDuplicateCatchStatementBody', // Requires PHP7.1 - 50+ occurrences
// 'PhanPluginUnknownArrayMethodParamType', // All fixed, except in api_*
// 'PhanPluginUnknownArrayMethodReturnType', // All fixed, except in api_*
// 'PhanUndeclaredGlobalVariable', // Helps identify variables that are not set/defined - add '@phan-var-force TYPE $varname' in tpl or includes to help type the variable
// 'PhanPluginUnknownObjectMethodCall', // False positive for some class. Is enabled in config_extended only.
'PhanTypeSuspiciousNonTraversableForeach', // Reports on `foreach ($object as $key => $value)` which works without php notices, so we ignore it because this is intentional in the code.
],
// You can put relative paths to internal stubs in this config option.
// Phan will continue using its detailed type annotations,
// but load the constants, classes, functions, and classes (and their Reflection types)
// from these stub files (doubling as valid php files).
// Use a different extension from php (and preferably a separate folder)
// to avoid accidentally parsing these as PHP (includes projects depending on this).
// The 'mkstubs' script can be used to generate your own stubs (compatible with php 7.0+ right now)
// Note: The array key must be the same as the extension name reported by `php -m`,
// so that phan can skip loading the stubs if the extension is actually available.
'autoload_internal_extension_signatures' => [
// Stubs may be available at https://github.com/JetBrains/phpstorm-stubs/tree/master
// Xdebug stubs are bundled with Phan 0.10.1+/0.8.9+ for usage,
// because Phan disables xdebug by default.
//'xdebug' => 'vendor/phan/phan/.phan/internal_stubs/xdebug.phan_php',
//'memcached' => PHAN_DIR . '/your_internal_stubs_folder_name/memcached.phan_php',
//'PDO' => PHAN_DIR . '/stubs/PDO.phan_php',
'brotli' => PHAN_DIR . '/stubs/brotli.phan_php',
'curl' => PHAN_DIR . '/stubs/curl.phan_php',
'calendar' => PHAN_DIR . '/stubs/calendar.phan_php',
'fileinfo' => PHAN_DIR . '/stubs/fileinfo.phan_php',
'ftp' => PHAN_DIR . '/stubs/ftp.phan_php',
'gd' => PHAN_DIR . '/stubs/gd.phan_php',
'geoip' => PHAN_DIR . '/stubs/geoip.phan_php',
'imagick' => PHAN_DIR . '/stubs/imagick.phan_php',
'imap' => PHAN_DIR . '/stubs/imap.phan_php',
'intl' => PHAN_DIR . '/stubs/intl.phan_php',
'ldap' => PHAN_DIR . '/stubs/ldap.phan_php',
'mcrypt' => PHAN_DIR . '/stubs/mcrypt.phan_php',
'memcache' => PHAN_DIR . '/stubs/memcache.phan_php',
'memcached' => PHAN_DIR . '/stubs/memcached.phan_php',
'mysqli' => PHAN_DIR . '/stubs/mysqli.phan_php',
'pdo_cubrid' => PHAN_DIR . '/stubs/pdo_cubrid.phan_php',
'pdo_mysql' => PHAN_DIR . '/stubs/pdo_mysql.phan_php',
'pdo_pgsql' => PHAN_DIR . '/stubs/pdo_pgsql.phan_php',
'pdo_sqlite' => PHAN_DIR . '/stubs/pdo_sqlite.phan_php',
'pgsql' => PHAN_DIR . '/stubs/pgsql.phan_php',
'session' => PHAN_DIR . '/stubs/session.phan_php',
'simplexml' => PHAN_DIR . '/stubs/SimpleXML.phan_php',
'soap' => PHAN_DIR . '/stubs/soap.phan_php',
'sockets' => PHAN_DIR . '/stubs/sockets.phan_php',
'tidy' => PHAN_DIR . '/stubs/tidy.phan_php',
'zip' => PHAN_DIR . '/stubs/zip.phan_php',
],
];