Skip to content

Commit a831698

Browse files
committed
Generate method entries from stubs
1 parent 3709e74 commit a831698

File tree

6 files changed

+450
-177
lines changed

6 files changed

+450
-177
lines changed

Zend/zend_API.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ typedef struct _zend_fcall_info_cache {
8585
#define ZEND_DEP_ME(classname, name, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##name, arg_info, flags | ZEND_ACC_DEPRECATED)
8686
#define ZEND_ABSTRACT_ME(classname, name, arg_info) ZEND_RAW_FENTRY(#name, NULL, arg_info, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
8787
#define ZEND_MALIAS(classname, name, alias, arg_info, flags) ZEND_RAW_FENTRY(#name, zim_##classname##_##alias, arg_info, flags)
88-
#define ZEND_ME_MAPPING(name, func_name, arg_types, flags) ZEND_RAW_FENTRY(#name, zif_##func_name, arg_types, flags)
88+
#define ZEND_ME_MAPPING(name, func_name, arg_info, flags) ZEND_RAW_FENTRY(#name, zif_##func_name, arg_info, flags)
8989

9090
#define ZEND_NS_FENTRY(ns, zend_name, name, arg_info, flags) ZEND_RAW_FENTRY(ZEND_NS_NAME(ns, #zend_name), name, arg_info, flags)
9191

build/gen_stub.php

Lines changed: 163 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -324,29 +324,43 @@ public function equals(ReturnInfo $other): bool {
324324
}
325325

326326
class FuncInfo {
327-
/** @var string */
328-
public $name;
329-
/** @var ?string */
330-
public $className;
331-
/** @var ?string */
332-
public $alias;
333-
/** @var bool */
334-
public $isDeprecated;
327+
public string $name;
328+
public ?string $className;
329+
public ?string $visibility;
330+
public bool $isAbstract;
331+
public bool $isStatic;
332+
public bool $isFinal;
333+
public ?string $mapping;
334+
public ?string $alias;
335+
public bool $isDeprecated;
335336
/** @var ArgInfo[] */
336-
public $args;
337-
/** @var ReturnInfo */
338-
public $return;
339-
/** @var int */
340-
public $numRequiredArgs;
341-
/** @var string|null */
342-
public $cond;
337+
public array $args;
338+
public ReturnInfo $return;
339+
public int $numRequiredArgs;
340+
public ?string $cond;
343341

344342
public function __construct(
345-
string $name, ?string $className, ?string $alias, bool $isDeprecated, array $args, ReturnInfo $return,
346-
int $numRequiredArgs, ?string $cond
343+
string $name,
344+
?string $className,
345+
?string $visibility,
346+
bool $isAbstract,
347+
bool $isStatic,
348+
bool $isFinal,
349+
?string $mapping,
350+
?string $alias,
351+
bool $isDeprecated,
352+
array $args,
353+
ReturnInfo $return,
354+
int $numRequiredArgs,
355+
?string $cond
347356
) {
348357
$this->name = $name;
349358
$this->className = $className;
359+
$this->visibility = $visibility;
360+
$this->isAbstract = $isAbstract;
361+
$this->isStatic = $isStatic;
362+
$this->isFinal = $isFinal;
363+
$this->mapping = $mapping;
350364
$this->alias = $alias;
351365
$this->isDeprecated = $isDeprecated;
352366
$this->args = $args;
@@ -458,10 +472,19 @@ function parseDocComment(DocComment $comment): array {
458472
}
459473

460474
function parseFunctionLike(
461-
PrettyPrinterAbstract $prettyPrinter, string $name, ?string $className, Node\FunctionLike $func, ?string $cond
475+
PrettyPrinterAbstract $prettyPrinter,
476+
string $name,
477+
?string $className,
478+
?string $visibility,
479+
bool $isAbstract,
480+
bool $isStatic,
481+
bool $isFinal,
482+
Node\FunctionLike $func,
483+
?string $cond
462484
): FuncInfo {
463485
$comment = $func->getDocComment();
464486
$paramMeta = [];
487+
$mapping = null;
465488
$alias = null;
466489
$isDeprecated = false;
467490
$haveDocReturnType = false;
@@ -475,6 +498,8 @@ function parseFunctionLike(
475498
$paramMeta[$varName] = [];
476499
}
477500
$paramMeta[$varName]['preferRef'] = true;
501+
} else if ($tag->name === 'mapping') {
502+
$mapping = $tag->getValue();
478503
} else if ($tag->name === 'alias') {
479504
$alias = $tag->getValue();
480505
} else if ($tag->name === 'deprecated') {
@@ -539,8 +564,24 @@ function parseFunctionLike(
539564

540565
$return = new ReturnInfo(
541566
$func->returnsByRef(),
542-
$returnType ? Type::fromNode($returnType) : null);
543-
return new FuncInfo($name, $className, $alias, $isDeprecated, $args, $return, $numRequiredArgs, $cond);
567+
$returnType ? Type::fromNode($returnType) : null
568+
);
569+
570+
return new FuncInfo(
571+
$name,
572+
$className,
573+
$visibility,
574+
$isAbstract,
575+
$isStatic,
576+
$isFinal,
577+
$mapping,
578+
$alias,
579+
$isDeprecated,
580+
$args,
581+
$return,
582+
$numRequiredArgs,
583+
$cond
584+
);
544585
}
545586

546587
function handlePreprocessorConditions(array &$conds, Stmt $stmt): ?string {
@@ -622,7 +663,18 @@ function parseStubFile(string $fileName): FileInfo {
622663
}
623664

624665
if ($stmt instanceof Stmt\Function_) {
625-
$funcInfos[] = parseFunctionLike($prettyPrinter, $stmt->name->toString(), null, $stmt, $cond);
666+
$funcInfos[] = parseFunctionLike(
667+
$prettyPrinter,
668+
$stmt->name->toString(),
669+
null,
670+
null,
671+
false,
672+
false,
673+
false,
674+
$stmt,
675+
$cond
676+
);
677+
626678
continue;
627679
}
628680

@@ -639,8 +691,22 @@ function parseStubFile(string $fileName): FileInfo {
639691
throw new Exception("Not implemented {$classStmt->getType()}");
640692
}
641693

694+
$visibility = $classStmt->isPublic() ? "public" : ($classStmt->isProtected() ? "protected" : "private");
695+
$isAbstract = $classStmt->isAbstract();
696+
$isStatic = $classStmt->isStatic();
697+
$isFinal = $classStmt->isFinal();
698+
642699
$methodInfos[] = parseFunctionLike(
643-
$prettyPrinter, $classStmt->name->toString(), $className, $classStmt, $cond);
700+
$prettyPrinter,
701+
$classStmt->name->toString(),
702+
$className,
703+
$visibility,
704+
$isAbstract,
705+
$isStatic,
706+
$isFinal,
707+
$classStmt,
708+
$cond
709+
);
644710
}
645711

646712
$classInfos[] = new ClassInfo($className, $methodInfos);
@@ -778,8 +844,6 @@ function generateCodeWithConditions(
778844
}
779845

780846
function generateArgInfoCode(FileInfo $fileInfo): string {
781-
$funcInfos = $fileInfo->funcInfos;
782-
783847
$code = "/* This is a generated file, edit the .stub.php file instead. */\n";
784848
$generatedFuncInfos = [];
785849
$code .= generateCodeWithConditions(
@@ -801,21 +865,80 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
801865
);
802866

803867
if ($fileInfo->generateFunctionEntries) {
804-
$code .= "\n\n";
805-
$generatedDeclarations = [];
806-
$code .= generateCodeWithConditions($funcInfos, "", function(FuncInfo $funcInfo) use (&$generatedDeclarations) {
807-
$name = $funcInfo->alias ?? $funcInfo->name;
808-
$key = "$name|$funcInfo->cond";
809-
if (isset($generatedDeclarations[$key])) {
810-
return null;
868+
$code .= generateFunctionEntry(null, $fileInfo->funcInfos);
869+
870+
foreach ($fileInfo->classInfos as $classInfo) {
871+
$code .= generateFunctionEntry($classInfo->name, $classInfo->funcInfos);
872+
}
873+
}
874+
875+
return $code;
876+
}
877+
878+
/**
879+
* @param FuncInfo[] $funcInfos
880+
*/
881+
function generateFunctionEntry(?string $className, array $funcInfos): string {
882+
$code = "\n\n";
883+
$generatedDeclarations = [];
884+
$code .= generateCodeWithConditions($funcInfos, "", function(FuncInfo $funcInfo) use (&$generatedDeclarations) {
885+
$name = $funcInfo->alias ?? ($funcInfo->mapping ?? $funcInfo->name);
886+
$key = "$name|$funcInfo->cond";
887+
if (isset($generatedDeclarations[$key])) {
888+
return null;
889+
}
890+
891+
$generatedDeclarations[$key] = true;
892+
893+
if ($funcInfo->isAbstract) {
894+
return "";
895+
}
896+
897+
if ($funcInfo->className && !$funcInfo->mapping) {
898+
return "ZEND_METHOD($funcInfo->className, $name);\n";
899+
}
900+
901+
return "ZEND_FUNCTION($name);\n";
902+
});
903+
904+
$functionEntryName = $className ? "class_{$className}_methods" : "ext_functions";
905+
906+
$code .= "\n\nstatic const zend_function_entry {$functionEntryName}[] = {\n";
907+
$code .= generateCodeWithConditions($funcInfos, "", function(FuncInfo $funcInfo) {
908+
if ($funcInfo->className) {
909+
$flags = sprintf("ZEND_ACC_%s", strtoupper($funcInfo->visibility));
910+
if ($funcInfo->isStatic) {
911+
$flags .= "|ZEND_ACC_STATIC";
912+
}
913+
if ($funcInfo->isFinal) {
914+
$flags .= "|ZEND_ACC_FINAL";
915+
}
916+
if ($funcInfo->isAbstract) {
917+
$flags .= "|ZEND_ACC_ABSTRACT";
918+
}
919+
if ($funcInfo->isDeprecated) {
920+
$flags .= "|ZEND_ACC_DEPRECATED";
921+
}
922+
923+
if ($funcInfo->alias) {
924+
return sprintf(
925+
"\tZEND_MALIAS(%s, %s, %s, %s, %s)\n",
926+
$funcInfo->className, $funcInfo->name, $funcInfo->alias, $funcInfo->getArgInfoName(), $flags
927+
);
811928
}
812929

813-
$generatedDeclarations[$key] = true;
814-
return "ZEND_FUNCTION($name);\n";
815-
});
930+
if ($funcInfo->mapping) {
931+
return sprintf(
932+
"\tZEND_ME_MAPPING(%s, %s, %s, %s)\n",
933+
$funcInfo->name, $funcInfo->mapping, $funcInfo->getArgInfoName(), $flags
934+
);
935+
}
816936

817-
$code .= "\n\nstatic const zend_function_entry ext_functions[] = {\n";
818-
$code .= generateCodeWithConditions($fileInfo->funcInfos, "", function(FuncInfo $funcInfo) {
937+
return sprintf(
938+
"\tZEND_ME(%s, %s, %s, %s)\n",
939+
$funcInfo->className, $funcInfo->name, $funcInfo->getArgInfoName(), $flags
940+
);
941+
} else {
819942
if ($funcInfo->alias) {
820943
return sprintf(
821944
"\tZEND_FALIAS(%s, %s, %s)\n",
@@ -828,10 +951,10 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
828951
}
829952

830953
return sprintf("\tZEND_FE(%s, %s)\n", $funcInfo->name, $funcInfo->getArgInfoName());
831-
});
832-
$code .= "\tZEND_FE_END\n";
833-
$code .= "};\n";
834-
}
954+
}
955+
});
956+
$code .= "\tZEND_FE_END\n";
957+
$code .= "};\n";
835958

836959
return $code;
837960
}

ext/date/php_date.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -147,26 +147,6 @@ static const zend_function_entry date_funcs_timezone[] = {
147147
PHP_FE_END
148148
};
149149

150-
static const zend_function_entry date_funcs_interval[] = {
151-
PHP_ME(DateInterval, __construct, arginfo_class_DateInterval___construct, ZEND_ACC_PUBLIC)
152-
PHP_ME(DateInterval, __wakeup, arginfo_class_DateInterval___wakeup, ZEND_ACC_PUBLIC)
153-
PHP_ME(DateInterval, __set_state, arginfo_class_DateInterval___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
154-
PHP_ME_MAPPING(format, date_interval_format, arginfo_class_DateInterval_format, 0)
155-
PHP_ME_MAPPING(createFromDateString, date_interval_create_from_date_string, arginfo_class_DateInterval_createFromDateString, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
156-
PHP_FE_END
157-
};
158-
159-
static const zend_function_entry date_funcs_period[] = {
160-
PHP_ME(DatePeriod, __construct, arginfo_class_DatePeriod___construct, ZEND_ACC_PUBLIC)
161-
PHP_ME(DatePeriod, __wakeup, arginfo_class_DatePeriod___wakeup, ZEND_ACC_PUBLIC)
162-
PHP_ME(DatePeriod, __set_state, arginfo_class_DatePeriod___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
163-
PHP_ME(DatePeriod, getStartDate, arginfo_class_DatePeriod_getStartDate, ZEND_ACC_PUBLIC)
164-
PHP_ME(DatePeriod, getEndDate, arginfo_class_DatePeriod_getEndDate, ZEND_ACC_PUBLIC)
165-
PHP_ME(DatePeriod, getDateInterval, arginfo_class_DatePeriod_getDateInterval, ZEND_ACC_PUBLIC)
166-
PHP_ME(DatePeriod, getRecurrences, arginfo_class_DatePeriod_getRecurrences, ZEND_ACC_PUBLIC)
167-
PHP_FE_END
168-
};
169-
170150
static char* guess_timezone(const timelib_tzdb *tzdb);
171151
static void date_register_classes(void);
172152
/* }}} */
@@ -1754,7 +1734,7 @@ static void date_register_classes(void) /* {{{ */
17541734
REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL_WITH_BC", PHP_DATE_TIMEZONE_GROUP_ALL_W_BC);
17551735
REGISTER_TIMEZONE_CLASS_CONST_STRING("PER_COUNTRY", PHP_DATE_TIMEZONE_PER_COUNTRY);
17561736

1757-
INIT_CLASS_ENTRY(ce_interval, "DateInterval", date_funcs_interval);
1737+
INIT_CLASS_ENTRY(ce_interval, "DateInterval", class_DateInterval_methods);
17581738
ce_interval.create_object = date_object_new_interval;
17591739
date_ce_interval = zend_register_internal_class_ex(&ce_interval, NULL);
17601740
memcpy(&date_object_handlers_interval, &std_object_handlers, sizeof(zend_object_handlers));
@@ -1769,7 +1749,7 @@ static void date_register_classes(void) /* {{{ */
17691749
date_object_handlers_interval.get_gc = date_object_get_gc_interval;
17701750
date_object_handlers_interval.compare = date_interval_compare_objects;
17711751

1772-
INIT_CLASS_ENTRY(ce_period, "DatePeriod", date_funcs_period);
1752+
INIT_CLASS_ENTRY(ce_period, "DatePeriod", class_DatePeriod_methods);
17731753
ce_period.create_object = date_object_new_period;
17741754
date_ce_period = zend_register_internal_class_ex(&ce_period, NULL);
17751755
date_ce_period->get_iterator = date_object_period_get_iterator;

ext/date/php_date.h

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,44 +26,6 @@
2626
extern zend_module_entry date_module_entry;
2727
#define phpext_date_ptr &date_module_entry
2828

29-
/* Advanced Interface */
30-
PHP_METHOD(DateTime, __construct);
31-
PHP_METHOD(DateTime, __wakeup);
32-
PHP_METHOD(DateTime, __set_state);
33-
PHP_METHOD(DateTime, createFromImmutable);
34-
PHP_METHOD(DateTime, createFromInterface);
35-
36-
PHP_METHOD(DateTimeImmutable, __construct);
37-
PHP_METHOD(DateTimeImmutable, __set_state);
38-
PHP_METHOD(DateTimeImmutable, modify);
39-
PHP_METHOD(DateTimeImmutable, add);
40-
PHP_METHOD(DateTimeImmutable, sub);
41-
PHP_METHOD(DateTimeImmutable, setTimezone);
42-
PHP_METHOD(DateTimeImmutable, setTime);
43-
PHP_METHOD(DateTimeImmutable, setDate);
44-
PHP_METHOD(DateTimeImmutable, setISODate);
45-
PHP_METHOD(DateTimeImmutable, setTimestamp);
46-
PHP_METHOD(DateTimeImmutable, createFromMutable);
47-
PHP_METHOD(DateTimeImmutable, createFromInterface);
48-
49-
PHP_METHOD(DateTimeZone, __construct);
50-
PHP_METHOD(DateTimeZone, __wakeup);
51-
PHP_METHOD(DateTimeZone, __set_state);
52-
53-
PHP_METHOD(DateInterval, __construct);
54-
PHP_METHOD(DateInterval, __wakeup);
55-
PHP_METHOD(DateInterval, __set_state);
56-
PHP_FUNCTION(date_interval_format);
57-
PHP_FUNCTION(date_interval_create_from_date_string);
58-
59-
PHP_METHOD(DatePeriod, __construct);
60-
PHP_METHOD(DatePeriod, __wakeup);
61-
PHP_METHOD(DatePeriod, __set_state);
62-
PHP_METHOD(DatePeriod, getStartDate);
63-
PHP_METHOD(DatePeriod, getEndDate);
64-
PHP_METHOD(DatePeriod, getDateInterval);
65-
PHP_METHOD(DatePeriod, getRecurrences);
66-
6729
PHP_RINIT_FUNCTION(date);
6830
PHP_RSHUTDOWN_FUNCTION(date);
6931
PHP_MINIT_FUNCTION(date);

0 commit comments

Comments
 (0)