Skip to content

Commit 3e79655

Browse files
committed
wip
1 parent 1e5f520 commit 3e79655

18 files changed

+676
-2
lines changed

app/Parser/Context.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace App\Parser;
44

5+
use Illuminate\Support\Arr;
6+
57
class Context
68
{
79
public $classDefinition = null;
@@ -34,14 +36,34 @@ class Context
3436

3537
public $paramIndex = 0;
3638

39+
public $children = [];
40+
3741
public function __construct(public ?Context $parent = null)
3842
{
39-
$this->freshObject = $this->toArray();
43+
$this->freshObject = $this->freshArray();
44+
}
45+
46+
protected function freshArray()
47+
{
48+
return Arr::except($this->toArray(), ['parent']);
49+
}
50+
51+
public function initNew()
52+
{
53+
if ($this->pristine()) {
54+
return $this;
55+
}
56+
57+
$newContext = new static();
58+
59+
$this->children[] = $newContext;
60+
61+
return $newContext;
4062
}
4163

4264
public function pristine(): bool
4365
{
44-
return $this->toArray() === $this->freshObject;
66+
return $this->freshObject === $this->freshArray();
4567
}
4668

4769
public function touched(): bool
@@ -112,6 +134,7 @@ public function toArray()
112134
'fillingInArrayKey' => $this->fillingInArrayKey,
113135
'fillingInArrayValue' => $this->fillingInArrayValue,
114136
'paramIndex' => $this->paramIndex,
137+
'children' => array_map(fn($child) => $child->toArray(), $this->children),
115138
];
116139
}
117140

app/Parser/Parse.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace App\Parser;
4+
5+
use Microsoft\PhpParser\Node;
6+
use Microsoft\PhpParser\Node\SourceFileNode;
7+
8+
class Parse
9+
{
10+
public static function parse(Node $node, $depth = 0, $currentContext = null)
11+
{
12+
echo str_repeat(' ', $depth) . $node::class . PHP_EOL;
13+
14+
$class = basename(str_replace('\\', '/', $node::class));
15+
$parser = 'App\\Parser\\Parsers\\' . $class . 'Parser';
16+
17+
$context = $currentContext ?? new Context();
18+
19+
if (class_exists($parser)) {
20+
echo str_repeat(' ', $depth) . '- Parsing: ' . $parser . PHP_EOL;
21+
echo PHP_EOL;
22+
23+
$parser = app()->make($parser);
24+
25+
if ($parser->shouldInitNewContext()) {
26+
// echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
27+
// echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
28+
// echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
29+
// echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
30+
$context = $context->initNew();
31+
}
32+
33+
// echo $context->toJson(JSON_PRETTY_PRINT) . PHP_EOL;
34+
35+
$parser->context($context)->depth($depth + 1)->parseNode($node);
36+
}
37+
38+
foreach ($node->getChildNodes() as $child) {
39+
self::parse($child, $depth + 1, $context);
40+
}
41+
42+
return $context;
43+
44+
echo str_repeat(' ', $depth) . $node::class . PHP_EOL;
45+
echo str_repeat(' ', $depth) . '[code] ' . substr(str_replace("\n", ' ', $node->getText()), 0, 25) . '...' . PHP_EOL;
46+
47+
if (!class_exists($parser)) {
48+
echo PHP_EOL;
49+
return $currentContext;
50+
}
51+
52+
echo str_repeat(' ', $depth) . '- Parsing: ' . $parser . PHP_EOL;
53+
echo PHP_EOL;
54+
55+
$parser = app()->make($parser);
56+
57+
$context = $currentContext ?? new Context();
58+
59+
if ($parser->shouldInitNewContext()) {
60+
echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
61+
echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
62+
echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
63+
echo '------------ INIT NEW CONTEXT ------------ ' . PHP_EOL;
64+
$context = $context->initNew();
65+
}
66+
67+
echo $context->toJson(JSON_PRETTY_PRINT) . PHP_EOL;
68+
69+
$result = $parser->context($context)->depth($depth + 1)->parse($node);
70+
71+
if ($node instanceof SourceFileNode) {
72+
dd($context, 'sou rce file');
73+
}
74+
75+
return $result;
76+
}
77+
}

