Skip to content

Commit e8ee6a2

Browse files
authored
Refactoring descriptor pool (#12)
1 parent 6794de1 commit e8ee6a2

7 files changed

Lines changed: 307 additions & 82 deletions

File tree

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"amphp/byte-stream": "^2.1",
2525
"nette/php-generator": "4.2.1",
2626
"thesis/package-version": "0.1.2",
27-
"thesis/protobuf": "^0.1.3",
27+
"thesis/protobuf": "^0.1.6",
2828
"thesis/protobuf-compiler-types": "0.1.0",
2929
"thesis/protobuf-descriptor-types": "0.1.0"
3030
},

src/Plugin/ClassLikeGenerator.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public function __construct(
3232
$this->grpc = new Generator\GrpcGenerator(
3333
$namespacer,
3434
$graph,
35+
$index,
3536
$package,
3637
);
3738
$this->proto = new Generator\ProtoGenerator(
@@ -78,11 +79,25 @@ public function generateGrpcServer(Parser\ServiceDescriptor $service): iterable
7879
}
7980
}
8081

82+
/**
83+
* @param list<string> $dependencies
84+
*/
8185
public function generateDescriptorMetadataRegistry(
8286
NameIndex $index,
87+
string $filename,
88+
array $dependencies,
8389
string $descriptorName,
8490
string $buffer,
8591
): CodeGeneratorResponse\File {
86-
return $this->files->create($this->metadata->generate($index, $descriptorName, $buffer), $descriptorName);
92+
return $this->files->create(
93+
$this->metadata->generate(
94+
$index,
95+
$filename,
96+
$dependencies,
97+
$descriptorName,
98+
$buffer,
99+
),
100+
$descriptorName,
101+
);
87102
}
88103
}

