Ну что, за два дня готов пакет для построения AST для protobuf
Чем он крут? Можно взять proto-файлы, превратить их в дерево PHP-объектов (AST) и далее сгенерировать свои DTO-классы. Например:
syntax = "proto3";
package examplepb;
message Person {
// Unique identifier for the person.
uint64 id = 1 [(validate.rules).uint64.gt = 999];
// Email address will be used for communication.
string email = 2 [(validate.rules).string.email = true];
// Full name of the person.
string name = 3 [(validate.rules).string = {
pattern: "^[A-Za-z]+( [A-Za-z]+)*$",
max_bytes: 256
}];
// Home location of the person.
Location home = 4 [(validate.rules).message.required = true];
message Location {
double lat = 1 [(validate.rules).double = {gte: -90, lte: 90}];
double lng = 2 [(validate.rules).double = {gte: -180, lte: 180}];
}
}
service ExampleService {
// Create a new person.
rpc CreatePerson(Person) returns (Person) {
option (google.api.http) = {
post: "/v1/persons"
body: "*"
};
}
}
Превратим в:
use Symfony\Component\Validator\Constraints as Assert;
final readonly class Person
{
public function __construct(
/** Unique identifier for the person. */
#[Assert\GreaterThan(value: 999)]
public int $id,
/** Email address will be used for communication. */
#[Assert\Email]
public string $email,
/** Full name of the person. */
#[Assert\Regex(pattern: '^[A-Za-z]+( [A-Za-z]+)*$'), Assert\Length(max: 256, charset: '8bit')]
public string $name,
/** Home location of the person. */
#[Assert\NotNull]
public Location $home,
) {
}
}
use Symfony\Component\Validator\Constraints as Assert;
final readonly class Location
{
public function __construct(
#[Assert\GreaterThanOrEqual(value: -90), Assert\LessThanOrEqual(value: 90)]
public float $lat,
#[Assert\GreaterThanOrEqual(value: -180), Assert\LessThanOrEqual(value: 180)]
public float $lng,
) {
}
}
<?php
declare(strict_types=1);
namespace Internal;
use App\Grpc\Service;
use OpenApi\Annotations as OA;
use Spiral\RoadRunner\GRPC\ContextInterface;
#[Service(name: 'ExampleService', package: 'examplepb')]
interface ExampleServiceInterface
{
/**
* Create a new person.
*/
#[OA\Post(path: '/v1/persons', tags: ['CreatePerson'])]
#[OA\RequestBody(path: '*', tags: ['CreatePerson'])]
public function CreatePerson(ContextInterface $ctx, Person $in): Person;
}
Что умеет:
1. Строить дерево. Понимает весь синтаксис, что я смог найти.
2. Привязывать комментарии к нодам. Например комментарий над полем будет в ноде поля. Комментарий к option будет в его ноде. И т.д.
3. Дока есть.
Что не умеет:
ХЗ что. призываю потестить и улучшить желающих.
Прогнал свой проект с > 100 proto файлов, все спарсил.
P.s. Ах да, забыл сказать, что эти DTO сгененировал мой другой пакет, который уже умеет работать с AST. Сделан на коленке, поэтому еще не выкладывал.