app/Parser/Parsers/AbstractParser.php

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
namespace App\Parser\Parsers;
4+
5+
use App\Parser\Context;
6+
use App\Parser\Parse;
7+
use Microsoft\PhpParser\Node;
8+
9+
abstract class AbstractParser
10+
{
11+
protected int $depth = 0;
12+
13+
protected Context $context;
14+
15+
// public function __construct()
16+
// {
17+
// $this->context = new Context();
18+
// }
19+
20+
public function context(Context $context)
21+
{
22+
$this->context = $context;
23+
24+
return $this;
25+
}
26+
27+
public function parseNode(Node $node): Context
28+
{
29+
if (method_exists($this, 'parse')) {
30+
return call_user_func([$this, 'parse'], $node);
31+
}
32+
33+
return $this->context;
34+
}
35+
36+
public function depth(int $depth)
37+
{
38+
$this->depth = $depth;
39+
40+
return $this;
41+
}
42+
43+
public function shouldInitNewContext()
44+
{
45+
return false;
46+
}
47+
48+
public function indent($message)
49+
{
50+
return str_repeat(' ', $this->depth) . $message;
51+
}
52+
53+
public function debug(...$messages)
54+
{
55+
return;
56+
foreach ($messages as $message) {
57+
echo $this->indent($message) . PHP_EOL;
58+
}
59+
}
60+
61+
protected function loopChildren(Node $node)
62+
{
63+
foreach ($node->getChildNodes() as $child) {
64+
$this->debug('Child: ' . $child::class);
65+
$this->addChild(Parse::parse($child, $this->depth + 1, $this->context));
66+
}
67+
}
68+
69+
protected function addChild($child)
70+
{
71+
// if ($child) {
72+
// $this->context->child = new Context($child);
73+
// $this->context = $this->context->child;
74+
// }
75+
76+
// $filtered = $child->filter();
77+
78+
// if ($filtered->isNotEmpty()) {
79+
// $this->context->child = new Context($filtered->last());
80+
// $this->context = $this->context->child;
81+
// }
82+
}
83+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace App\Parser\Parsers;
4+
5+
use Microsoft\PhpParser\MissingToken;
6+
use Microsoft\PhpParser\Node\Expression\ArrayCreationExpression;
7+
8+
class ArrayCreationExpressionParser extends AbstractParser
9+
{
10+
public function parse(ArrayCreationExpression $node)
11+
{
12+
return $this->context;
13+
14+
$array = [];
15+
$lastValue = null;
16+
17+
if ($node->arrayElements) {
18+
foreach ($node->arrayElements->getElements() as $element) {
19+
$array[] = [
20+
'key' => $this->parseArgument($element->elementKey),
21+
'value' => $this->parseArgument($element->elementValue),
22+
];
23+
24+
$lastValue = $element->elementValue;
25+
}
26+
}
27+
28+
if ($node->closeParenOrBracket instanceof MissingToken) {
29+
$this->handleMissingArrayCloseToken($array, $lastValue);
30+
}
31+
32+
return [
33+
'type' => 'array',
34+
'value' => $array,
35+
];
36+
37+
return $this->context;
38+
}
39+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Parser\Parsers;
4+
5+
use App\Parser\Parse;
6+
use Microsoft\PhpParser\Node\Expression\AssignmentExpression;
7+
8+
class AssignmentExpressionParser extends AbstractParser
9+
{
10+
public function parse(AssignmentExpression $node)
11+
{
12+
// parseArgument in walker
13+
// StringLiteral
14+
// ArrayCreationExpression
15+
// AnonymousFunctionCreationExpression
16+
// ArrowFunctionCreationExpression
17+
// ObjectCreationExpression
18+
$this->context->addVariable(
19+
$node->leftOperand->getText(),
20+
Parse::parse($node->rightOperand)?->toArray() ?? [
21+
'type' => 'unknown',
22+
'value' => $node->rightOperand->getText(),
23+
],
24+
);
25+
26+
return $this->context;
27+
}
28+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace App\Parser\Parsers;
4+
5+
use App\Parser\SourceFile;
6+
use Microsoft\PhpParser\Node\Expression\CallExpression;
7+
use Microsoft\PhpParser\Node\Expression\MemberAccessExpression;
8+
use Microsoft\PhpParser\Node\Expression\ScopedPropertyAccessExpression;
9+
use Microsoft\PhpParser\Node\QualifiedName;
10+
11+
class CallExpressionParser extends AbstractParser
12+
{
13+
use InitsNewContext;
14+
15+
public function parse(CallExpression $node)
16+
{
17+
return $this->context;
18+
19+
// $lastChild = null;
20+
21+
// foreach ($node->getDescendantNodes() as $child) {
22+
// if ($child instanceof QualifiedName) {
23+
// if ($lastChild instanceof ScopedPropertyAccessExpression || $lastChild instanceof MemberAccessExpression) {
24+
// $this->context->classUsed ??= (string) $child->getResolvedName();
25+
// }
26+
// }
27+
28+
// if ($child instanceof Variable) {
29+
// if ($this->context->classUsed) {
30+
// continue;
31+
// }
32+
33+
// if ($child->getName() === 'this') {
34+
// $propName = $child->getParent()->memberName->getFullText($this->sourceFile->getFileContents());
35+
36+
// $result = $this->context->searchForProperty($propName);
37+
38+
// if ($result) {
39+
// $this->context->classUsed = $result['types'][0] ?? null;
40+
// }
41+
42+
// continue;
43+
// }
44+
45+
// $varName = $child->getName();
46+
47+
// $result = $this->context->searchForVar($varName);
48+
49+
// if ($result) {
50+
// $this->context->classUsed = $result['value'] ?? $result['types'][0] ?? null;
51+
// }
52+
// }
53+
54+
// $lastChild = $child;
55+
// }
56+
57+
// if ($node && property_exists($node, 'expression') && property_exists($node->expression, 'argumentExpressionList') && $node?->expression?->argumentExpressionList) {
58+
// $lastArgExpression = null;
59+
// $lastMethodArg = null;
60+
61+
// foreach ($node->expression->argumentExpressionList->getChildNodesAndTokens() as $el) {
62+
// if ($el instanceof Token) {
63+
// continue;
64+
// }
65+
66+
// $lastMethodArg = $this->parseArgument($el->expression ?? null);
67+
// $this->context->methodExistingArgs[] = $lastMethodArg;
68+
// $lastArgExpression = $el;
69+
70+
// $this->increaseParamIndex($el);
71+
// }
72+
73+
// if ($lastMethodArg['type'] === 'closure') {
74+
// $this->debug('closure as last arg', $lastArgExpression::class);
75+
// $this->nextNodeToWalk = $lastArgExpression->expression;
76+
// }
77+
78+
// if ($this->postArgumentParsingCallback) {
79+
// ($this->postArgumentParsingCallback)();
80+
// $this->postArgumentParsingCallback = null;
81+
// }
82+
// }
83+
84+
// return $this->context;
85+
}
86+
}

0 commit comments

Comments
 (0)