Skip to content

Commit b03391a

Browse files
committed
[+]: add simple auto-fix
1 parent 82e5689 commit b03391a

File tree

7 files changed

+350
-116
lines changed

7 files changed

+350
-116
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
# ***PHP-Documentation-Check***
88

9-
This is a experiment! Lets check (maybe fix at some point) the php documentation automatically.
9+
This is a experiment! Lets check and fix the php documentation automatically.
1010

1111
```
1212
git clone https://github.com/php/doc-en
1313
cd ..
1414
git clone https://github.com/voku/php-doc-fixer
1515
composer install
16-
php bin/phpdocfixer run doc-en/reference
16+
php bin/phpdocfixer run [--auto-fix="true"] doc-en/reference
1717
```
1818

1919
### Support

src/voku/PhpDocFixer/CliCommand/PhpDocFixerCommand.php

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ public function configure(): void
3232
new InputArgument('path', InputArgument::REQUIRED, 'The path to analyse'),
3333
]
3434
)
35+
)
36+
->addOption(
37+
'auto-fix',
38+
null,
39+
\Symfony\Component\Console\Input\InputOption::VALUE_OPTIONAL,
40+
'Automatically fix the types in the given xml files. (false or true)',
41+
'false'
3542
);
3643
}
3744

@@ -42,6 +49,8 @@ public function execute(InputInterface $input, OutputInterface $output): int
4249
$realPath = \realpath($path);
4350
\assert(\is_string($realPath));
4451

52+
$autoFix = $input->getOption('auto-fix') !== 'false';
53+
4554
if (!$realPath || !\file_exists($realPath)) {
4655
$output->writeln('-------------------------------');
4756
$output->writeln('The path "' . $path . '" does not exists.');
@@ -50,26 +59,39 @@ public function execute(InputInterface $input, OutputInterface $output): int
5059
return 2;
5160
}
5261

53-
$xmlReader = new \voku\PhpDocFixer\ReadXmlDocs\XmlReader($realPath);
62+
$xmlReader = new \voku\PhpDocFixer\XmlDocs\XmlReader($realPath);
5463
$xmlDocInfo = $xmlReader->parse();
5564

5665
$phpStormStubsPath = __DIR__ . '/../../../../vendor/jetbrains/phpstorm-stubs/';
57-
$phpTypesFromPhpStormStubs = new \voku\PhpDocFixer\ReadPhpStormStubs\PhpStormStubsReader($phpStormStubsPath);
66+
$phpTypesFromPhpStormStubs = new \voku\PhpDocFixer\PhpStormStubs\PhpStormStubsReader($phpStormStubsPath);
5867
$phpStormStubsInfo = $phpTypesFromPhpStormStubs->parse();
5968

