Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/5.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Nov 23, 2024
2 parents 03ee02c + bfbd53c commit 95631f5
Show file tree
Hide file tree
Showing 126 changed files with 3,118 additions and 331 deletions.
1 change: 1 addition & 0 deletions config.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@
<xs:element name="MismatchingDocblockParamType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MismatchingDocblockPropertyType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MismatchingDocblockReturnType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MissingClassConstType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MissingClosureParamType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MissingClosureReturnType" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MissingConstructor" type="IssueHandlerType" minOccurs="0" />
Expand Down
78 changes: 39 additions & 39 deletions dictionaries/CallMap.php

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions dictionaries/CallMap_73_delta.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@
'old' => ['bool', 'directory'=>'string', 'permissions='=>'int', 'recursive='=>'bool', 'context='=>'resource'],
'new' => ['bool', 'directory'=>'string', 'permissions='=>'int', 'recursive='=>'bool', 'context='=>'null|resource'],
],
'session_get_cookie_params' => [
'old' => ['array{lifetime:?int,path:?string,domain:?string,secure:?bool,httponly:?bool}'],
'new' => ['array{lifetime:?int,path:?string,domain:?string,secure:?bool,httponly:?bool,samesite:?string}'],
]
],
'removed' => [
],
Expand Down
92 changes: 92 additions & 0 deletions dictionaries/CallMap_81_delta.php
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,30 @@
'old' => ['bool', 'statement' => 'mysqli_stmt'],
'new' => ['bool', 'statement' => 'mysqli_stmt', 'params=' => 'list<mixed>|null'],
],
'mysqli_fetch_field' => [
'old' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'result'=>'mysqli_result'],
'new' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:0,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'result'=>'mysqli_result'],
],
'mysqli_fetch_field_direct' => [
'old' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'result'=>'mysqli_result', 'index'=>'int'],
'new' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:0,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'result'=>'mysqli_result', 'index'=>'int'],
],
'mysqli_fetch_fields' => [
'old' => ['list<object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}>', 'result'=>'mysqli_result'],
'new' => ['list<object{name:string,orgname:string,table:string,orgtable:string,max_length:0,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}>', 'result'=>'mysqli_result'],
],
'mysqli_result::fetch_field' => [
'old' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false'],
'new' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:0,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false'],
],
'mysqli_result::fetch_field_direct' => [
'old' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'index'=>'int'],
'new' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:0,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'index'=>'int'],
],
'mysqli_result::fetch_fields' => [
'old' => ['list<object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}>'],
'new' => ['list<object{name:string,orgname:string,table:string,orgtable:string,max_length:0,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}>'],
],
'mysqli_stmt_execute' => [
'old' => ['bool', 'statement' => 'mysqli_stmt'],
'new' => ['bool', 'statement' => 'mysqli_stmt', 'params=' => 'list<mixed>|null'],
Expand Down Expand Up @@ -1211,6 +1235,74 @@
'old' => ['int|false', '&rw_read'=>'?resource[]', '&rw_write'=>'?resource[]', '&rw_except'=>'?resource[]', 'seconds'=>'?int', 'microseconds='=>'int'],
'new' => ['int|false', '&rw_read'=>'?resource[]', '&rw_write'=>'?resource[]', '&rw_except'=>'?resource[]', 'seconds'=>'?int', 'microseconds='=>'?int'],
],
'mb_check_encoding' => [
'old' => ['bool', 'value='=>'array|string|null', 'encoding='=>'string|null'],
'new' => ['bool', 'value'=>'array|string', 'encoding='=>'string|null'],
],
'ctype_alnum' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_alpha' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_cntrl' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_digit' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_graph' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_lower' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_print' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_punct' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_space' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_upper' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'ctype_xdigit' => [
'old' => ['bool', 'text'=>'string|int'],
'new' => ['bool', 'text'=>'string'],
],
'key' => [
'old' => ['int|string|null', 'array'=>'array|object'],
'new' => ['int|string|null', 'array'=>'array'],
],
'current' => [
'old' => ['mixed|false', 'array'=>'array|object'],
'new' => ['mixed|false', 'array'=>'array'],
],
'next' => [
'old' => ['mixed', '&r_array'=>'array|object'],
'new' => ['mixed', '&r_array'=>'array'],
],
'prev' => [
'old' => ['mixed', '&r_array'=>'array|object'],
'new' => ['mixed', '&r_array'=>'array'],
],
'reset' => [
'old' => ['mixed|false', '&r_array'=>'array|object'],
'new' => ['mixed|false', '&r_array'=>'array'],
],
],

