Skip to content

Commit a062c55

Browse files
committed
Extractor: refactoring
1 parent 249f307 commit a062c55

File tree

1 file changed

+47
-32
lines changed

1 file changed

+47
-32
lines changed

src/PhpGenerator/Extractor.php

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ public function extractMethodBodies(string $className): array
6262
foreach ($nodeFinder->findInstanceOf($classNode, Node\Stmt\ClassMethod::class) as $methodNode) {
6363
/** @var Node\Stmt\ClassMethod $methodNode */
6464
if ($methodNode->stmts) {
65-
$body = $this->extractBody($nodeFinder, $methodNode->stmts);
66-
$res[$methodNode->name->toString()] = Helpers::unindent($body, 2);
65+
$res[$methodNode->name->toString()] = $this->getReformattedBody($methodNode->stmts, 2);
6766
}
6867
}
6968
return $res;
@@ -72,34 +71,38 @@ public function extractMethodBodies(string $className): array
7271

7372
public function extractFunctionBody(string $name): ?string
7473
{
75-
$nodeFinder = new NodeFinder;
76-
/** @var Node\Stmt\Function_ $functionNode */
77-
$functionNode = $nodeFinder->findFirst($this->statements, function (Node $node) use ($name) {
74+
$functionNode = (new NodeFinder)->findFirst($this->statements, function (Node $node) use ($name) {
7875
return $node instanceof Node\Stmt\Function_ && $node->namespacedName->toString() === $name;
7976
});
8077

81-
$body = $this->extractBody($nodeFinder, $functionNode->stmts);
82-
return Helpers::unindent($body, 1);
78+
return $this->getReformattedBody($functionNode->stmts, 1);
8379
}
8480

8581

86-
/**
87-
* @param Node[] $statements
88-
*/
89-
private function extractBody(NodeFinder $nodeFinder, array $statements): string
82+
/** @param Node[] $statements */
83+
private function getReformattedBody(array $statements, int $level): string
9084
{
91-
$start = $statements[0]->getAttribute('startFilePos');
92-
$body = substr($this->code, $start, end($statements)->getAttribute('endFilePos') - $start + 1);
85+
$replacements = $this->prepareReplacements($statements);
86+
$body = $this->getNodeContents(...$statements);
87+
$body = $this->performReplacements($body, $replacements);
88+
return Helpers::unindent($body, $level);
89+
}
9390

91+
92+
private function prepareReplacements(array $statements): array
93+
{
94+
$start = $statements[0]->getStartFilePos();
9495
$replacements = [];
96+
$nodeFinder = new NodeFinder;
97+
9598
// name-nodes => resolved fully-qualified name
9699
foreach ($nodeFinder->findInstanceOf($statements, Node\Name::class) as $node) {
97100
if ($node->hasAttribute('resolvedName')
98101
&& $node->getAttribute('resolvedName') instanceof Node\Name\FullyQualified
99102
) {
100103
$replacements[] = [
101-
$node->getStartFilePos(),
102-
$node->getEndFilePos(),
104+
$node->getStartFilePos() - $start,
105+
$node->getEndFilePos() - $start,
103106
$node->getAttribute('resolvedName')->toCodeString(),
104107
];
105108
}
@@ -111,12 +114,12 @@ private function extractBody(NodeFinder $nodeFinder, array $statements): string
111114
$nodeFinder->findInstanceOf($statements, Node\Scalar\EncapsedStringPart::class)
112115
) as $node) {
113116
/** @var Node\Scalar\String_|Node\Scalar\EncapsedStringPart $node */
114-
$token = substr($body, $node->getStartFilePos() - $start, $node->getEndFilePos() - $node->getStartFilePos() + 1);
117+
$token = $this->getNodeContents($node);
115118
if (strpos($token, "\n") !== false) {
116119
$quote = $node instanceof Node\Scalar\String_ ? '"' : '';
117120
$replacements[] = [
118-
$node->getStartFilePos(),
119-
$node->getEndFilePos(),
121+
$node->getStartFilePos() - $start,
122+
$node->getEndFilePos() - $start,
120123
$quote . addcslashes($node->value, "\x00..\x1F") . $quote,
121124
];
122125
}
@@ -127,34 +130,46 @@ private function extractBody(NodeFinder $nodeFinder, array $statements): string
127130
/** @var Node\Scalar\Encapsed $node */
128131
if ($node->getAttribute('kind') === Node\Scalar\String_::KIND_HEREDOC) {
129132
$replacements[] = [
130-
$node->getStartFilePos(),
131-
$node->parts[0]->getStartFilePos() - 1,
133+
$node->getStartFilePos() - $start,
134+
$node->parts[0]->getStartFilePos() - $start - 1,
132135
'"',
133136
];
134137
$replacements[] = [
135-
end($node->parts)->getEndFilePos() + 1,
136-
$node->getEndFilePos(),
138+
end($node->parts)->getEndFilePos() - $start + 1,
139+
$node->getEndFilePos() - $start,
137140
'"',
138141
];
139142
}
140143
}
141144

142-
//sort collected resolved names by position in file
143-
usort($replacements, function ($a, $b) {
145+
return $replacements;
146+
}
147+
148+
149+
private function performReplacements(string $s, array $replacements): string
150+
{
151+
usort($replacements, function ($a, $b) { // sort by position in file
144152
return $a[0] <=> $b[0];
145153
});
146-
$correctiveOffset = -$start;
147-
//replace changes body length so we need correct offset
148-
foreach ($replacements as [$startPos, $endPos, $replacement]) {
149-
$replacingStringLength = $endPos - $startPos + 1;
150-
$body = substr_replace(
151-
$body,
154+
155+
$correctiveOffset = 0;
156+
foreach ($replacements as [$start, $end, $replacement]) {
157+
$replacingStringLength = $end - $start + 1;
158+
$s = substr_replace(
159+
$s,
152160
$replacement,
153-
$correctiveOffset + $startPos,
161+
$correctiveOffset + $start,
154162
$replacingStringLength
155163
);
156164
$correctiveOffset += strlen($replacement) - $replacingStringLength;
157165
}
158-
return $body;
166+
return $s;
167+
}
168+
169+
170+
private function getNodeContents(Node ...$nodes): string
171+
{
172+
$start = $nodes[0]->getStartFilePos();
173+
return substr($this->code, $start, end($nodes)->getEndFilePos() - $start + 1);
159174
}
160175
}

0 commit comments

Comments
 (0)