Skip to content
This repository was archived by the owner on Dec 29, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 76 additions & 1 deletion src/Converter.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ class Converter
const OBJECT_TRAIT = 2;
const OBJECT_FUNCTION = 3;

/**
* @link http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
*/
const TYPES = [
'array',
'bool',
'callable',
'float',
'int',
'self',
'string',
];

/**
* Converts the given file.
*
Expand Down Expand Up @@ -446,13 +459,44 @@ private function getReturn(Project $project, int $objectType, string $namespace
}

/**
* Gets the type of the parameter or null if it is not defined.
* Gets the parameter type and tries to find best-matching PHP type
*
* Commonly used type aliases are normalized and a whitelist for
* all-lowercase types is applied.
*
* @param Tag $tag
*
* @return array
*/
private function getType(Tag $tag): array
{
$type = $this->getTypeFromTag($tag);

if (!$type) {
return $type;
}

$typeDesc = $type[0];

if ($typeDesc === strtolower($typeDesc)) {
$typeDesc = $this->normalizeType($typeDesc);
// match all-lowercase types against known types
if (!in_array($typeDesc, static::TYPES)) {
return [];
}
}

return $type;
}

/**
* Gets the type of the parameter or an empty array if it is not defined.
*
* @param Tag $tag
*
* @return array
*/
private function getTypeFromTag(Tag $tag): array
{
$type = $tag->getType();

Expand Down Expand Up @@ -517,4 +561,35 @@ private function endsInNewLine(string $output): string

return $matches[1];
}

/**
* Normalizes the type.
*
* @link https://github.com/symfony/symfony/blob/d2d8d17a8068d76f42c42c7791f45ca68f4f98a4/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php#L317-L346
* @license https://github.com/symfony/symfony/blob/d2d8d17a8068d76f42c42c7791f45ca68f4f98a4/src/Symfony/Component/PropertyInfo/LICENSE
*
* @param string $docType
*
* @return string
*/
private function normalizeType($docType)
{
switch ($docType) {
case 'integer':
return 'int';

case 'boolean':
return 'bool';

// real is not part of the PHPDoc standard, so we ignore it
case 'double':
return 'float';

case 'callback':
return 'callable';

default:
return $docType;
}
}
}
14 changes: 14 additions & 0 deletions tests/Fixtures/type_aliases_and_whitelisting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* @param integer $integer
* @param boolean $boolean
* @param real $real
* @param double $double
* @param callback $callback
* @param void $void
* @param mixed $mixed
* @param unknown $unknown
* @param Class $class
*/
function aliases($integer, $boolean, $real, $double, $callback, $void, $mixed, $unkown, $class) {
}
27 changes: 26 additions & 1 deletion tests/test.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ function param_no_type($noType)
}

$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('paramNoType', [__DIR__.'/Fixtures/array_no_types.php']);
$project = $projectFactory->create('arrayNoTypes', [__DIR__.'/Fixtures/array_no_types.php']);

foreach ($project->getFiles() as $path => $file) {
$expected = <<<'PHP'
Expand All @@ -257,4 +257,29 @@ function array_no_types(array $ints, array $strings, array $someClasses) : array
same($expected, $converter->convert($project, $file));
}


$projectFactory = ProjectFactory::createInstance();
$project = $projectFactory->create('typeAliasesWhitelisting', [__DIR__.'/Fixtures/type_aliases_and_whitelisting.php']);

foreach ($project->getFiles() as $path => $file) {
$expected = <<<'PHP'
<?php
/**
* @param integer $integer
* @param boolean $boolean
* @param real $real
* @param double $double
* @param callback $callback
* @param void $void
* @param mixed $mixed
* @param unknown $unknown
* @param Class $class
*/
function aliases(int $integer, bool $boolean, $real, float $double, callable $callback, $void, $mixed, $unkown, \Class $class) {
}

PHP;
same($expected, $converter->convert($project, $file));
}

echo 'Good job! Everything is fine.'.PHP_EOL;