'removed' => [
Expand Down
24 changes: 24 additions & 0 deletions dictionaries/CallMap_82_delta.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,30 @@
'old' => ['array|string|int|false', 'type='=>'string'],
'new' => ['array|string|int|false|null', 'type='=>'string'],
],
'strcmp' => [
'old' => ['int', 'string1' => 'string', 'string2' => 'string'],
'new' => ['int<-1,1>', 'string1' => 'string', 'string2' => 'string'],
],
'strcasecmp' => [
'old' => ['int', 'string1' => 'string', 'string2' => 'string'],
'new' => ['int<-1,1>', 'string1' => 'string', 'string2' => 'string'],
],
'strnatcasecmp' => [
'old' => ['int', 'string1' => 'string', 'string2' => 'string'],
'new' => ['int<-1,1>', 'string1' => 'string', 'string2' => 'string'],
],
'strnatcmp' => [
'old' => ['int', 'string1' => 'string', 'string2' => 'string'],
'new' => ['int<-1,1>', 'string1' => 'string', 'string2' => 'string'],
],
'strncmp' => [
'old' => ['int', 'string1'=>'string', 'string2'=>'string', 'length'=>'int'],
'new' => ['int<-1,1>', 'string1' => 'string', 'string2' => 'string', 'length'=>'positive-int|0'],
],
'strncasecmp' => [
'old' => ['int', 'string1'=>'string', 'string2'=>'string', 'length'=>'int'],
'new' => ['int<-1,1>', 'string1' => 'string', 'string2' => 'string', 'length'=>'positive-int|0'],
],
],

'removed' => [
Expand Down
8 changes: 8 additions & 0 deletions dictionaries/CallMap_83_delta.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@
'old' => ['string|false', 'haystack'=>'string', 'needle'=>'string'],
'new' => ['string|false', 'haystack'=>'string', 'needle'=>'string', 'before_needle='=>'bool'],
],
'get_class' => [
'old' => ['class-string', 'object='=>'object'],
'new' => ['class-string', 'object'=>'object'],
],
'get_parent_class' => [
'old' => ['class-string|false', 'object_or_class='=>'object|class-string'],
'new' => ['class-string|false', 'object_or_class'=>'object|class-string'],
],
],

