@@ -324,29 +324,43 @@ public function equals(ReturnInfo $other): bool {
324
324
}
325
325
326
326
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 ;
335
336
/** @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 ;
343
341
344
342
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
347
356
) {
348
357
$ this ->name = $ name ;
349
358
$ this ->className = $ className ;
359
+ $ this ->visibility = $ visibility ;
360
+ $ this ->isAbstract = $ isAbstract ;
361
+ $ this ->isStatic = $ isStatic ;
362
+ $ this ->isFinal = $ isFinal ;
363
+ $ this ->mapping = $ mapping ;
350
364
$ this ->alias = $ alias ;
351
365
$ this ->isDeprecated = $ isDeprecated ;
352
366
$ this ->args = $ args ;
@@ -458,10 +472,19 @@ function parseDocComment(DocComment $comment): array {
458
472
}
459
473
460
474
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
462
484
): FuncInfo {
463
485
$ comment = $ func ->getDocComment ();
464
486
$ paramMeta = [];
487
+ $ mapping = null ;
465
488
$ alias = null ;
466
489
$ isDeprecated = false ;
467
490
$ haveDocReturnType = false ;
@@ -475,6 +498,8 @@ function parseFunctionLike(
475
498
$ paramMeta [$ varName ] = [];
476
499
}
477
500
$ paramMeta [$ varName ]['preferRef ' ] = true ;
501
+ } else if ($ tag ->name === 'mapping ' ) {
502
+ $ mapping = $ tag ->getValue ();
478
503
} else if ($ tag ->name === 'alias ' ) {
479
504
$ alias = $ tag ->getValue ();
480
505
} else if ($ tag ->name === 'deprecated ' ) {
@@ -539,8 +564,24 @@ function parseFunctionLike(
539
564
540
565
$ return = new ReturnInfo (
541
566
$ 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
+ );
544
585
}
545
586
546
587
function handlePreprocessorConditions (array &$ conds , Stmt $ stmt ): ?string {
@@ -622,7 +663,18 @@ function parseStubFile(string $fileName): FileInfo {
622
663
}
623
664
624
665
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
+
626
678
continue ;
627
679
}
628
680
@@ -639,8 +691,22 @@ function parseStubFile(string $fileName): FileInfo {
639
691
throw new Exception ("Not implemented {$ classStmt ->getType ()}" );
640
692
}
641
693
694
+ $ visibility = $ classStmt ->isPublic () ? "public " : ($ classStmt ->isProtected () ? "protected " : "private " );
695
+ $ isAbstract = $ classStmt ->isAbstract ();
696
+ $ isStatic = $ classStmt ->isStatic ();
697
+ $ isFinal = $ classStmt ->isFinal ();
698
+
642
699
$ 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
+ );
644
710
}
645
711
646
712
$ classInfos [] = new ClassInfo ($ className , $ methodInfos );
@@ -778,8 +844,6 @@ function generateCodeWithConditions(
778
844
}
779
845
780
846
function generateArgInfoCode (FileInfo $ fileInfo ): string {
781
- $ funcInfos = $ fileInfo ->funcInfos ;
782
-
783
847
$ code = "/* This is a generated file, edit the .stub.php file instead. */ \n" ;
784
848
$ generatedFuncInfos = [];
785
849
$ code .= generateCodeWithConditions (
@@ -801,21 +865,80 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
801
865
);
802
866
803
867
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
+ );
811
928
}
812
929
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
+ }
816
936
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 {
819
942
if ($ funcInfo ->alias ) {
820
943
return sprintf (
821
944
"\tZEND_FALIAS(%s, %s, %s) \n" ,
@@ -828,10 +951,10 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
828
951
}
829
952
830
953
return sprintf ("\tZEND_FE(%s, %s) \n" , $ funcInfo ->name , $ funcInfo ->getArgInfoName ());
831
- });
832
- $ code .= "\t ZEND_FE_END \n" ;
833
- $ code .= "}; \n" ;
834
- }
954
+ }
955
+ }) ;
956
+ $ code .= "\t ZEND_FE_END \n" ;
957
+ $ code .= " }; \n" ;
835
958
836
959
return $ code ;
837
960
}
0 commit comments