[phpstorm-stubs] added new tests for parameters without default value.

This commit is contained in:
LolGleb 2023-09-13 15:23:56 +02:00 committed by Ivan Fedorov
parent fb1e679110
commit a0c77afb46
12 changed files with 160 additions and 60 deletions

View File

@ -622,7 +622,7 @@ class Phar extends RecursiveDirectoryIterator implements RecursiveIterator, Seek
*/
public function setStub(
$stub,
#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $length = null
#[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $length
) {}
/**

View File

@ -533,7 +533,7 @@ class ReflectionClass implements Reflector
*
* @link https://php.net/manual/en/reflectionclass.getstaticpropertyvalue.php
* @param string $name The name of the static property for which to return a value.
* @param mixed $default A default value to return in case the class does
* @param mixed $default [optional] A default value to return in case the class does
* not declare a static property with the given name. If the property does
* not exist and this argument is omitted, a {@see ReflectionException} is thrown.
* @return mixed The value of the static property.
@ -542,7 +542,7 @@ class ReflectionClass implements Reflector
#[TentativeType]
public function getStaticPropertyValue(
#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name,
#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $default = null
#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $default
): mixed {}
/**

View File

@ -130,13 +130,13 @@ class ReflectionProperty implements Reflector
* @param mixed $objectOrValue If the property is non-static an object must
* be provided to change the property on. If the property is static this
* parameter is left out and only $value needs to be provided.
* @param mixed $value The new value.
* @param mixed $value [optional] The new value.
* @return void No value is returned.
*/
#[TentativeType]
public function setValue(
#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $objectOrValue,
#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value = null
#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $value
): void {}
/**

View File

@ -5563,7 +5563,7 @@ function intlcal_before(IntlCalendar $calendar, IntlCalendar $other): bool {}
* @since 5.5
*/
#[LanguageAware(['8.3' => 'true'], default: 'bool')]
function intlcal_set(IntlCalendar $calendar, int $year, int $month, int $dayOfMonth = null, int $hour = null, int $minute = null, int $second = null) {}
function intlcal_set(IntlCalendar $calendar, int $year, int $month, int $dayOfMonth, int $hour, int $minute, int $second) {}
/**
* (PHP 5 &gt;=5.5.0 PECL intl &gt;= 3.0.0a1)<br/>
@ -6448,17 +6448,17 @@ function intltz_use_daylight_time(IntlTimeZone $timezone): bool {}
/**
* (PHP 5 &gt;=5.5.0 PECL intl &gt;= 3.0.0a1)<br/>
* @param DateTimeZone|IntlTimeZone|string|int|null $timezoneOrYear
* @param string|null $localeOrMonth
* @param int $day
* @param int $hour
* @param int $minute
* @param int $second
* @param DateTimeZone|IntlTimeZone|string|int|null $timezoneOrYear [optional]
* @param string|null $localeOrMonth [optional]
* @param int $day [optional]
* @param int $hour [optional]
* @param int $minute [optional]
* @param int $second [optional]
* @return IntlGregorianCalendar|null
* @since 5.5
*/
#[Pure]
function intlgregcal_create_instance($timezoneOrYear = null, $localeOrMonth = null, $day = null, $hour = null, $minute = null, $second = null): ?IntlGregorianCalendar {}
function intlgregcal_create_instance($timezoneOrYear, $localeOrMonth, $day, $hour, $minute, $second): ?IntlGregorianCalendar {}
/**
* @param IntlGregorianCalendar $calendar

View File

@ -267,7 +267,7 @@ function pg_ping(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], de
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $name <p>
* @param string $name [optional] <p>
* Possible <i>param_name</i> values include server_version,
* server_encoding, client_encoding,
* is_superuser, session_authorization,
@ -277,7 +277,7 @@ function pg_ping(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'], de
* @return string|false A string containing the value of the parameter, <b>FALSE</b> on failure or invalid
* <i>param_name</i>.
*/
function pg_parameter_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $name = null): string|false {}
function pg_parameter_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, string $name): string|false {}
/**
* Returns the current in-transaction status of the server.
@ -304,7 +304,7 @@ function pg_transaction_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connect
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $query <p>
* @param string $query [optional] <p>
* The SQL statement or statements to be executed. When multiple statements are passed to the function,
* they are automatically executed as one transaction, unless there are explicit BEGIN/COMMIT commands
* included in the query string. However, using multiple transactions in one function call is not recommended.
@ -327,7 +327,7 @@ function pg_transaction_status(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connect
function pg_query(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $query = null
string $query
) {}
/**
@ -352,7 +352,7 @@ function pg_query(
* If for some reason you cannot use a parameter, ensure that interpolated
* values are properly escaped.
* </p>
* @param array $params <p>
* @param array $params [optional] <p>
* An array of parameter values to substitute for the $1, $2, etc. placeholders
* in the original prepared query string. The number of elements in the array
* must match the number of placeholders.
@ -370,7 +370,7 @@ function pg_query_params(
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $query = '',
#[PhpStormStubsElementAvailable(from: '8.0')] $query,
array $params = null
array $params
) {}
/**
@ -388,7 +388,7 @@ function pg_query_params(
* "" is specified, then an unnamed statement is created, overwriting any
* previously defined unnamed statement.
* </p>
* @param string $query <p>
* @param string $query [optional] <p>
* The parameterized SQL statement. Must contain only a single statement.
* (multiple statements separated by semi-colons are not allowed.) If any parameters
* are used, they are referred to as $1, $2, etc.
@ -401,7 +401,7 @@ function pg_prepare(
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $statement_name = '',
#[PhpStormStubsElementAvailable(from: '8.0')] string $statement_name,
string $query = null
string $query
) {}
/**
@ -420,7 +420,7 @@ function pg_prepare(
* <b>pg_send_prepare</b> or a PREPARE SQL
* command.
* </p>
* @param array $params <p>
* @param array $params [optional] <p>
* An array of parameter values to substitute for the $1, $2, etc. placeholders
* in the original prepared query string. The number of elements in the array
* must match the number of placeholders.
@ -436,7 +436,7 @@ function pg_execute(
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] string $statement_name = '',
#[PhpStormStubsElementAvailable(from: '8.0')] $statement_name,
array $params = null
array $params
) {}
/**
@ -566,7 +566,7 @@ function pg_cancel_query(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'],
* Row number in result to fetch. Rows are numbered from 0 upwards. If omitted,
* next row is fetched.
* </p>
* @param mixed $field <p>
* @param mixed $field [optional] <p>
* A string representing the name of the field (column) to fetch, otherwise
* an int representing the field number to fetch. Fields are
* numbered from 0 upwards.
@ -585,7 +585,7 @@ function pg_fetch_result(
#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result,
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0,
#[PhpStormStubsElementAvailable(from: '8.0')] $row,
string|int $field = null
string|int $field
): string|false|null {}
/**
@ -951,14 +951,14 @@ function pg_field_type_oid(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], d
* (among others).
* </p>
* @param int $row
* @param mixed $field
* @param mixed $field [optional]
* @return int|false The field printed length, or <b>FALSE</b> on error.
*/
function pg_field_prtlen(
#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result,
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0,
#[PhpStormStubsElementAvailable(from: '8.0')] $row,
string|int $field = null
string|int $field
): int|false {}
/**
@ -973,7 +973,7 @@ function pg_field_prtlen(
* Row number in result to fetch. Rows are numbered from 0 upwards. If omitted,
* current row is fetched.
* </p>
* @param mixed $field <p>
* @param mixed $field [optional] <p>
* Field number (starting from 0) as an integer or
* the field name as a string.
* </p>
@ -984,7 +984,7 @@ function pg_field_is_null(
#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result,
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $row = 0,
#[PhpStormStubsElementAvailable(from: '8.0')] $row,
string|int $field = null
string|int $field
): int|false {}
/**
@ -1129,7 +1129,7 @@ function pg_last_notice(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'],
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $query <p>
* @param string $query [optional] <p>
* A line of text to be sent directly to the PostgreSQL backend. A NULL
* terminator is added automatically.
* </p>
@ -1138,7 +1138,7 @@ function pg_last_notice(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'],
function pg_put_line(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $query = null
string $query
): bool {}
/**
@ -1271,7 +1271,7 @@ function pg_untrace(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection|null'],
* </p>
* @return string|int|false A large object OID or <b>FALSE</b> on error.
*/
function pg_lo_create(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection = null, $oid = null): string|int|false {}
function pg_lo_create(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection, $oid): string|int|false {}
/**
* Delete a large object
@ -1282,7 +1282,7 @@ function pg_lo_create(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], de
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param int $oid <p>
* @param int $oid [optional] <p>
* The OID of the large object in the database.
* </p>
* @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure.
@ -1290,7 +1290,7 @@ function pg_lo_create(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], de
function pg_lo_unlink(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
$oid = null
$oid
): bool {}
/**
@ -1302,10 +1302,10 @@ function pg_lo_unlink(
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param int $oid <p>
* @param int $oid [optional] <p>
* The OID of the large object in the database.
* </p>
* @param string $mode <p>
* @param string $mode [optional] <p>
* Can be either "r" for read-only, "w" for write only or "rw" for read and
* write.
* </p>
@ -1315,8 +1315,8 @@ function pg_lo_unlink(
function pg_lo_open(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
$oid = null,
string $mode = null
$oid,
string $mode
) {}
/**
@ -1479,7 +1479,7 @@ function pg_lo_truncate(
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $string <p>
* @param string $string [optional] <p>
* A string containing text to be escaped.
* </p>
* @return string A string containing the escaped data.
@ -1487,7 +1487,7 @@ function pg_lo_truncate(
function pg_escape_string(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $string = null
string $string
): string {}
/**
@ -1499,7 +1499,7 @@ function pg_escape_string(
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $string <p>
* @param string $string [optional] <p>
* A string containing text or binary data to be inserted into a bytea
* column.
* </p>
@ -1508,7 +1508,7 @@ function pg_escape_string(
function pg_escape_bytea(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $string = null
string $string
): string {}
/**
@ -1520,7 +1520,7 @@ function pg_escape_bytea(
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $string <p>
* @param string $string [optional] <p>
* A string containing text to be escaped.
* </p>
* @return string|false A string containing the escaped data.
@ -1529,7 +1529,7 @@ function pg_escape_bytea(
function pg_escape_identifier(
#[PhpStormStubsElementAvailable(from: '5.4', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $string = null
string $string
): string|false {}
/**
@ -1541,7 +1541,7 @@ function pg_escape_identifier(
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $string <p>
* @param string $string [optional] <p>
* A string containing text to be escaped.
* </p>
* @return string|false A string containing the escaped data.
@ -1550,7 +1550,7 @@ function pg_escape_identifier(
function pg_escape_literal(
#[PhpStormStubsElementAvailable(from: '5.4', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $string = null
string $string
): string|false {}
/**
@ -1574,7 +1574,7 @@ function pg_unescape_bytea(string $string): string {}
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param int $verbosity <p>
* @param int $verbosity [optional] <p>
* The required verbosity: <b>PGSQL_ERRORS_TERSE</b>,
* <b>PGSQL_ERRORS_DEFAULT</b>
* or <b>PGSQL_ERRORS_VERBOSE</b>.
@ -1586,7 +1586,7 @@ function pg_unescape_bytea(string $string): string {}
function pg_set_error_verbosity(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
int $verbosity = null
int $verbosity
): int|false {}
/**
@ -1611,7 +1611,7 @@ function pg_client_encoding(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection
* is used. The default connection is the last connection made by
* <b>pg_connect</b> or <b>pg_pconnect</b>.
* </p>
* @param string $encoding <p>
* @param string $encoding [optional] <p>
* The required client encoding. One of SQL_ASCII, EUC_JP,
* EUC_CN, EUC_KR, EUC_TW,
* UNICODE, MULE_INTERNAL, LATINX (X=1...9),
@ -1627,7 +1627,7 @@ function pg_client_encoding(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection
function pg_set_client_encoding(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $encoding = null
string $encoding
): int {}
/**
@ -1817,14 +1817,14 @@ function pg_select(
/**
* @param $connection
* @param $query
* @param $query [optional]
* @return mixed
*/
#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result|false'], default: 'resource|false')]
function pg_exec(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection = null,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection,
string $query = null
string $query
) {}
/**
@ -1932,14 +1932,14 @@ function pg_freeresult(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], defau
/**
* @param PgSql\Result|resource $result
* @param $row
* @param $field
* @param $field [optional]
* @deprecated
*/
function pg_result(
#[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] $connection,
#[PhpStormStubsElementAvailable(from: '8.0')] #[LanguageLevelTypeAware(['8.1' => 'PgSql\Result'], default: 'resource')] $result,
#[PhpStormStubsElementAvailable(from: '8.0')] $row,
#[PhpStormStubsElementAvailable(from: '8.0')] string|int $field = null
#[PhpStormStubsElementAvailable(from: '8.0')] string|int $field
): string|null|false {}
/**

View File

@ -50,17 +50,17 @@ namespace {
/**
* Generate a random integer
* @link https://php.net/manual/en/function.rand.php
* @param int $min
* @param int $min [optional]
* @param int $max [optional]
* @return int A pseudo random value between min
* (or 0) and max (or getrandmax, inclusive).
*/
function rand(int $min = null, int $max): int {}
function rand(int $min, int $max): int {}
/**
* Generate a random value via the Mersenne Twister Random Number Generator
* @link https://php.net/manual/en/function.mt-rand.php
* @param int $min <p>
* @param int $min [optional] <p>
* Optional lowest value to be returned (default: 0)
* </p>
* @param int $max [optional] <p>
@ -69,7 +69,7 @@ namespace {
* @return int A random integer value between min (or 0)
* and max (or mt_getrandmax, inclusive)
*/
function mt_rand(int $min = null, int $max): int {}
function mt_rand(int $min, int $max): int {}
/**
* Show largest possible random value

View File

@ -1054,7 +1054,7 @@ class SoapHeader
public function __construct(
#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace,
#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $name,
#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data = null,
#[LanguageLevelTypeAware(['8.0' => 'mixed'], default: '')] $data,
#[LanguageLevelTypeAware(['8.0' => 'bool'], default: '')] $mustUnderstand = false,
#[LanguageLevelTypeAware(['8.0' => 'string|int|null'], default: '')] $actor = null
) {}

View File

@ -103,6 +103,7 @@ class PHPFunction extends BasePHPElement
$relatedParamTag = array_pop($relatedParamTags);
if ($relatedParamTag !== null) {
$parameter->isOptional = $parameter->isOptional || str_contains((string)$relatedParamTag->getDescription(), '[optional]');
$parameter->markedOptionalInPhpDoc = str_contains((string)$relatedParamTag->getDescription(), '[optional]');
}
}

View File

@ -119,6 +119,7 @@ class PHPMethod extends PHPFunction
$relatedParamTag = array_pop($relatedParamTags);
if ($relatedParamTag !== null) {
$parameter->isOptional = $parameter->isOptional || str_contains((string)$relatedParamTag->getDescription(), '[optional]');
$parameter->markedOptionalInPhpDoc = str_contains((string)$relatedParamTag->getDescription(), '[optional]');
}
}

View File

@ -23,6 +23,8 @@ class PHPParameter extends BasePHPElement
public $is_vararg = false;
public $is_passed_by_ref = false;
public $isOptional = false;
public $isDefaultValueAvailable = false;
public $markedOptionalInPhpDoc = false;
public $defaultValue;
/**
@ -39,6 +41,7 @@ class PHPParameter extends BasePHPElement
$this->is_passed_by_ref = $reflectionObject->isPassedByReference() && !$reflectionObject->canBePassedByValue();
$this->isOptional = $reflectionObject->isOptional();
$this->indexInSignature = $reflectionObject->getPosition();
$this->isDefaultValueAvailable = $reflectionObject->isDefaultValueAvailable();
if ($reflectionObject->isDefaultValueAvailable()) {
$this->defaultValue = $reflectionObject->getDefaultValue();
if (in_array('bool', $this->typesFromSignature, true)) {

View File

@ -57,6 +57,33 @@ class StubsConstantsAndParametersValuesTest extends AbstractBaseStubsTestCase
);
}
/**
* @dataProvider \StubTests\TestData\Providers\Reflection\ReflectionParametersProvider::functionOptionalParametersWithoutDefaultValueProvider
* @throws Exception|RuntimeException
*/
public function testFunctionsWithoutOptionalDefaultParametersValue(PHPFunction $function, PHPParameter $parameter)
{
$phpstormFunction = PhpStormStubsSingleton::getPhpStormStubs()->getFunction($function->name);
$stubParameters = array_filter($phpstormFunction->parameters, fn (PHPParameter $stubParameter) => $stubParameter->indexInSignature === $parameter->indexInSignature);
/** @var PHPParameter $stubOptionalParameter */
$stubOptionalParameter = array_pop($stubParameters);
self::assertTrue(empty($stubOptionalParameter->defaultValue),
sprintf(
'Stub function "%s" has a parameter "%s" which expected to have no default value but it has',
$function->name,
$stubOptionalParameter->name
)
);
self::assertTrue($stubOptionalParameter->markedOptionalInPhpDoc,
sprintf(
'Stub function "%s" has a parameter "%s" which expected to be marked as [optional] at PHPDoc but it is not',
$function->name,
$stubOptionalParameter->name
)
);
}
/**
* @dataProvider \StubTests\TestData\Providers\Reflection\ReflectionParametersProvider::methodOptionalParametersWithDefaultValueProvider
* @throws Exception|RuntimeException
@ -88,4 +115,39 @@ class StubsConstantsAndParametersValuesTest extends AbstractBaseStubsTestCase
)
);
}
/**
* @dataProvider \StubTests\TestData\Providers\Reflection\ReflectionParametersProvider::methodOptionalParametersWithoutDefaultValueProvider
* @throws Exception|RuntimeException
*/
public function testMethodsWithoutOptionalDefaultParametersValue(PHPClass|PHPInterface $class, PHPMethod $method, PHPParameter $parameter)
{
if ($class instanceof PHPEnum) {
$phpstormFunction = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($class->name)->getMethod($method->name);
} elseif ($class instanceof PHPClass) {
$phpstormFunction = PhpStormStubsSingleton::getPhpStormStubs()->getClass($class->name)->getMethod($method->name);
} else {
$phpstormFunction = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($class->name)->getMethod($method->name);
}
$stubParameters = array_filter($phpstormFunction->parameters, fn (PHPParameter $stubParameter) => $stubParameter->indexInSignature === $parameter->indexInSignature);
/** @var PHPParameter $stubOptionalParameter */
$stubOptionalParameter = array_pop($stubParameters);
self::assertTrue(empty($stubOptionalParameter->defaultValue),
sprintf(
'Stub method %s::%s has a parameter "%s" which expected to have no default value but it has',
$class->name,
$method->name,
$stubOptionalParameter->name
)
);
self::assertTrue($stubOptionalParameter->markedOptionalInPhpDoc,
sprintf(
'Stub method %s::%s has a parameter "%s" which expected to be marked as [optional] at PHPDoc but it is not',
$class->name,
$method->name,
$stubOptionalParameter->name
)
);
}
}

