clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,260 @@
<?php
namespace VariableAnalysis\Lib;
class Constants
{
/**
* Array of known pass-by-reference functions and the argument(s) which are passed
* by reference, the arguments are numbered starting from 1 and an elipsis '...'
* means all argument numbers after the previous should be considered pass-by-reference.
*
* This does not need to cover all pass-by-reference arguments, only the
* ones which can be passed an undefined variable (eg: `$matches` in
* `preg_match`) and will define that variable.
*
* @return array<string, array<int|string>>
*/
public static function getPassByReferenceFunctions()
{
return [
'__soapCall' => [5],
'addFunction' => [3],
'addTask' => [3],
'addTaskBackground' => [3],
'addTaskHigh' => [3],
'addTaskHighBackground' => [3],
'addTaskLow' => [3],
'addTaskLowBackground' => [3],
'addTaskStatus' => [2],
'apc_dec' => [3],
'apc_fetch' => [2],
'apc_inc' => [3],
'apcu_dec' => [3],
'apcu_fetch' => [2],
'apcu_inc' => [3],
'areConfusable' => [3],
'arsort' => [1],
'asort' => [1],
'bindColumn' => [2],
'bindParam' => [2],
'bind_param' => [2, 3, '...'],
'bind_result' => [1, 2, '...'],
'call_user_method' => [2],
'call_user_method_array' => [2],
'curl_multi_exec' => [2],
'curl_multi_info_read' => [2],
'current' => [1],
'dbplus_curr' => [2],
'dbplus_first' => [2],
'dbplus_info' => [3],
'dbplus_last' => [2],
'dbplus_next' => [2],
'dbplus_prev' => [2],
'dbplus_tremove' => [3],
'dns_get_record' => [3, 4],
'domxml_open_file' => [3],
'domxml_open_mem' => [3],
'each' => [1],
'enchant_dict_quick_check' => [3],
'end' => [1],
'ereg' => [3],
'eregi' => [3],
'exec' => [2, 3],
'exif_thumbnail' => [1, 2, 3],
'expect_expectl' => [3],
'extract' => [1],
'filter' => [3],
'flock' => [2,3],
'fscanf' => [2, 3, '...'],
'fsockopen' => [3, 4],
'ftp_alloc' => [3],
'get' => [2, 3],
'getByKey' => [4],
'getMulti' => [2],
'getMultiByKey' => [3],
'getimagesize' => [2],
'getmxrr' => [2, 3],
'gnupg_decryptverify' => [3],
'gnupg_verify' => [4],
'grapheme_extract' => [5],
'headers_sent' => [1, 2],
'http_build_url' => [4],
'http_get' => [3],
'http_head' => [3],
'http_negotiate_charset' => [2],
'http_negotiate_content_type' => [2],
'http_negotiate_language' => [2],
'http_post_data' => [4],
'http_post_fields' => [5],
'http_put_data' => [4],
'http_put_file' => [4],
'http_put_stream' => [4],
'http_request' => [5],
'isSuspicious' => [2],
'is_callable' => [3],
'key' => [1],
'krsort' => [1],
'ksort' => [1],
'ldap_get_option' => [3],
'ldap_parse_reference' => [3],
'ldap_parse_result' => [3, 4, 5, 6],
'localtime' => [2],
'm_completeauthorizations' => [2],
'maxdb_stmt_bind_param' => [3, 4, '...'],
'maxdb_stmt_bind_result' => [2, 3, '...'],
'mb_convert_variables' => [3, 4, '...'],
'mb_parse_str' => [2],
'mqseries_back' => [2, 3],
'mqseries_begin' => [3, 4],
'mqseries_close' => [4, 5],
'mqseries_cmit' => [2, 3],
'mqseries_conn' => [2, 3, 4],
'mqseries_connx' => [2, 3, 4, 5],
'mqseries_disc' => [2, 3],
'mqseries_get' => [3, 4, 5, 6, 7, 8, 9],
'mqseries_inq' => [6, 8, 9, 10],
'mqseries_open' => [2, 4, 5, 6],
'mqseries_put' => [3, 4, 6, 7],
'mqseries_put1' => [2, 3, 4, 6, 7],
'mqseries_set' => [9, 10],
'msg_receive' => [3, 5, 8],
'msg_send' => [6],
'mssql_bind' => [3],
'natcasesort' => [1],
'natsort' => [1],
'ncurses_color_content' => [2, 3, 4],
'ncurses_getmaxyx' => [2, 3],
'ncurses_getmouse' => [1],
'ncurses_getyx' => [2, 3],
'ncurses_instr' => [1],
'ncurses_mouse_trafo' => [1, 2],
'ncurses_mousemask' => [2],
'ncurses_pair_content' => [2, 3],
'ncurses_wmouse_trafo' => [2, 3],
'newt_button_bar' => [1],
'newt_form_run' => [2],
'newt_get_screen_size' => [1, 2],
'newt_grid_get_size' => [2, 3],
'newt_reflow_text' => [5, 6],
'newt_win_entries' => [7],
'newt_win_menu' => [8],
'next' => [1],
'oci_bind_array_by_name' => [3],
'oci_bind_by_name' => [3],
'oci_define_by_name' => [3],
'oci_fetch_all' => [2],
'ocifetchinto' => [2],
'odbc_fetch_into' => [2],
'openssl_csr_export' => [2],
'openssl_csr_new' => [2],
'openssl_open' => [2],
'openssl_pkcs12_export' => [2],
'openssl_pkcs12_read' => [2],
'openssl_pkey_export' => [2],
'openssl_private_decrypt' => [2],
'openssl_private_encrypt' => [2],
'openssl_public_decrypt' => [2],
'openssl_public_encrypt' => [2],
'openssl_random_pseudo_bytes' => [2],
'openssl_seal' => [2, 3],
'openssl_sign' => [2],
'openssl_x509_export' => [2],
'ovrimos_fetch_into' => [2],
'parse' => [2,3],
'parseCurrency' => [2, 3],
'parse_str' => [2],
'parsekit_compile_file' => [2],
'parsekit_compile_string' => [2],
'passthru' => [2],
'pcntl_sigprocmask' => [3],
'pcntl_sigtimedwait' => [2],
'pcntl_sigwaitinfo' => [2],
'pcntl_wait' => [1],
'pcntl_waitpid' => [2],
'pfsockopen' => [3, 4],
'php_check_syntax' => [2],
'poll' => [1, 2, 3],
'preg_filter' => [5],
'preg_match' => [3],
'preg_match_all' => [3],
'preg_replace' => [5],
'preg_replace_callback' => [5],
'prev' => [1],
'proc_open' => [3],
'query' => [3],
'queryExec' => [2],
'reset' => [1],
'rsort' => [1],
'settype' => [1],
'shuffle' => [1],
'similar_text' => [3],
'socket_create_pair' => [4],
'socket_getpeername' => [2, 3],
'socket_getsockname' => [2, 3],
'socket_recv' => [2],
'socket_recvfrom' => [2, 5, 6],
'socket_select' => [1, 2, 3],
'sort' => [1],
'sortWithSortKeys' => [1],
'sqlite_exec' => [3],
'sqlite_factory' => [3],
'sqlite_open' => [3],
'sqlite_popen' => [3],
'sqlite_query' => [4],
'sqlite_unbuffered_query' => [4],
'sscanf' => [3, '...'],
'str_ireplace' => [4],
'str_replace' => [4],
'stream_open' => [4],
'stream_select' => [1, 2, 3],
'stream_socket_accept' => [3],
'stream_socket_client' => [2, 3],
'stream_socket_recvfrom' => [4],
'stream_socket_server' => [2, 3],
'system' => [2],
'uasort' => [1],
'uksort' => [1],
'unbufferedQuery' => [3],
'usort' => [1],
'wincache_ucache_dec' => [3],
'wincache_ucache_get' => [2],
'wincache_ucache_inc' => [3],
'xdiff_string_merge3' => [4],
'xdiff_string_patch' => [4],
'xml_parse_into_struct' => [3, 4],
'xml_set_object' => [2],
'xmlrpc_decode_request' => [2],
'xmlrpc_set_type' => [1],
'xslt_set_object' => [2],
'yaml_parse' => [3],
'yaml_parse_file' => [3],
'yaml_parse_url' => [3],
'yaz_ccl_parse' => [3],
'yaz_hits' => [2],
'yaz_scan_result' => [2],
'yaz_wait' => [1],
];
}
/**
* @return array<string, array<int>>
*/
public static function getWordPressPassByReferenceFunctions()
{
return [
'wp_parse_str' => [2],
'wp_cache_get' => [4],
];
}
/**
* A regexp for matching variable names in double-quoted strings.
*
* @return string
*/
public static function getDoubleQuotedVarRegexp()
{
return '|(?<!\\\\)(?:\\\\{2})*\${?([a-zA-Z0-9_]+)}?|';
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace VariableAnalysis\Lib;
/**
* Holds details of an enum.
*/
class EnumInfo
{
/**
* The position of the `enum` token.
*
* @var int
*/
public $enumIndex;
/**
* The position of the block opener (curly brace) for the enum.
*
* @var int
*/
public $blockStart;
/**
* The position of the block closer (curly brace) for the enum.
*
* @var int
*/
public $blockEnd;
/**
* @param int $enumIndex
* @param int $blockStart
* @param int $blockEnd
*/
public function __construct(
$enumIndex,
$blockStart,
$blockEnd
) {
$this->enumIndex = $enumIndex;
$this->blockStart = $blockStart;
$this->blockEnd = $blockEnd;
}
}

View File

@@ -0,0 +1,114 @@
<?php
namespace VariableAnalysis\Lib;
/**
* Holds details of a for loop.
*/
class ForLoopInfo
{
/**
* The position of the `for` token.
*
* @var int
*/
public $forIndex;
/**
* The position of the initialization expression opener for the loop.
*
* @var int
*/
public $initStart;
/**
* The position of the initialization expression closer for the loop.
*
* @var int
*/
public $initEnd;
/**
* The position of the condition expression opener for the loop.
*
* @var int
*/
public $conditionStart;
/**
* The position of the condition expression closer for the loop.
*
* @var int
*/
public $conditionEnd;
/**
* The position of the increment expression opener for the loop.
*
* @var int
*/
public $incrementStart;
/**
* The position of the increment expression closer for the loop.
*
* @var int
*/
public $incrementEnd;
/**
* The position of the block opener for the loop.
*
* @var int
*/
public $blockStart;
/**
* The position of the block closer for the loop.
*
* @var int
*/
public $blockEnd;
/**
* Any variables defined inside the third expression of the loop.
*
* The key is the variable index.
*
* @var array<int, \VariableAnalysis\Lib\VariableInfo>
*/
public $incrementVariables = [];
/**
* @param int $forIndex
* @param int $blockStart
* @param int $blockEnd
* @param int $initStart
* @param int $initEnd
* @param int $conditionStart
* @param int $conditionEnd
* @param int $incrementStart
* @param int $incrementEnd
*/
public function __construct(
$forIndex,
$blockStart,
$blockEnd,
$initStart,
$initEnd,
$conditionStart,
$conditionEnd,
$incrementStart,
$incrementEnd
) {
$this->forIndex = $forIndex;
$this->blockStart = $blockStart;
$this->blockEnd = $blockEnd;
$this->initStart = $initStart;
$this->initEnd = $initEnd;
$this->conditionStart = $conditionStart;
$this->conditionEnd = $conditionEnd;
$this->incrementStart = $incrementStart;
$this->incrementEnd = $incrementEnd;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
<?php
namespace VariableAnalysis\Lib;
/**
* Holds details of a scope.
*/
class ScopeInfo
{
/**
* The token index of the start of this scope.
*
* @var int
*/
public $scopeStartIndex;
/**
* The token index of the end of this scope, if important.
*
* @var int|null
*/
public $scopeEndIndex;
/**
* The variables defined in this scope.
*
* @var VariableInfo[]
*/
public $variables = [];
/**
* @param int $scopeStartIndex
* @param int|null $scopeEndIndex
*/
public function __construct($scopeStartIndex, $scopeEndIndex = null)
{
$this->scopeStartIndex = $scopeStartIndex;
$this->scopeEndIndex = $scopeEndIndex;
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace VariableAnalysis\Lib;
use VariableAnalysis\Lib\ScopeInfo;
use VariableAnalysis\Lib\Helpers;
use PHP_CodeSniffer\Files\File;
class ScopeManager
{
/**
* An associative array of a list of token index pairs which start and end
* scopes and will be used to check for unused variables.
*
* The outer array of scopes is keyed by a string containing the filename.
* The inner array of scopes in keyed by the scope start token index.
*
* @var array<string, array<int, ScopeInfo>>
*/
private $scopes = [];
/**
* Add a scope's start and end index to our record for the file.
*
* @param File $phpcsFile
* @param int $scopeStartIndex
*
* @return ScopeInfo
*/
public function recordScopeStartAndEnd(File $phpcsFile, $scopeStartIndex)
{
$scopeEndIndex = Helpers::getScopeCloseForScopeOpen($phpcsFile, $scopeStartIndex);
$filename = $phpcsFile->getFilename();
if (! isset($this->scopes[$filename])) {
$this->scopes[$filename] = [];
}
Helpers::debug('recording scope for file', $filename, 'start/end', $scopeStartIndex, $scopeEndIndex);
$scope = new ScopeInfo($scopeStartIndex, $scopeEndIndex);
$this->scopes[$filename][$scopeStartIndex] = $scope;
return $scope;
}
/**
* Return the scopes for a file.
*
* @param string $filename
*
* @return ScopeInfo[]
*/
public function getScopesForFilename($filename)
{
if (empty($this->scopes[$filename])) {
return [];
}
return array_values($this->scopes[$filename]);
}
/**
* Return the scope for a scope start index.
*
* @param string $filename
* @param int $scopeStartIndex
*
* @return ScopeInfo|null
*/
public function getScopeForScopeStart($filename, $scopeStartIndex)
{
if (empty($this->scopes[$filename][$scopeStartIndex])) {
return null;
}
return $this->scopes[$filename][$scopeStartIndex];
}
/**
* Find scopes closed by a scope close index.
*
* @param string $filename
* @param int $scopeEndIndex
*
* @return ScopeInfo[]
*/
public function getScopesForScopeEnd($filename, $scopeEndIndex)
{
$scopePairsForFile = $this->getScopesForFilename($filename);
$scopeIndicesThisCloses = array_reduce(
$scopePairsForFile,
/**
* @param ScopeInfo[] $found
* @param ScopeInfo $scope
*
* @return ScopeInfo[]
*/
function ($found, $scope) use ($scopeEndIndex) {
if (! is_int($scope->scopeEndIndex)) {
Helpers::debug('No scope closer found for scope start', $scope->scopeStartIndex);
return $found;
}
if ($scopeEndIndex === $scope->scopeEndIndex) {
$found[] = $scope;
}
return $found;
},
[]
);
return $scopeIndicesThisCloses;
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace VariableAnalysis\Lib;
class ScopeType
{
const PARAM = 'param';
const BOUND = 'bound';
const LOCAL = 'local';
const GLOBALSCOPE = 'global';
const STATICSCOPE = 'static';
}

View File

@@ -0,0 +1,109 @@
<?php
namespace VariableAnalysis\Lib;
use VariableAnalysis\Lib\ScopeType;
/**
* Holds details of a variable within a scope.
*/
class VariableInfo
{
/**
* @var string
*/
public $name;
/**
* What scope the variable has: local, param, static, global, bound
*
* @var ScopeType::PARAM|ScopeType::BOUND|ScopeType::LOCAL|ScopeType::GLOBALSCOPE|ScopeType::STATICSCOPE|null
*/
public $scopeType;
/**
* @var string|null
*/
public $typeHint;
/**
* @var int|null
*/
public $referencedVariableScope;
/**
* True if the variable is a reference but one created at runtime
*
* @var bool
*/
public $isDynamicReference = false;
/**
* Stack pointer of first declaration
*
* Declaration is when a variable is created but has no value assigned.
*
* Assignment by reference is also a declaration and not an initialization.
*
* @var int|null
*/
public $firstDeclared;
/**
* Stack pointer of first initialization
*
* @var int|null
*/
public $firstInitialized;
/**
* Stack pointer of first read
*
* @var int|null
*/
public $firstRead;
/**
* Stack pointers of all assignments
*
* This includes both declarations and initializations and may contain
* duplicates!
*
* @var int[]
*/
public $allAssignments = [];
/**
* @var bool
*/
public $ignoreUnused = false;
/**
* @var bool
*/
public $ignoreUndefined = false;
/**
* @var bool
*/
public $isForeachLoopAssociativeValue = false;
/**
* @var array<ScopeType::PARAM|ScopeType::BOUND|ScopeType::LOCAL|ScopeType::GLOBALSCOPE|ScopeType::STATICSCOPE, string>
*/
public static $scopeTypeDescriptions = [
ScopeType::LOCAL => 'variable',
ScopeType::PARAM => 'function parameter',
ScopeType::STATICSCOPE => 'static variable',
ScopeType::GLOBALSCOPE => 'global variable',
ScopeType::BOUND => 'bound variable',
];
/**
* @param string $varName
*/
public function __construct($varName)
{
$this->name = $varName;
}
}