Skip to content

Commit cf3f639

Browse files
committed
FEAT: add first draft of autogenerated class diagram
This is a first hack to implement a new feature to generate class diagrams based on user defined queries. And example of such page is: ``` Element Structure ================= .. phpdoc:class-diagram:: [?(@.namespace starts_with "\phpDocumentor\Descriptor")] ``` More features need to be implemented, but this starts as a POC to see what we actually need to complete this feature.
1 parent fecff14 commit cf3f639

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

src/AST/Comparison.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public function visit(Executor $param, $currentObject, $root): bool
3030
{
3131
return match ($this->operator) {
3232
'==' => $param->evaluateEqualsComparison($root, $currentObject, $this->left, $this->right),
33+
'!=' => $param->evaluateNotEqualsComparison($root, $currentObject, $this->left, $this->right),
34+
'starts_with' => $param->evaluateStartsWithComparison($root, $currentObject, $this->left, $this->right),
3335
default => throw new InvalidArgumentException(),
3436
};
3537
}

src/Executor.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use function is_object;
3232
use function is_string;
3333
use function iterator_to_array;
34+
use function str_starts_with;
3435
use function strrpos;
3536
use function substr;
3637

@@ -49,8 +50,12 @@ public function evaluate(QueryNode $query, mixed $currentElement, mixed $rootEle
4950
return $query->visit($this, $currentElement, $rootElement);
5051
}
5152

52-
public function evaluateEqualsComparison(mixed $root, mixed $currentObject, QueryNode $left, QueryNode $right): bool
53-
{
53+
public function evaluateEqualsComparison(
54+
mixed $root,
55+
mixed $currentObject,
56+
QueryNode $left,
57+
QueryNode $right,
58+
): bool {
5459
$leftValue = $this->toValue($this->evaluate($left, $currentObject, $root));
5560
$rightValue = $this->toValue($this->evaluate($right, $currentObject, $root));
5661

@@ -61,6 +66,27 @@ public function evaluateEqualsComparison(mixed $root, mixed $currentObject, Quer
6166
return $leftValue === $rightValue;
6267
}
6368

69+
public function evaluateNotEqualsComparison(
70+
mixed $root,
71+
mixed $currentObject,
72+
QueryNode $left,
73+
QueryNode $right,
74+
): bool {
75+
return ! $this->evaluateEqualsComparison($root, $currentObject, $left, $right);
76+
}
77+
78+
public function evaluateStartsWithComparison(
79+
mixed $root,
80+
mixed $currentObject,
81+
QueryNode $left,
82+
QueryNode $right,
83+
): bool {
84+
$leftValue = $this->toValue($this->evaluate($left, $currentObject, $root));
85+
$rightValue = $this->toValue($this->evaluate($right, $currentObject, $root));
86+
87+
return str_starts_with((string) $leftValue, (string) $rightValue);
88+
}
89+
6490
/**
6591
* @param Generator<mixed>|mixed $value
6692
*

src/Parser/ParserBuilder.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ private static function expression(): Parser
9696
{
9797
$operator = choice(
9898
string('=='),
99+
string('!='),
100+
string('starts_with'),
99101
);
100102

101103
$value = choice(

tests/unit/Parser/ParserBuilderTest.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace phpDocumentor\JsonPath\Parser;
1515

16+
use Generator;
1617
use Parsica\Parsica\Parser;
1718
use phpDocumentor\JsonPath\AST\Comparison;
1819
use phpDocumentor\JsonPath\AST\CurrentNode;
@@ -101,9 +102,10 @@ public function testRootFieldChildAccess(): void
101102
);
102103
}
103104

104-
public function testFilterExpressionCurrentObjectPropertyEquals(): void
105+
/** @dataProvider operatorProvider */
106+
public function testFilterExpression(string $operator): void
105107
{
106-
$result = $this->parser->tryString('$.store.books[?(@.title == "phpDoc")]');
108+
$result = $this->parser->tryString('$.store.books[?(@.title ' . $operator . ' "phpDoc")]');
107109
self::assertEquals(
108110
new Path([
109111
new RootNode(),
@@ -119,7 +121,7 @@ public function testFilterExpressionCurrentObjectPropertyEquals(): void
119121
new CurrentNode(),
120122
new FieldAccess(new FieldName('title')),
121123
]),
122-
'==',
124+
$operator,
123125
new Value(
124126
'phpDoc',
125127
),
@@ -130,6 +132,20 @@ public function testFilterExpressionCurrentObjectPropertyEquals(): void
130132
);
131133
}
132134

135+
/** @return Generator<string, string> */
136+
public static function operatorProvider(): Generator
137+
{
138+
$operators = [
139+
'==',
140+
'!=',
141+
'starts_with',
142+
];
143+
144+
foreach ($operators as $operator) {
145+
yield $operator => [$operator];
146+
}
147+
}
148+
133149
public function testFilterExpressionCurrentObjectProperyWildCard(): void
134150
{
135151
$result = $this->parser->tryString('$.store.books[?(@.* == "phpDoc")]');

0 commit comments

Comments
 (0)