src/Plugin/Compiler.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ private function doGenerate(
9797

9898
yield $generator->generateDescriptorMetadataRegistry(
9999
$index,
100+
$proto->name,
101+
$proto->dependencies,
100102
$descriptorName,
101103
$this->encoder->encode($proto->file),
102104
);

src/Plugin/Generator/DescriptorMetadataRegistryGenerator.php

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Nette\PhpGenerator\ClassType;
88
use Nette\PhpGenerator\Constant;
99
use Nette\PhpGenerator\Literal;
10+
use Nette\PhpGenerator\Method;
1011
use Nette\PhpGenerator\Parameter;
1112
use Nette\PhpGenerator\PhpNamespace;
1213
use Thesis\Protoc\Plugin\NameIndex;
@@ -20,8 +21,13 @@ public function __construct(
2021
private PhpNamespacer $namespacer,
2122
) {}
2223

24+
/**
25+
* @param list<string> $dependencies
26+
*/
2327
public function generate(
2428
NameIndex $index,
29+
string $filename,
30+
array $dependencies,
2531
string $className,
2632
string $buffer,
2733
): PhpNamespace {
@@ -44,39 +50,84 @@ public function generate(
4450
$namespace->add($classType);
4551

4652
$namespace->addUse('Thesis\Protobuf\Pool');
53+
$namespace->addUse('Thesis\Protobuf\Pool\File');
4754
$namespace->addUse(\Override::class);
4855

49-
$classType
56+
$method = $classType
5057
->addMethod('register')
5158
->setPublic()
5259
->setParameters([
5360
new Parameter('pool')->setType('Pool\Registry'),
5461
])
5562
->setReturnType('void')
56-
->addAttribute(\Override::class)
57-
->setBody(
58-
\sprintf(
63+
->addAttribute(\Override::class);
64+
65+
$method->addBody('$pool->add(Pool\Descriptor::base64(self::DESCRIPTOR_BUFFER), new File(');
66+
$method->addBody(' name: ?,', [$filename]);
67+
68+
self::pushParameter($method, 'dependencies', $dependencies);
69+
self::pushParameter(
70+
$method,
71+
'messages',
72+
$index->messageTypes,
73+
static fn(string $type, string $fqcn) => new Literal(
74+
\sprintf("new File\\MessageDescriptor('%s', \\%s::class)", $type, $fqcn),
75+
),
76+
);
77+
self::pushParameter($method, 'enums', $index->enumTypes, static fn(string $type, string $fqcn) => new Literal(
78+
\sprintf("new File\\EnumDescriptor('%s', \\%s::class)", $type, $fqcn),
79+
));
80+
self::pushParameter(
81+
$method,
82+
'services',
83+
$index->grpc,
84+
static fn(string $type, object $service) => new Literal(
85+
vsprintf(
5986
<<<'PHP'
60-
$pool->add(Pool\Descriptor::base64(self::DESCRIPTOR_BUFFER), [
61-
%s,
62-
]);
87+
new File\ServiceDescriptor(
88+
name: '%s',
89+
clientFqcn: %s,
90+
serverFqcn: %s,
91+
)
6392
PHP,
64-
implode(",\n\t", array_fill(0, \count($index), '?')),
65-
),
66-
array_merge(
67-
array_map(
68-
static fn(string $type, string $fqcn) => new Literal(\sprintf("'%s' => new Pool\\MessageMetadata(\\%s::class)", $type, $fqcn)),
69-
array_keys($index->messageTypes),
70-
array_values($index->messageTypes),
71-
),
72-
array_map(
73-
static fn(string $type, string $fqcn) => new Literal(\sprintf("'%s' => new Pool\\EnumMetadata(\\%s::class)", $type, $fqcn)),
74-
array_keys($index->enumTypes),
75-
array_values($index->enumTypes),
76-
),
93+
[
94+
$type,
95+
isset($service->client) ? "\\{$service->client}::class" : 'null',
96+
isset($service->server) ? "\\{$service->server}::class" : 'null',
97+
],
7798
),
78-
);
99+
),
100+
);
101+
102+
$method->addBody('));');
79103

80104
return $namespace;
81105
}
106+
107+
/**
108+
* @template K of array-key
109+
* @template V
110+
* @template R
111+
* @param non-empty-string $name
112+
* @param array<K, V> $items
113+
* @param ?\Closure(K, V): R $format
114+
*/
115+
private static function pushParameter(
116+
Method $method,
117+
string $name,
118+
array $items,
119+
?\Closure $format = null,
120+
): void {
121+
$format ??= static fn(mixed $key, mixed $value) => $value;
122+
123+
if ($items !== []) {
124+
$method->addBody(" {$name}: [");
125+
126+
foreach ($items as $key => $value) {
127+
$method->addBody(' ?,', [$format($key, $value)]);
128+
}
129+
130+
$method->addBody(' ],');
131+
}
132+
}
82133
}

src/Plugin/Generator/GrpcGenerator.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Nette\PhpGenerator\PhpNamespace;
1212
use Nette\PhpGenerator\PromotedParameter;
1313
use Thesis\Protoc\Plugin\Dependency;
14+
use Thesis\Protoc\Plugin\NameIndex;
1415
use Thesis\Protoc\Plugin\Naming;
1516
use Thesis\Protoc\Plugin\Parser;
1617

@@ -22,6 +23,7 @@
2223
public function __construct(
2324
private PhpNamespacer $namespacer,
2425
private Dependency\Graph $graph,
26+
private NameIndex $index,
2527
private ?string $package = null,
2628
) {}
2729

@@ -31,6 +33,8 @@ public function generateClient(Parser\ServiceDescriptor $service): PhpNamespace
3133

3234
$name = \sprintf('%sClient', Naming::pascalCase($service->name));
3335

36+
$this->index->addClient(($this->package !== null ? "{$this->package}." : '') . $service->path, "{$namespace->getName()}\\{$name}");
37+
3438
$classType = new ClassType($name)
3539
->setFinal()
3640
->setReadOnly()
@@ -197,10 +201,12 @@ public function generateServer(Parser\ServiceDescriptor $service): PhpNamespace
197201
{
198202
$namespace = $this->namespacer->create($service->path);
199203

200-
$interfaceType = new InterfaceType(\sprintf('%sServer', Naming::pascalCase($service->name)))
204+
$interfaceType = new InterfaceType($name = \sprintf('%sServer', Naming::pascalCase($service->name)))
201205
->addComment('@api')
202206
->addComment($service->comment !== null ? "\n{$service->comment}" : '');
203207

208+
$this->index->addServer(($this->package !== null ? "{$this->package}." : '') . $service->path, "{$namespace->getName()}\\{$name}");
209+
204210
$namespace->add($interfaceType);
205211

206212
if ($service->methods === []) {

src/Plugin/NameIndex.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@
66

77
/**
88
* @api
9+
* @phpstan-type GrpcService = object{client: ?string, server: ?string}
910
*/
10-
final class NameIndex implements \Countable
11+
final class NameIndex
1112
{
1213
/** @var array<string, string> */
1314
public private(set) array $messageTypes = [];
1415

1516
/** @var array<string, string> */
1617
public private(set) array $enumTypes = [];
1718

19+
/** @var array<string, GrpcService>
20+
*/
21+
public private(set) array $grpc = [];
22+
1823
public function addMessageType(string $type, string $fqcn): void
1924
{
2025
$this->messageTypes[$type] = $fqcn;
@@ -25,14 +30,30 @@ public function addEnumType(string $type, string $fqcn): void
2530
$this->enumTypes[$type] = $fqcn;
2631
}
2732

28-
public function empty(): bool
33+
public function addClient(string $type, string $fqcn): void
34+
{
35+
$this->grpc[$type] ??= new class {
36+
public function __construct(
37+
public ?string $client = null,
38+
public ?string $server = null,
39+
) {}
40+
};
41+
$this->grpc[$type]->client = $fqcn; // @phpstan-ignore assign.propertyReadOnly
42+
}
43+
44+
public function addServer(string $type, string $fqcn): void
2945
{
30-
return $this->messageTypes === [] && $this->enumTypes === [];
46+
$this->grpc[$type] ??= new class {
47+
public function __construct(
48+
public ?string $client = null,
49+
public ?string $server = null,
50+
) {}
51+
};
52+
$this->grpc[$type]->server = $fqcn; // @phpstan-ignore assign.propertyReadOnly
3153
}
3254

33-
#[\Override]
34-
public function count(): int
55+
public function empty(): bool
3556
{
36-
return \count($this->messageTypes) + \count($this->enumTypes);
57+
return $this->messageTypes === [] && $this->enumTypes === [] && $this->grpc === [];
3758
}
3859
}

0 commit comments

Comments
 (0)