'removed' => [
Expand Down
28 changes: 14 additions & 14 deletions dictionaries/CallMap_historical.php
Original file line number Diff line number Diff line change
Expand Up @@ -3393,7 +3393,7 @@
'LimitIterator::seek' => ['int', 'offset'=>'int'],
'LimitIterator::valid' => ['bool'],
'Locale::acceptFromHttp' => ['string|false', 'header'=>'string'],
'Locale::canonicalize' => ['string', 'locale'=>'string'],
'Locale::canonicalize' => ['?string', 'locale'=>'string'],
'Locale::composeLocale' => ['string', 'subtags'=>'array'],
'Locale::filterMatches' => ['?bool', 'languageTag'=>'string', 'locale'=>'string', 'canonicalize='=>'bool'],
'Locale::getAllVariants' => ['array', 'locale'=>'string'],
Expand Down Expand Up @@ -5968,7 +5968,7 @@
'ReflectionParameter::getDeclaringFunction' => ['ReflectionFunctionAbstract'],
'ReflectionParameter::getDefaultValue' => ['mixed'],
'ReflectionParameter::getDefaultValueConstantName' => ['?string'],
'ReflectionParameter::getName' => ['string'],
'ReflectionParameter::getName' => ['non-empty-string'],
'ReflectionParameter::getPosition' => ['int<0, max>'],
'ReflectionParameter::getType' => ['?ReflectionType'],
'ReflectionParameter::hasType' => ['bool'],
Expand Down Expand Up @@ -10671,7 +10671,7 @@
'getimagesize' => ['array{0:int, 1: int, 2: int, 3: string, mime: string, channels?: 3|4, bits?: int}|false', 'filename'=>'string', '&w_image_info='=>'array'],
'getimagesizefromstring' => ['array{0:int, 1: int, 2: int, 3: string, mime: string, channels?: 3|4, bits?: int}|false', 'string'=>'string', '&w_image_info='=>'array'],
'getlastmod' => ['int|false'],
'getmxrr' => ['bool', 'hostname'=>'string', '&w_hosts'=>'array', '&w_weights='=>'array'],
'getmxrr' => ['bool', 'hostname'=>'string', '&w_hosts'=>'array<int, string>', '&w_weights='=>'array<int, int>'],
'getmygid' => ['int|false'],
'getmyinode' => ['int|false'],
'getmypid' => ['int|false'],
Expand Down Expand Up @@ -12728,9 +12728,9 @@
'mysqli_fetch_array\'1' => ['array<string,null|int|float|string>|false|null', 'result'=>'mysqli_result', 'mode='=>'1'],
'mysqli_fetch_array\'2' => ['list<null|int|float|string>|false|null', 'result'=>'mysqli_result', 'mode='=>'2'],
'mysqli_fetch_assoc' => ['array<string,null|int|float|string>|false|null', 'result'=>'mysqli_result'],
'mysqli_fetch_field' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result'],
'mysqli_fetch_field_direct' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result', 'index'=>'int'],
'mysqli_fetch_fields' => ['list<object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}>', 'result'=>'mysqli_result'],
'mysqli_fetch_field' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'result'=>'mysqli_result'],
'mysqli_fetch_field_direct' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'result'=>'mysqli_result', 'index'=>'int'],
'mysqli_fetch_fields' => ['list<object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}>', 'result'=>'mysqli_result'],
'mysqli_fetch_lengths' => ['array|false', 'result'=>'mysqli_result'],
'mysqli_fetch_object' => ['object|false|null', 'result'=>'mysqli_result', 'class='=>'string', 'constructor_args='=>'array'],
'mysqli_fetch_row' => ['list<null|int|float|string>|false|null', 'result'=>'mysqli_result'],
Expand All @@ -12742,7 +12742,7 @@
'mysqli_get_charset' => ['?object', 'mysql'=>'mysqli'],
'mysqli_get_client_info' => ['string', 'mysql='=>'?mysqli'],
'mysqli_get_client_stats' => ['array'],
'mysqli_get_client_version' => ['int', 'link'=>'mysqli'],
'mysqli_get_client_version' => ['int'],
'mysqli_get_connection_stats' => ['array', 'mysql'=>'mysqli'],
'mysqli_get_host_info' => ['string', 'mysql'=>'mysqli'],
'mysqli_get_links_stats' => ['array'],
Expand Down Expand Up @@ -12783,9 +12783,9 @@
'mysqli_result::fetch_array\'1' => ['array<string,null|int|float|string>|false|null', 'mode='=>'1'],
'mysqli_result::fetch_array\'2' => ['list<null|int|float|string>|false|null', 'mode='=>'2'],
'mysqli_result::fetch_assoc' => ['array<string,null|int|float|string>|false|null'],
'mysqli_result::fetch_field' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false'],
'mysqli_result::fetch_field_direct' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'index'=>'int'],
'mysqli_result::fetch_fields' => ['list<object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}>'],
'mysqli_result::fetch_field' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false'],
'mysqli_result::fetch_field_direct' => ['object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}|false', 'index'=>'int'],
'mysqli_result::fetch_fields' => ['list<object{name:string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:\'\',catalog:\'def\'}>'],
'mysqli_result::fetch_object' => ['object|false|null', 'class='=>'string', 'constructor_args='=>'array'],
'mysqli_result::fetch_row' => ['list<null|int|float|string>|false|null'],
'mysqli_result::field_seek' => ['bool', 'index'=>'int'],
Expand Down Expand Up @@ -13499,9 +13499,9 @@
'preg_filter' => ['string|string[]|null', 'pattern'=>'string|string[]', 'replacement'=>'string|string[]', 'subject'=>'string|string[]', 'limit='=>'int', '&w_count='=>'int'],
'preg_grep' => ['array|false', 'pattern'=>'string', 'array'=>'array', 'flags='=>'int'],
'preg_last_error' => ['int'],
'preg_match' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'string[]', 'flags='=>'0', 'offset='=>'int'],
'preg_match\'1' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
'preg_match_all' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
'preg_match' => ['0|1|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'string[]', 'flags='=>'0', 'offset='=>'int'],
'preg_match\'1' => ['0|1|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
'preg_match_all' => ['int<0,max>|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
'preg_quote' => ['string', 'str'=>'string', 'delimiter='=>'string'],
'preg_replace' => ['string|string[]|null', 'pattern'=>'string|array', 'replacement'=>'string|array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'],
'preg_replace_callback' => ['string|null', 'pattern'=>'string|array', 'callback'=>'callable(string[]):string', 'subject'=>'string', 'limit='=>'int', '&w_count='=>'int'],
Expand Down Expand Up @@ -13840,7 +13840,7 @@
'session_decode' => ['bool', 'data'=>'string'],
'session_destroy' => ['bool'],
'session_encode' => ['string|false'],
'session_get_cookie_params' => ['array'],
'session_get_cookie_params' => ['array{lifetime:?int,path:?string,domain:?string,secure:?bool,httponly:?bool}'],
'session_id' => ['string|false', 'id='=>'string'],
'session_is_registered' => ['bool', 'name'=>'string'],
'session_module_name' => ['string|false', 'module='=>'string'],
Expand Down
5 changes: 5 additions & 0 deletions dictionaries/ImpureFunctionsList.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,9 @@
'openssl_pkcs12_export_to_file' => true,
'openssl_pkey_export_to_file' => true,
'openssl_x509_export_to_file' => true,
// xml
'xml_parser_set_option' => true,
'xml_parser_free' => true,
// mail
'mail' => true,
];
40 changes: 35 additions & 5 deletions docs/annotating_code/supported_annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,10 @@ $b = $a->bar(); // this call fails

### `@psalm-internal`

Used to mark a class, property or function as internal to a given namespace. Psalm treats this slightly differently to
the PHPDoc `@internal` tag. For `@internal`, an issue is raised if the calling code is in a namespace completely
unrelated to the namespace of the calling code, i.e. not sharing the first element of the namespace.
Used to mark a class, property or function as internal to a given namespace or class or even method.
Psalm treats this slightly differently to the PHPDoc `@internal` tag. For `@internal`,
an issue is raised if the calling code is in a namespace completely unrelated to the namespace of the calling code,
i.e. not sharing the first element of the namespace.

In contrast for `@psalm-internal`, the docblock line must specify a namespace. An issue is raised if the calling code
is not within the given namespace.
Expand All @@ -272,15 +273,44 @@ namespace A\B {
namespace A\B\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // this is fine
$a = new \A\B\Foo(); // this is fine
}
}
}

namespace A {
class B {
public function batBat(): void {
$a = new \A\B\Foo(); // this is fine
}
}
}

namespace A\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // error
$a = new \A\B\Foo(); // error
}
}
}

namespace X {
class Foo {
/**
* @psalm-internal Y\Bat::batBat
*/
public static function barBar(): void {
}
}
}

namespace Y {
class Bat {
public function batBat() : void {
\X\Foo::barBar(); // this is fine
}
public function fooFoo(): void {
\X\Foo::barBar(); // error
}
}
}
Expand Down
Loading

0 comments on commit 95631f5

Please sign in to comment.