Skip to content
This repository was archived by the owner on Dec 29, 2020. It is now read-only.

Commit ccf37b7

Browse files
committed
Merge pull request #10 from mfn/type-whitelist
converter: apply whitelist filtering on supported types
2 parents 8673f09 + 79f6b55 commit ccf37b7

File tree

3 files changed

+116
-2
lines changed

3 files changed

+116
-2
lines changed

src/Converter.php

+76-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ class Converter
3737
const OBJECT_TRAIT = 2;
3838
const OBJECT_FUNCTION = 3;
3939

40+
/**
41+
* @link http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
42+
*/
43+
const TYPES = [
44+
'array',
45+
'bool',
46+
'callable',
47+
'float',
48+
'int',
49+
'self',
50+
'string',
51+
];
52+
4053
/**
4154
* Converts the given file.
4255
*
@@ -446,13 +459,44 @@ private function getReturn(Project $project, int $objectType, string $namespace
446459
}
447460

448461
/**
449-
* Gets the type of the parameter or null if it is not defined.
462+
* Gets the parameter type and tries to find best-matching PHP type
463+
*
464+
* Commonly used type aliases are normalized and a whitelist for
465+
* all-lowercase types is applied.
450466
*
451467
* @param Tag $tag
452468
*
453469
* @return array
454470
*/
455471
private function getType(Tag $tag): array
472+
{
473+
$type = $this->getTypeFromTag($tag);
474+
475+
if (!$type) {
476+
return $type;
477+
}
478+
479+
$typeDesc = $type[0];
480+
481+
if ($typeDesc === strtolower($typeDesc)) {
482+
$typeDesc = $this->normalizeType($typeDesc);
483+
// match all-lowercase types against known types
484+
if (!in_array($typeDesc, static::TYPES)) {
485+
return [];
486+
}
487+
}
488+
489+
return $type;
490+
}
491+
492+
/**
493+
* Gets the type of the parameter or an empty array if it is not defined.
494+
*
495+
* @param Tag $tag
496+
*
497+
* @return array
498+
*/
499+
private function getTypeFromTag(Tag $tag): array
456500
{
457501
$type = $tag->getType();
458502

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

518562
return $matches[1];
519563
}
564+
565+
/**
566+
* Normalizes the type.
567+
*
568+
* @link https://github.com/symfony/symfony/blob/d2d8d17a8068d76f42c42c7791f45ca68f4f98a4/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php#L317-L346
569+
* @license https://github.com/symfony/symfony/blob/d2d8d17a8068d76f42c42c7791f45ca68f4f98a4/src/Symfony/Component/PropertyInfo/LICENSE
570+
*
571+
* @param string $docType
572+
*
573+
* @return string
574+
*/
575+
private function normalizeType($docType)
576+
{
577+
switch ($docType) {
578+
case 'integer':
579+
return 'int';
580+
581+
case 'boolean':
582+
return 'bool';
583+
584+
// real is not part of the PHPDoc standard, so we ignore it
585+
case 'double':
586+
return 'float';
587+
588+
case 'callback':
589+
return 'callable';
590+
591+
default:
592+
return $docType;
593+
}
594+
}
520595
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
/**
3+
* @param integer $integer
4+
* @param boolean $boolean
5+
* @param real $real
6+
* @param double $double
7+
* @param callback $callback
8+
* @param void $void
9+
* @param mixed $mixed
10+
* @param unknown $unknown
11+
* @param Class $class
12+
*/
13+
function aliases($integer, $boolean, $real, $double, $callback, $void, $mixed, $unkown, $class) {
14+
}

tests/test.php

+26-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ function param_no_type($noType)
238238
}
239239

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

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

260+
261+
$projectFactory = ProjectFactory::createInstance();
262+
$project = $projectFactory->create('typeAliasesWhitelisting', [__DIR__.'/Fixtures/type_aliases_and_whitelisting.php']);
263+
264+
foreach ($project->getFiles() as $path => $file) {
265+
$expected = <<<'PHP'
266+
<?php
267+
/**
268+
* @param integer $integer
269+
* @param boolean $boolean
270+
* @param real $real
271+
* @param double $double
272+
* @param callback $callback
273+
* @param void $void
274+
* @param mixed $mixed
275+
* @param unknown $unknown
276+
* @param Class $class
277+
*/
278+
function aliases(int $integer, bool $boolean, $real, float $double, callable $callback, $void, $mixed, $unkown, \Class $class) {
279+
}
280+
281+
PHP;
282+
same($expected, $converter->convert($project, $file));
283+
}
284+
260285
echo 'Good job! Everything is fine.'.PHP_EOL;

0 commit comments

Comments
 (0)