gen_stub.php support for @cvalue DocBlock annotation for backed enum cases
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- C
- Star
- 40.4k
- Fork
- 8.1k
- Merge trung bình
- 2 ngày 13 giờ
- Pull request đã merge (30 ngày)
- 96
Mô tả
Description
I am trying to use a *.stub.php file to create an *_arginfo.h file which will bind third-party c enum values to a PHP backed enum.
My naïve approach was:
enum MyEnum: int {
/**
* @var int
* @cvalue MY_C_ENUM_VALUE1
*/
case Value1 = UNKNOWN;
}
but that did not work.
A rather verbose and unintuitive workaround is:
enum MyEnum: int {
/**
* @var int
* @cvalue MY_C_ENUM_VALUE1
*/
private const VALUE1 = UNKNOWN
case Value1 = MyEnum::VALUE1;
}
Ideally, the type is inferred from the enum declaration but using @var works for me.
I'm using the 8.4 branch at commit 5295fc07d5985d962df342f65d66fc0fb89f5edb for my tests.
@kocsismate included because you are a volunteer for gen_stub.php.
Please find below a very simple implementation of what I try to achieve. While it does what I want it is not extensively tested and has probably side effects. If this is worth a PR please let me know. Any guidance on missing bits and pieces is very welcome. Obviously, tests have to be added.
---
build/gen_stub.php | 62 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 58 insertions(+), 4 deletions(-)
diff --git a/build/gen_stub.php b/build/gen_stub.php
index f1d8b43862e..219c9af2cc4 100755
--- a/build/gen_stub.php
+++ b/build/gen_stub.php
@@ -3096,10 +3096,19 @@ public function __clone()
class EnumCaseInfo {
public string $name;
public ?Expr $value;
+ public ?SimpleType $constType;
+ public ?string $cConstName;
- public function __construct(string $name, ?Expr $value) {
+ public function __construct(
+ string $name,
+ ?Expr $value,
+ ?SimpleType $constType,
+ ?string $cConstName
+ ) {
$this->name = $name;
$this->value = $value;
+ $this->constType = $constType;
+ $this->cConstName = $cConstName;
}
/** @param array<string, ConstInfo> $allConstInfos */
@@ -3108,7 +3117,12 @@ public function getDeclaration(array $allConstInfos): string {
if ($this->value === null) {
$code = "\n\tzend_enum_add_case_cstr(class_entry, \"$escapedName\", NULL);\n";
} else {
- $value = EvaluatedValue::createFromExpression($this->value, null, null, $allConstInfos);
+ $value = EvaluatedValue::createFromExpression(
+ $this->value,
+ $this->constType,
+ $this->cConstName,
+ $allConstInfos
+ );
$zvalName = "enum_case_{$escapedName}_value";
$code = "\n" . $value->initializeZval($zvalName);
@@ -4444,6 +4458,43 @@ function parseConstLike(
);
}
+function parseEnumCase(
+ string $name,
+ ?Expr $value,
+ array $comments
+): EnumCaseInfo {
+ $cConstName = null;
+ $phpDocType = null;
+ if ($comments) {
+ $tags = parseDocComments($comments);
+ foreach ($tags as $tag) {
+ if ($tag->name === 'var') {
+ $phpDocType = $tag->getType();
+ } elseif ($tag->name === 'cvalue') {
+ $cConstName = $tag->value;
+ }
+ }
+ }
+
+ $constPhpDocType = $phpDocType
+ ? SimpleType::fromString($phpDocType)
+ : null;
+
+ // Toto: infer type from enum declaration
+ if ($cConstName && $constPhpDocType
+ && !($constPhpDocType->name === 'int' || $constPhpDocType->name === 'string')
+ ) {
+ throw new Exception("Backed enums must be of type int or string");
+ }
+
+ return new EnumCaseInfo(
+ $name,
+ $value,
+ $constPhpDocType,
+ $cConstName
+ );
+}
+
/**
* @param array<int, array<int, AttributeGroup> $attributes
*/
@@ -4810,8 +4861,11 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac
$fileInfo->getMinimumPhpVersionIdCompatibility()
);
} else if ($classStmt instanceof Stmt\EnumCase) {
- $enumCaseInfos[] = new EnumCaseInfo(
- $classStmt->name->toString(), $classStmt->expr);
+ $enumCaseInfos[] = parseEnumCase(
+ $classStmt->name->toString(),
+ $classStmt->expr,
+ $classStmt->getComments()
+ );
} else {
throw new Exception("Not implemented {$classStmt->getType()}");
}
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu trong build/gen_stub.php với EnumCaseInfo, phần xử lý enum case trong handleStatements(), cùng các luồng parsing DocBlock và EvaluatedValue hiện có. Xem xét cách tiếp cận parseEnumCase được đề xuất và thêm các kiểm thử cho @cvalue trên các enum case backed. Hoàn tất khi quá trình xử lý stub tạo ra arginfo liên kết các giá trị enum C được ghi nhận trong tài liệu mà không cần workaround bằng hằng private.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- php
- Lĩnh vực
- build-system, tooling
- Loại issue
- Tính năng
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 42/100