@@ -206,7 +206,7 @@ public function tryToRepresentableType(): ?RepresentableType {
206
206
$ classType = $ type ;
207
207
} else {
208
208
// We can only represent a single class type.
209
- return false ;
209
+ return null ;
210
210
}
211
211
}
212
212
return new RepresentableType ($ classType , $ builtinTypes );
@@ -326,9 +326,17 @@ public function equals(ReturnInfo $other): bool {
326
326
class FuncInfo {
327
327
/** @var string */
328
328
public $ name ;
329
- /** @var ? string */
329
+ /** @var string|null */
330
330
public $ className ;
331
- /** @var ?string */
331
+ /** @var string|null */
332
+ public $ visibility ;
333
+ /** @var bool */
334
+ public $ isAbstract ;
335
+ /** @var bool */
336
+ public $ isStatic ;
337
+ /** @var bool */
338
+ public $ isFinal ;
339
+ /** @var string|null */
332
340
public $ alias ;
333
341
/** @var bool */
334
342
public $ isDeprecated ;
@@ -342,11 +350,25 @@ class FuncInfo {
342
350
public $ cond ;
343
351
344
352
public function __construct (
345
- string $ name , ?string $ className , ?string $ alias , bool $ isDeprecated , array $ args , ReturnInfo $ return ,
346
- int $ numRequiredArgs , ?string $ cond
353
+ string $ name ,
354
+ ?string $ className ,
355
+ ?string $ visibility ,
356
+ bool $ isAbstract ,
357
+ bool $ isStatic ,
358
+ bool $ isFinal ,
359
+ ?string $ alias ,
360
+ bool $ isDeprecated ,
361
+ array $ args ,
362
+ ReturnInfo $ return ,
363
+ int $ numRequiredArgs ,
364
+ ?string $ cond
347
365
) {
348
366
$ this ->name = $ name ;
349
367
$ this ->className = $ className ;
368
+ $ this ->visibility = $ visibility ;
369
+ $ this ->isAbstract = $ isAbstract ;
370
+ $ this ->isStatic = $ isStatic ;
371
+ $ this ->isFinal = $ isFinal ;
350
372
$ this ->alias = $ alias ;
351
373
$ this ->isDeprecated = $ isDeprecated ;
352
374
$ this ->args = $ args ;
@@ -377,6 +399,78 @@ public function getArgInfoName(): string {
377
399
}
378
400
return 'arginfo_ ' . $ this ->name ;
379
401
}
402
+
403
+ public function getFlags (): string
404
+ {
405
+ $ flags = sprintf ("ZEND_ACC_%s " , strtoupper ($ this ->visibility ));
406
+
407
+ if ($ this ->isStatic ) {
408
+ $ flags .= "|ZEND_ACC_STATIC " ;
409
+ }
410
+
411
+ if ($ this ->isFinal ) {
412
+ $ flags .= "|ZEND_ACC_FINAL " ;
413
+ }
414
+
415
+ if ($ this ->isAbstract ) {
416
+ $ flags .= "|ZEND_ACC_ABSTRACT " ;
417
+ }
418
+
419
+ if ($ this ->isDeprecated ) {
420
+ $ flags .= "|ZEND_ACC_DEPRECATED " ;
421
+ }
422
+
423
+ return $ flags ;
424
+ }
425
+
426
+ public function getDeclarationKey (): string
427
+ {
428
+ $ name = $ this ->alias ?? $ this ->name ;
429
+
430
+ return "$ name| $ this ->cond " ;
431
+ }
432
+
433
+ public function hasDeclaration (): bool
434
+ {
435
+ return $ this ->isAbstract === false || $ this ->visibility !== "public " ;
436
+ }
437
+
438
+ public function getDeclaration (): string
439
+ {
440
+ if ($ this ->hasDeclaration () === false ) {
441
+ return "" ;
442
+ }
443
+
444
+ if ($ this ->alias ) {
445
+ $ methodAlias = $ this ->getMethodAlias ();
446
+
447
+ if ($ methodAlias ) {
448
+ return "ZEND_METHOD( $ this ->className , $ methodAlias); \n" ;
449
+ } else {
450
+ return "ZEND_FUNCTION( $ this ->alias ); \n" ;
451
+ }
452
+ }
453
+
454
+ if ($ this ->className ) {
455
+ return "ZEND_METHOD( $ this ->className , $ this ->name ); \n" ;
456
+ }
457
+
458
+ return "ZEND_FUNCTION( $ this ->name ); \n" ;
459
+ }
460
+
461
+ public function getMethodAlias (): ?string
462
+ {
463
+ if ($ this ->className === false || $ this ->alias === null ) {
464
+ return null ;
465
+ }
466
+
467
+ $ separatorPosition = strpos ($ this ->alias , ":: " );
468
+ if ($ separatorPosition === false ) {
469
+ return null ;
470
+ }
471
+
472
+ return substr ($ this ->alias , $ separatorPosition );
473
+ }
380
474
}
381
475
382
476
class ClassInfo {
@@ -417,7 +511,7 @@ public function getAllFuncInfos(): iterable {
417
511
class DocCommentTag {
418
512
/** @var string */
419
513
public $ name ;
420
- /** @var ? string */
514
+ /** @var string|null */
421
515
public $ value ;
422
516
423
517
public function __construct (string $ name , ?string $ value ) {
@@ -458,7 +552,15 @@ function parseDocComment(DocComment $comment): array {
458
552
}
459
553
460
554
function parseFunctionLike (
461
- PrettyPrinterAbstract $ prettyPrinter , string $ name , ?string $ className , Node \FunctionLike $ func , ?string $ cond
555
+ PrettyPrinterAbstract $ prettyPrinter ,
556
+ string $ name ,
557
+ ?string $ className ,
558
+ ?string $ visibility ,
559
+ bool $ isAbstract ,
560
+ bool $ isStatic ,
561
+ bool $ isFinal ,
562
+ Node \FunctionLike $ func ,
563
+ ?string $ cond
462
564
): FuncInfo {
463
565
$ comment = $ func ->getDocComment ();
464
566
$ paramMeta = [];
@@ -539,8 +641,23 @@ function parseFunctionLike(
539
641
540
642
$ return = new ReturnInfo (
541
643
$ func ->returnsByRef (),
542
- $ returnType ? Type::fromNode ($ returnType ) : null );
543
- return new FuncInfo ($ name , $ className , $ alias , $ isDeprecated , $ args , $ return , $ numRequiredArgs , $ cond );
644
+ $ returnType ? Type::fromNode ($ returnType ) : null
645
+ );
646
+
647
+ return new FuncInfo (
648
+ $ name ,
649
+ $ className ,
650
+ $ visibility ,
651
+ $ isAbstract ,
652
+ $ isStatic ,
653
+ $ isFinal ,
654
+ $ alias ,
655
+ $ isDeprecated ,
656
+ $ args ,
657
+ $ return ,
658
+ $ numRequiredArgs ,
659
+ $ cond
660
+ );
544
661
}
545
662
546
663
function handlePreprocessorConditions (array &$ conds , Stmt $ stmt ): ?string {
@@ -622,7 +739,18 @@ function parseStubFile(string $fileName): FileInfo {
622
739
}
623
740
624
741
if ($ stmt instanceof Stmt \Function_) {
625
- $ funcInfos [] = parseFunctionLike ($ prettyPrinter , $ stmt ->name ->toString (), null , $ stmt , $ cond );
742
+ $ funcInfos [] = parseFunctionLike (
743
+ $ prettyPrinter ,
744
+ $ stmt ->name ->toString (),
745
+ null ,
746
+ null ,
747
+ false ,
748
+ false ,
749
+ false ,
750
+ $ stmt ,
751
+ $ cond
752
+ );
753
+
626
754
continue ;
627
755
}
628
756
@@ -639,8 +767,22 @@ function parseStubFile(string $fileName): FileInfo {
639
767
throw new Exception ("Not implemented {$ classStmt ->getType ()}" );
640
768
}
641
769
770
+ $ visibility = $ classStmt ->isPublic () ? "public " : ($ classStmt ->isProtected () ? "protected " : "private " );
771
+ $ isAbstract = $ classStmt ->isAbstract () || $ stmt instanceof Stmt \Interface_;
772
+ $ isStatic = $ classStmt ->isStatic ();
773
+ $ isFinal = $ classStmt ->isFinal ();
774
+
642
775
$ methodInfos [] = parseFunctionLike (
643
- $ prettyPrinter , $ classStmt ->name ->toString (), $ className , $ classStmt , $ cond );
776
+ $ prettyPrinter ,
777
+ $ classStmt ->name ->toString (),
778
+ $ className ,
779
+ $ visibility ,
780
+ $ isAbstract ,
781
+ $ isStatic ,
782
+ $ isFinal ,
783
+ $ classStmt ,
784
+ $ cond
785
+ );
644
786
}
645
787
646
788
$ classInfos [] = new ClassInfo ($ className , $ methodInfos );
@@ -778,8 +920,6 @@ function generateCodeWithConditions(
778
920
}
779
921
780
922
function generateArgInfoCode (FileInfo $ fileInfo ): string {
781
- $ funcInfos = $ fileInfo ->funcInfos ;
782
-
783
923
$ code = "/* This is a generated file, edit the .stub.php file instead. */ \n" ;
784
924
$ generatedFuncInfos = [];
785
925
$ code .= generateCodeWithConditions (
@@ -801,21 +941,69 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
801
941
);
802
942
803
943
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 ;
944
+ $ code .= generateFunctionEntry (null , $ fileInfo ->funcInfos );
945
+
946
+ foreach ($ fileInfo ->classInfos as $ classInfo ) {
947
+ $ code .= generateFunctionEntry ($ classInfo ->name , $ classInfo ->funcInfos );
948
+ }
949
+ }
950
+
951
+ return $ code ;
952
+ }
953
+
954
+ /**
955
+ * @param FuncInfo[] $funcInfos
956
+ */
957
+ function generateFunctionEntry (?string $ className , array $ funcInfos ): string {
958
+ $ code = "" ;
959
+ $ generatedDeclarations = [];
960
+ $ code .= generateCodeWithConditions ($ funcInfos , "" , function (FuncInfo $ funcInfo ) use (&$ generatedDeclarations ) {
961
+ $ key = $ funcInfo ->getDeclarationKey ();
962
+ if (isset ($ generatedDeclarations [$ key ])) {
963
+ return null ;
964
+ }
965
+ $ generatedDeclarations [$ key ] = true ;
966
+
967
+ return $ funcInfo ->getDeclaration ();
968
+ });
969
+
970
+ if ($ code ) {
971
+ $ code = "\n\n" . $ code ;
972
+ }
973
+
974
+ $ functionEntryName = $ className ? "class_ {$ className }_methods " : "ext_functions " ;
975
+
976
+ $ code .= "\n\nstatic const zend_function_entry {$ functionEntryName }[] = { \n" ;
977
+ $ code .= generateCodeWithConditions ($ funcInfos , "" , function (FuncInfo $ funcInfo ) {
978
+ if ($ funcInfo ->className ) {
979
+ if ($ funcInfo ->alias ) {
980
+ $ methodAlias = $ funcInfo ->getMethodAlias ();
981
+
982
+ if ($ methodAlias ) {
983
+ return sprintf (
984
+ "\tZEND_MALIAS(%s, %s, %s, %s, %s) \n" ,
985
+ $ funcInfo ->className , $ funcInfo ->name , $ methodAlias , $ funcInfo ->getArgInfoName (), $ funcInfo ->getFlags ()
986
+ );
987
+ }
988
+
989
+ return sprintf (
990
+ "\tZEND_ME_MAPPING(%s, %s, %s, %s) \n" ,
991
+ $ funcInfo ->name , $ funcInfo ->alias , $ funcInfo ->getArgInfoName (), $ funcInfo ->getFlags ()
992
+ );
811
993
}
812
994
813
- $ generatedDeclarations [$ key ] = true ;
814
- return "ZEND_FUNCTION( $ name); \n" ;
815
- });
995
+ if ($ funcInfo ->hasDeclaration () === false ) {
996
+ return sprintf (
997
+ "\tZEND_ABSTRACT_ME(%s, %s, %s) \n" ,
998
+ $ funcInfo ->className , $ funcInfo ->name , $ funcInfo ->getArgInfoName ()
999
+ );
1000
+ }
816
1001
817
- $ code .= "\n\nstatic const zend_function_entry ext_functions[] = { \n" ;
818
- $ code .= generateCodeWithConditions ($ fileInfo ->funcInfos , "" , function (FuncInfo $ funcInfo ) {
1002
+ return sprintf (
1003
+ "\tZEND_ME(%s, %s, %s, %s) \n" ,
1004
+ $ funcInfo ->className , $ funcInfo ->name , $ funcInfo ->getArgInfoName (), $ funcInfo ->getFlags ()
1005
+ );
1006
+ } else {
819
1007
if ($ funcInfo ->alias ) {
820
1008
return sprintf (
821
1009
"\tZEND_FALIAS(%s, %s, %s) \n" ,
@@ -828,10 +1016,10 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
828
1016
}
829
1017
830
1018
return sprintf ("\tZEND_FE(%s, %s) \n" , $ funcInfo ->name , $ funcInfo ->getArgInfoName ());
831
- });
832
- $ code .= "\t ZEND_FE_END \n" ;
833
- $ code .= "}; \n" ;
834
- }
1019
+ }
1020
+ }) ;
1021
+ $ code .= "\t ZEND_FE_END \n" ;
1022
+ $ code .= " }; \n" ;
835
1023
836
1024
return $ code ;
837
1025
}
0 commit comments