6069
$errors = [];
6170
foreach ($xmlDocInfo as $functionName_or_classAndMethodName => $types) {
6271
if (!isset($phpStormStubsInfo[$functionName_or_classAndMethodName])) {
63-
// TODO: check this
64-
//\var_dump($functionName_or_classAndMethodName);
72+
// TODO: error in phpstorm-stubs ?
73+
//\var_dump($functionName_or_classAndMethodName); exit;
6574
continue;
6675
}
6776

68-
if ($phpStormStubsInfo[$functionName_or_classAndMethodName] !== $types) {
77+
if (
78+
($phpStormStubsInfo[$functionName_or_classAndMethodName]['return'] ?? []) !== ($types['return'] ?? [])
79+
||
80+
($phpStormStubsInfo[$functionName_or_classAndMethodName]['params'] ?? []) !== ($types['params'] ?? [])
81+
) {
82+
$pathTmp = $types['absoluteFilePath'];
83+
unset($types['absoluteFilePath']);
84+
6985
$errors[$functionName_or_classAndMethodName] = [
7086
'phpStubTypes' => $phpStormStubsInfo[$functionName_or_classAndMethodName],
71-
'phpDocTypes' => $types,
87+
'phpDocTypes' => $types,
88+
'path' => $pathTmp,
7289
];
90+
91+
if ($autoFix) {
92+
$xmlFixer = new \voku\PhpDocFixer\XmlDocs\XmlWriter($pathTmp);
93+
$xmlFixer->fix($phpStormStubsInfo[$functionName_or_classAndMethodName]);
94+
}
7395
}
7496
}
7597

src/voku/PhpDocFixer/ReadPhpStormStubs/PhpStormStubsReader.php renamed to src/voku/PhpDocFixer/PhpStormStubs/PhpStormStubsReader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace voku\PhpDocFixer\ReadPhpStormStubs;
5+
namespace voku\PhpDocFixer\PhpStormStubs;
66

77
final class PhpStormStubsReader
88
{

src/voku/PhpDocFixer/ReadXmlDocs/XmlReader.php

Lines changed: 0 additions & 104 deletions
This file was deleted.
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace voku\PhpDocFixer\XmlDocs;
6+
7+
final class XmlReader
8+
{
9+
private string $xml_path;
10+
11+
public function __construct(string $xml_path)
12+
{
13+
$this->xml_path = $xml_path;
14+
}
15+
16+
/**
17+
* @return array
18+
*
19+
* @phpstan-return array<string, array{
20+
* return?: string,
21+
* params?: array<string, string>,
22+
* absoluteFilePath: string
23+
* }>
24+
*/
25+
public function parse(): array
26+
{
27+
$xmlParser = new \voku\helper\XmlDomParser();
28+
$xmlParser->autoRemoveXPathNamespaces();
29+
30+
$finder = new \Symfony\Component\Finder\Finder();
31+
$finder->files()->in($this->xml_path);
32+
33+
$data = [[]];
34+
foreach ($finder as $file) {
35+
$fileName = $file->getFilename();
36+
if (\strpos($fileName, '.xml') === false) {
37+
continue;
38+
}
39+
40+
$absoluteFilePath = $file->getPath() . \DIRECTORY_SEPARATOR . $fileName;
41+
$content = $file->getContents();
42+
43+
\preg_match('#<methodsynopsis>.*</methodsynopsis>#Uis', $content, $contentMethod);
44+
$contentMethod = $contentMethod[0] ?? null;
45+
46+
\preg_match('#<methodsynopsis role="oop">.*</methodsynopsis>#Uis', $content, $contentMethodOop);
47+
$contentMethodOop = $contentMethodOop[0] ?? null;
48+
49+
\preg_match('#<constructorsynopsis>.*</constructorsynopsis>#Uis', $content, $contentConstructor);
50+
$contentConstructor = $contentConstructor[0] ?? null;
51+
52+
if (!$contentMethod && !$contentMethodOop && !$contentConstructor) {
53+
continue;
54+
}
55+
56+
if ($contentMethod) {
57+
$methodsynopsis = $xmlParser->loadXml($contentMethod);
58+
$data[] = $this->findTypes($methodsynopsis, $absoluteFilePath);
59+
}
60+
61+
if ($contentMethodOop) {
62+
$methodsynopsisOop = $xmlParser->loadXml($contentMethodOop);
63+
$data[] = $this->findTypes($methodsynopsisOop, $absoluteFilePath);
64+
}
65+
66+
if ($contentConstructor) {
67+
$constructorsynopsis = $xmlParser->loadXml($contentConstructor);
68+
$data[] = $this->findTypes($constructorsynopsis, $absoluteFilePath);
69+
}
70+
}
71+
72+
return \array_merge([], ...$data);
73+
}
74+
75+
/**
76+
* @param \voku\helper\XmlDomParser $xmlParser
77+
* @param string $absoluteFilePath
78+
*
79+
* @return array
80+
*
81+
* @phpstan-return array<string, array{
82+
* return?: string,
83+
* params?: array<string, string>,
84+
* absoluteFilePath: string
85+
* }>
86+
*/
87+
private function findTypes(
88+
\voku\helper\XmlDomParser $xmlParser,
89+
string $absoluteFilePath
90+
): array {
91+
// init
92+
$data = [];
93+
94+
$name = $xmlParser->findOne('//methodname')->text();
95+
$data[$name]['absoluteFilePath'] = $absoluteFilePath;
96+
97+
$returnTypesArray = [];
98+
$returnTypesTmp = $xmlParser->findMultiOrFalse('type.union type');
99+
if ($returnTypesTmp !== false) {
100+
foreach ($returnTypesTmp as $returnTypeTmp) {
101+
$returnTypeText = $returnTypeTmp->text();
102+
$returnTypesArray[$returnTypeText] = \ltrim($returnTypeText, '\\');
103+
}
104+
} elseif (($returnTypeTmp = $xmlParser->findOneOrFalse('type')) !== false) {
105+
$returnTypeText = $returnTypeTmp->text();
106+
$returnTypesArray[$returnTypeText] = \ltrim($returnTypeText, '\\');
107+
}
108+
$data[$name]['return'] = \implode('|', $returnTypesArray ?? []);
109+
110+
$params = $xmlParser->findMultiOrFalse('//methodparam');
111+
if ($params !== false) {
112+
foreach ($params as $param) {
113+
$paramName = $param->findOne('parameter')->text();
114+
$paramTypesArray = [];
115+
116+
$paramTypesTmp = $param->findMultiOrFalse('type.union type');
117+
if ($paramTypesTmp !== false) {
118+
foreach ($paramTypesTmp as $paramTypeTmp) {
119+
$paramTypeText = $paramTypeTmp->text();
120+
$paramTypesArray[$paramTypeText] = \ltrim($paramTypeText, '\\');
121+
}
122+
} elseif (($paramTypeTmp = $param->findOneOrFalse('type')) !== false) {
123+
$paramTypeText = $paramTypeTmp->text();
124+
$paramTypesArray[$paramTypeText] = \ltrim($paramTypeText, '\\');
125+
}
126+
127+
$data[$name]['params'][$paramName] = \implode('|', $paramTypesArray ?? []);
128+
}
129+
}
130+
131+
return $data;
132+
}
133+
}

0 commit comments

Comments
 (0)