forked from phpstan/phpstan-src
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtransform-source.php
executable file
·122 lines (101 loc) · 2.66 KB
/
transform-source.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env php
<?php declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
ini_set('memory_limit', '512M');
use PhpParser\Lexer;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\NullableType;
use PhpParser\Node\UnionType;
use PhpParser\Parser;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor;
use PhpParser\NodeVisitorAbstract;
use PhpParser\PrettyPrinter;
use PhpParser\Node;
class PhpPatcher extends NodeVisitorAbstract
{
public function leaveNode(Node $node)
{
if (!$node instanceof Node\Stmt\Property) {
return null;
}
if ($node->type === null) {
return null;
}
$docComment = $node->getDocComment();
if ($docComment !== null) {
$node->type = null;
return $node;
}
$node->setDocComment(new \PhpParser\Comment\Doc(sprintf('/** @var %s */', $this->printType($node->type))));
$node->type = null;
return $node;
}
/**
* @param Identifier|Name|NullableType|UnionType $type
* @return string
*/
private function printType($type): string
{
if ($type instanceof NullableType) {
return $this->printType($type->type) . '|null';
}
if ($type instanceof UnionType) {
throw new \Exception('UnionType not yet supported');
}
if ($type instanceof Name) {
$name = $type->toString();
if ($type->isFullyQualified()) {
return '\\' . $name;
}
return $name;
}
if ($type instanceof Identifier) {
return $type->name;
}
throw new \Exception('Unsupported type class');
}
}
(function () {
$dir = __DIR__ . '/../src';
$lexer = new Lexer\Emulative([
'usedAttributes' => [
'comments',
'startLine', 'endLine',
'startTokenPos', 'endTokenPos',
],
]);
$parser = new Parser\Php7($lexer, [
'useIdentifierNodes' => true,
'useConsistentVariableNodes' => true,
'useExpressionStatements' => true,
'useNopStatements' => false,
]);
$nameResolver = new NodeVisitor\NameResolver(null, [
'replaceNodes' => false
]);
$printer = new PrettyPrinter\Standard();
$traverser = new NodeTraverser();
$traverser->addVisitor(new NodeVisitor\CloningVisitor());
$traverser->addVisitor($nameResolver);
$traverser->addVisitor(new PhpPatcher($printer));
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($it as $file) {
$fileName = $file->getPathname();
if (!preg_match('/\.php$/', $fileName)) {
continue;
}
$code = \PHPStan\File\FileReader::read($fileName);
$origStmts = $parser->parse($code);
$newCode = $printer->printFormatPreserving(
$traverser->traverse($origStmts),
$origStmts,
$lexer->getTokens()
);
\PHPStan\File\FileWriter::write($fileName, $newCode);
}
})();