@@ -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,83 @@ 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 getDeclarationName (): string
434
+ {
435
+ return $ this ->alias ?? $ this ->name ;
436
+ }
437
+
438
+ public function hasDeclaration (): bool
439
+ {
440
+ return $ this ->isAbstract === false || $ this ->visibility !== "public " ;
441
+ }
442
+
443
+ public function getDeclaration (): string
444
+ {
445
+ if ($ this ->hasDeclaration () === false ) {
446
+ return "" ;
447
+ }
448
+
449
+ if ($ this ->alias ) {
450
+ $ methodAlias = $ this ->getMethodAlias ();
451
+
452
+ if ($ methodAlias ) {
453
+ return "ZEND_METHOD( $ this ->className , $ methodAlias); \n" ;
454
+ } else {
455
+ return "ZEND_FUNCTION( $ this ->alias ); \n" ;
456
+ }
457
+ }
458
+
459
+ if ($ this ->className ) {
460
+ return "ZEND_METHOD( $ this ->className , $ this ->name ); \n" ;
461
+ }
462
+
463
+ return "ZEND_FUNCTION( $ this ->name ); \n" ;
464
+ }
465
+
466
+ public function getMethodAlias (): ?string
467
+ {
468
+ if ($ this ->className === false || $ this ->alias === null ) {
469
+ return null ;
470
+ }
471
+
472
+ $ separatorPosition = strpos ($ this ->alias , ":: " );
473
+ if ($ separatorPosition === false ) {
474
+ return null ;
475
+ }
476
+
477
+ return substr ($ this ->alias , $ separatorPosition );
478
+ }
380
479
}
381
480
382
481
class ClassInfo {
@@ -417,7 +516,7 @@ public function getAllFuncInfos(): iterable {
417
516
class DocCommentTag {
418
517
/** @var string */
419
518
public $ name ;
420
- /** @var ? string */
519
+ /** @var string|null */
421
520
public $ value ;
422
521
423
522
public function __construct (string $ name , ?string $ value ) {
@@ -458,7 +557,15 @@ function parseDocComment(DocComment $comment): array {
458
557
}
459
558
460
559
function parseFunctionLike (
461
- PrettyPrinterAbstract $ prettyPrinter , string $ name , ?string $ className , Node \FunctionLike $ func , ?string $ cond
560
+ PrettyPrinterAbstract $ prettyPrinter ,
561
+ string $ name ,
562
+ ?string $ className ,
563
+ ?string $ visibility ,
564
+ bool $ isAbstract ,
565
+ bool $ isStatic ,
566
+ bool $ isFinal ,
567
+ Node \FunctionLike $ func ,
568
+ ?string $ cond
462
569
): FuncInfo {
463
570
$ comment = $ func ->getDocComment ();
464
571
$ paramMeta = [];
@@ -539,8 +646,23 @@ function parseFunctionLike(
539
646
540
647
$ return = new ReturnInfo (
541
648
$ func ->returnsByRef (),
542
- $ returnType ? Type::fromNode ($ returnType ) : null );
543
- return new FuncInfo ($ name , $ className , $ alias , $ isDeprecated , $ args , $ return , $ numRequiredArgs , $ cond );
649
+ $ returnType ? Type::fromNode ($ returnType ) : null
650
+ );
651
+
652
+ return new FuncInfo (
653
+ $ name ,
654
+ $ className ,
655
+ $ visibility ,
656
+ $ isAbstract ,
657
+ $ isStatic ,
658
+ $ isFinal ,
659
+ $ alias ,
660
+ $ isDeprecated ,
661
+ $ args ,
662
+ $ return ,
663
+ $ numRequiredArgs ,
664
+ $ cond
665
+ );
544
666
}
545
667
546
668
function handlePreprocessorConditions (array &$ conds , Stmt $ stmt ): ?string {
@@ -622,7 +744,18 @@ function parseStubFile(string $fileName): FileInfo {
622
744
}
623
745
624
746
if ($ stmt instanceof Stmt \Function_) {
625
- $ funcInfos [] = parseFunctionLike ($ prettyPrinter , $ stmt ->name ->toString (), null , $ stmt , $ cond );
747
+ $ funcInfos [] = parseFunctionLike (
748
+ $ prettyPrinter ,
749
+ $ stmt ->name ->toString (),
750
+ null ,
751
+ null ,
752
+ false ,
753
+ false ,
754
+ false ,
755
+ $ stmt ,
756
+ $ cond
757
+ );
758
+
626
759
continue ;
627
760
}
628
761
@@ -639,8 +772,22 @@ function parseStubFile(string $fileName): FileInfo {
639
772
throw new Exception ("Not implemented {$ classStmt ->getType ()}" );
640
773
}
641
774
775
+ $ visibility = $ classStmt ->isPublic () ? "public " : ($ classStmt ->isProtected () ? "protected " : "private " );
776
+ $ isAbstract = $ classStmt ->isAbstract () || $ stmt instanceof Stmt \Interface_;
777
+ $ isStatic = $ classStmt ->isStatic ();
778
+ $ isFinal = $ classStmt ->isFinal ();
779
+
642
780
$ methodInfos [] = parseFunctionLike (
643
- $ prettyPrinter , $ classStmt ->name ->toString (), $ className , $ classStmt , $ cond );
781
+ $ prettyPrinter ,
782
+ $ classStmt ->name ->toString (),
783
+ $ className ,
784
+ $ visibility ,
785
+ $ isAbstract ,
786
+ $ isStatic ,
787
+ $ isFinal ,
788
+ $ classStmt ,
789
+ $ cond
790
+ );
644
791
}
645
792
646
793
$ classInfos [] = new ClassInfo ($ className , $ methodInfos );
@@ -778,8 +925,6 @@ function generateCodeWithConditions(
778
925
}
779
926
780
927
function generateArgInfoCode (FileInfo $ fileInfo ): string {
781
- $ funcInfos = $ fileInfo ->funcInfos ;
782
-
783
928
$ code = "/* This is a generated file, edit the .stub.php file instead. */ \n" ;
784
929
$ generatedFuncInfos = [];
785
930
$ code .= generateCodeWithConditions (
@@ -801,21 +946,65 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
801
946
);
802
947
803
948
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 ;
949
+ $ code .= generateFunctionEntry (null , $ fileInfo ->funcInfos );
950
+
951
+ foreach ($ fileInfo ->classInfos as $ classInfo ) {
952
+ $ code .= generateFunctionEntry ($ classInfo ->name , $ classInfo ->funcInfos );
953
+ }
954
+ }
955
+
956
+ return $ code ;
957
+ }
958
+
959
+ /**
960
+ * @param FuncInfo[] $funcInfos
961
+ */
962
+ function generateFunctionEntry (?string $ className , array $ funcInfos ): string {
963
+ $ code = "\n\n" ;
964
+ $ generatedDeclarations = [];
965
+ $ code .= generateCodeWithConditions ($ funcInfos , "" , function (FuncInfo $ funcInfo ) use (&$ generatedDeclarations ) {
966
+ $ key = $ funcInfo ->getDeclarationName ();
967
+ if (isset ($ generatedDeclarations [$ key ])) {
968
+ return null ;
969
+ }
970
+ $ generatedDeclarations [$ key ] = true ;
971
+
972
+ return $ funcInfo ->getDeclaration ();
973
+ });
974
+
975
+ $ functionEntryName = $ className ? "class_ {$ className }_methods " : "ext_functions " ;
976
+
977
+ $ code .= "\n\nstatic const zend_function_entry {$ functionEntryName }[] = { \n" ;
978
+ $ code .= generateCodeWithConditions ($ funcInfos , "" , function (FuncInfo $ funcInfo ) {
979
+ if ($ funcInfo ->className ) {
980
+ if ($ funcInfo ->alias ) {
981
+ $ methodAlias = $ funcInfo ->getMethodAlias ();
982
+
983
+ if ($ methodAlias ) {
984
+ return sprintf (
985
+ "\tZEND_MALIAS(%s, %s, %s, %s, %s) \n" ,
986
+ $ funcInfo ->className , $ funcInfo ->name , $ methodAlias , $ funcInfo ->getArgInfoName (), $ funcInfo ->getFlags ()
987
+ );
988
+ }
989
+
990
+ return sprintf (
991
+ "\tZEND_ME_MAPPING(%s, %s, %s, %s) \n" ,
992
+ $ funcInfo ->name , $ funcInfo ->alias , $ funcInfo ->getArgInfoName (), $ funcInfo ->getFlags ()
993
+ );
811
994
}
812
995
813
- $ generatedDeclarations [$ key ] = true ;
814
- return "ZEND_FUNCTION( $ name); \n" ;
815
- });
996
+ if ($ funcInfo ->hasDeclaration () === false ) {
997
+ return sprintf (
998
+ "\tZEND_ABSTRACT_ME(%s, %s, %s) \n" ,
999
+ $ funcInfo ->className , $ funcInfo ->name , $ funcInfo ->getArgInfoName ()
1000
+ );
1001
+ }
816
1002
817
- $ code .= "\n\nstatic const zend_function_entry ext_functions[] = { \n" ;
818
- $ code .= generateCodeWithConditions ($ fileInfo ->funcInfos , "" , function (FuncInfo $ funcInfo ) {
1003
+ return sprintf (
1004
+ "\tZEND_ME(%s, %s, %s, %s) \n" ,
1005
+ $ funcInfo ->className , $ funcInfo ->name , $ funcInfo ->getArgInfoName (), $ funcInfo ->getFlags ()
1006
+ );
1007
+ } else {
819
1008
if ($ funcInfo ->alias ) {
820
1009
return sprintf (
821
1010
"\tZEND_FALIAS(%s, %s, %s) \n" ,
@@ -828,10 +1017,10 @@ function(FuncInfo $funcInfo) use(&$generatedFuncInfos) {
828
1017
}
829
1018
830
1019
return sprintf ("\tZEND_FE(%s, %s) \n" , $ funcInfo ->name , $ funcInfo ->getArgInfoName ());
831
- });
832
- $ code .= "\t ZEND_FE_END \n" ;
833
- $ code .= "}; \n" ;
834
- }
1020
+ }
1021
+ }) ;
1022
+ $ code .= "\t ZEND_FE_END \n" ;
1023
+ $ code .= " }; \n" ;
835
1024
836
1025
return $ code ;
837
1026
}
0 commit comments