View File

@ -63,6 +63,19 @@ class ReflectionParametersProvider
}
}
public static function functionOptionalParametersWithoutDefaultValueProvider(): ?Generator
{
foreach (EntitiesFilter::getFilteredFunctions() as $function) {
foreach (EntitiesFilter::getFilteredParameters(
$function,
fn (PHPParameter $parameter) => !$parameter->isOptional || $parameter->isDefaultValueAvailable || $parameter->is_vararg,
StubProblemType::WRONG_PARAMETER_DEFAULT_VALUE
) as $parameter) {
yield "$function->name($parameter->name)" => [$function, $parameter];
}
}
}
public static function methodParametersProvider(): ?Generator
{
$classesAndInterfaces = ReflectionStubsSingleton::getReflectionStubs()->getClasses() +
@ -129,7 +142,27 @@ class ReflectionParametersProvider
foreach (EntitiesFilter::getFilteredFunctions($class) as $method) {
foreach (EntitiesFilter::getFilteredParameters(
$method,
fn (PHPParameter $parameter) => !$parameter->isOptional,
fn (PHPParameter $parameter) => !$parameter->isOptional || !$parameter->isDefaultValueAvailable,
StubProblemType::WRONG_PARAMETER_DEFAULT_VALUE
) as $parameter) {
yield "$class->name::$method->name($parameter->name)" => [$class, $method, $parameter];
}
}
}
}
}
public static function methodOptionalParametersWithoutDefaultValueProvider(): ?Generator
{
$classesAndInterfaces = ReflectionStubsSingleton::getReflectionStubs()->getClasses() +
ReflectionStubsSingleton::getReflectionStubs()->getInterfaces();
foreach (EntitiesFilter::getFiltered($classesAndInterfaces) as $class) {
//exclude classes from PHPReflectionParser
if (strncmp($class->name, 'PHP', 3) !== 0) {
foreach (EntitiesFilter::getFilteredFunctions($class) as $method) {
foreach (EntitiesFilter::getFilteredParameters(
$method,
fn (PHPParameter $parameter) => !$parameter->isOptional || $parameter->isDefaultValueAvailable || $parameter->is_vararg,
StubProblemType::WRONG_PARAMETER_DEFAULT_VALUE
) as $parameter) {
yield "$class->name::$method->name($parameter->name)" => [$class, $method, $parameter];