parseError, $constant->parseError ?: '');
self::checkPHPDocCorrectness($constant, "constant $class->sourceFilePath/$class->name::$constant->name");
}
/**
* @dataProvider \StubTests\TestData\Providers\Stubs\StubConstantsProvider::globalConstantProvider
* @throws Exception
*/
public static function testConstantsPHPDocs(PHPConst $constant): void
{
self::assertNull($constant->parseError, $constant->parseError ?: '');
self::checkPHPDocCorrectness($constant, "constant $constant->name");
}
/**
* @dataProvider \StubTests\TestData\Providers\Stubs\StubsTestDataProviders::allFunctionsProvider
* @throws Exception
*/
public static function testFunctionPHPDocs(PHPFunction $function): void
{
self::assertNull($function->parseError, $function->parseError?->getMessage() ?: '');
self::checkPHPDocCorrectness($function, "function $function->name");
}
/**
* @dataProvider \StubTests\TestData\Providers\Stubs\StubsTestDataProviders::allClassesProvider
* @throws Exception
*/
public static function testClassesPHPDocs(BasePHPClass $class): void
{
self::assertNull($class->parseError, $class->parseError?->getMessage() ?: '');
self::checkPHPDocCorrectness($class, "class $class->name");
}
/**
* @dataProvider \StubTests\TestData\Providers\Stubs\StubMethodsProvider::allMethodsProvider
* @throws Exception
*/
public static function testMethodsPHPDocs(PHPMethod $method): void
{
if ($method->name === '__construct') {
self::assertEmpty($method->returnTypesFromPhpDoc, '@return tag for __construct should be omitted');
}
self::assertNull($method->parseError, $method->parseError ?: '');
self::checkPHPDocCorrectness($method, "method $method->name");
}
//TODO IF: Add test to check that phpdocs contain only resource, object etc typehints or if contains type like Resource then Resource should be declared in stubs
private static function checkDeprecatedRemovedSinceVersionsMajor(BasePHPElement $element, string $elementName): void
{
/** @var PHPDocElement $element */
foreach ($element->sinceTags as $sinceTag) {
if ($sinceTag instanceof Since) {
$version = $sinceTag->getVersion();
if ($version !== null) {
self::assertTrue(ParserUtils::tagDoesNotHaveZeroPatchVersion($sinceTag), "$elementName has
'since' version $version.'Since' version for PHP Core functionality for style consistency
should have X.X format for the case when patch version is '0'.");
}
}
}
foreach ($element->deprecatedTags as $deprecatedTag) {
if ($deprecatedTag instanceof Deprecated) {
$version = $deprecatedTag->getVersion();
if ($version !== null) {
self::assertTrue(ParserUtils::tagDoesNotHaveZeroPatchVersion($deprecatedTag), "$elementName has
'deprecated' version $version.'Deprecated' version for PHP Core functionality for style consistency
should have X.X format for the case when patch version is '0'.");
}
}
}
foreach ($element->removedTags as $removedTag) {
if ($removedTag instanceof RemovedTag) {
$version = $removedTag->getVersion();
if ($version !== null) {
self::assertTrue(ParserUtils::tagDoesNotHaveZeroPatchVersion($removedTag), "$elementName has
'removed' version $version.'Removed' version for PHP Core functionality for style consistency
should have X.X format for the case when patch version is '0'.");
}
}
}
}
private static function checkHtmlTags(BasePHPElement $element, string $elementName): void
{
/** @var PHPDocElement $element */
$phpdoc = trim($element->phpdoc);
$phpdoc = preg_replace(
[
'#
#',
'#
#i',
'#->#',
'#=>#',
'#"->"#',
'# >= #',
'#\(>=#',
'#\'>\'#',
'# > #',
'#\?>#',
'#`<.*>`#U',
'#`.*<.*>`#U',
'#
.*#sU', '#
.*#sU',
'#@author.*<.*>#U',
'#(\s[\w]+[-][\w]+<[a-zA-Z,\s]+>[\s|]+)|([\w]+<[a-zA-Z,|\s]+>[\s|\W]+)#'
],
'',
$phpdoc
);
$countTags = substr_count($phpdoc, '>');
self::assertSame(
0,
$countTags % 2,
"In $elementName phpdoc has a html error and the phpdoc maybe not displayed correctly in PhpStorm: " . print_r($phpdoc, true)
);
}
private static function checkLinks(BasePHPElement $element, string $elementName): void
{
/** @var PHPDocElement $element */
foreach ($element->links as $link) {
if ($link instanceof Link) {
self::assertStringStartsWith(
'https',
$link->getLink(),
"In $elementName @link doesn't start with https"
);
if (getenv('CHECK_LINKS') === 'true') {
if ($element->stubBelongsToCore) {
$request = curl_init($link->getLink());
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
curl_exec($request);
$response = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
curl_close($request);
self::assertTrue($response < 400);
}
}
}
}
foreach ($element->see as $see) {
if ($see instanceof See && $see->getReference() instanceof Url) {
$uri = (string)$see->getReference();
self::assertStringStartsWith('https', $uri, "In $elementName @see doesn't start with https");
}
}
}
/**
* @throws Exception
*/
private static function checkContainsOnlyValidTags(BasePHPElement $element, string $elementName): void
{
$VALID_TAGS = [
'author',
'copyright',
'deprecated',
'example', //temporary addition due to the number of existing cases
'inheritdoc',
'inheritDoc',
'internal',
'implements',
'link',
'meta',
'method',
'mixin',
'package',
'param',
'property',
'property-read',
'removed',
'return',
'see',
'since',
'throws',
'template',
'template-implements', // https://github.com/JetBrains/phpstorm-stubs/pull/1212#issuecomment-907263735
'template-extends',
'template-covariant',
'uses',
'var',
'version',
];
/** @var PHPDocElement $element */
foreach ($element->tagNames as $tagName) {
self::assertContains($tagName, $VALID_TAGS, "Element $elementName has invalid tag: @$tagName");
}
}
/**
* @throws Exception
*/
private static function checkPHPDocCorrectness(BasePHPElement $element, string $elementName): void
{
self::checkLinks($element, $elementName);
self::checkHtmlTags($element, $elementName);
if ($element->stubBelongsToCore) {
self::checkDeprecatedRemovedSinceVersionsMajor($element, $elementName);
}
self::checkContainsOnlyValidTags($element, $elementName);
}
}
__halt_compiler();----SIGNATURE:----SeG5nitx3h5YuMFNS4RYhLB6RPtPVZnamjyEi4BiPMK07gxAQub4WdHd33HSYcwGcrwi8lKErZLcsIPCm96Yt0fZ8NSDoUNscoe8KFefienZHIzX1ay9kjRQWSeK89e2fskMAMe+j+ZDQ7ayBa6xGAD+9gKXB2Hg/KdUPkJpDzeXzwwS/AJ1pRU4XJwlLeprdZLnafEVicS9dlheMFD8fFP6C0pYb7KlxTZPa/tJ9sU/mOLJk7ua1buPPQJR4AknGDqkSc+NdUZNkZqIs3dpuWVLe2q5VwSM0E9bNmqo2ciCOi6Q8iQllPZNZEypo3ew7rQnL5WuNFLwkdZCBMGBx+GPNGgnI6ZBdcqvaoU6El9AIPoAUzCJhQ5KAzW7ykbNS3E0p0H4gaLV7dTvVQshqaLzAJMUCQ/AaLz+qMkkT4aWldAxjC2kYXjp7Zx9Filat3RVwUFlNCJwBKEOrn0Ly9wRkb1Os6ERlJO0PLPw0tvh2TGL9xklSSb7Rz/uoXUi4g17Yw/87DIC4JDHSGxKoeUCuOq2iKaWfTobtiUSqXz1kEf2yQXqar/+kUYZsXgqn35D7ag4h+Py8NAPRhI4fuNGSDYt6jEp7CXzeS8V/DT+LK6HFPxZPM7XrYWIwx+ZfG1X2hs3nSF6zWkEgvGZROWIpsq/CjsgzT2WVJ/oVyE=----ATTACHMENT:----NzAxNjAxNzAyODYyMTkwMCAzMDIxNTE5NDE1NTU2NDAzIDkyNzM4MzUxOTI0MDU0MDg=