@@ -2700,17 +2700,18 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera
2700
2700
}
2701
2701
$ classSynopsisInfo ->appendChild (new DOMText ("\n " ));
2702
2702
2703
- /** @var Name[] $parentsWithInheritedConstants */
2703
+ /** @var array<string, Name> $parentsWithInheritedConstants */
2704
2704
$ parentsWithInheritedConstants = [];
2705
- /** @var Name[] $parentsWithInheritedProperties */
2705
+ /** @var array<string, Name> $parentsWithInheritedProperties */
2706
2706
$ parentsWithInheritedProperties = [];
2707
- /** @var Name[] $parentsWithInheritedMethods */
2707
+ /** @var array<int, array{name: Name, types: int[]}> $parentsWithInheritedMethods */
2708
2708
$ parentsWithInheritedMethods = [];
2709
2709
2710
2710
$ this ->collectInheritedMembers (
2711
2711
$ parentsWithInheritedConstants ,
2712
2712
$ parentsWithInheritedProperties ,
2713
2713
$ parentsWithInheritedMethods ,
2714
+ $ this ->hasConstructor (),
2714
2715
$ classMap
2715
2716
);
2716
2717
@@ -2756,9 +2757,9 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera
2756
2757
"&InheritedProperties; "
2757
2758
);
2758
2759
2759
- $ isConcreteClass = ( $ this ->type === " class " && !( $ this -> flags & Class_:: MODIFIER_ABSTRACT ) );
2760
+ $ isConcreteClassWithoutParentConstructor = $ this ->isConcreteClassWithoutParentConstructor ( $ classMap );
2760
2761
2761
- if ($ isConcreteClass || !empty ($ this ->funcInfos )) {
2762
+ if ($ isConcreteClassWithoutParentConstructor || !empty ($ this ->funcInfos )) {
2762
2763
$ classSynopsis ->appendChild (new DOMText ("\n\n " ));
2763
2764
$ classSynopsisInfo = $ doc ->createElement ("classsynopsisinfo " , "&Methods; " );
2764
2765
$ classSynopsisInfo ->setAttribute ("role " , "comment " );
@@ -2768,7 +2769,7 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera
2768
2769
$ classReference = self ::getClassSynopsisReference ($ this ->name );
2769
2770
$ escapedName = addslashes ($ this ->name ->__toString ());
2770
2771
2771
- if ($ isConcreteClass || $ this ->hasConstructor ()) {
2772
+ if ($ isConcreteClassWithoutParentConstructor || $ this ->hasConstructor ()) {
2772
2773
$ classSynopsis ->appendChild (new DOMText ("\n " ));
2773
2774
$ includeElement = $ this ->createIncludeElement (
2774
2775
$ doc ,
@@ -2802,14 +2803,21 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera
2802
2803
$ classSynopsis ->appendChild ($ classSynopsisInfo );
2803
2804
2804
2805
foreach ($ parentsWithInheritedMethods as $ parent ) {
2805
- $ classSynopsis ->appendChild (new DOMText ("\n " ));
2806
- $ parentReference = self ::getClassSynopsisReference ($ parent );
2807
- $ escapedParentName = addslashes ($ parent ->__toString ());
2808
- $ includeElement = $ this ->createIncludeElement (
2809
- $ doc ,
2810
- "xmlns(db=http://docbook.org/ns/docbook) xpointer(id(' $ parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db:methodsynopsis[@role=' $ escapedParentName']) "
2811
- );
2812
- $ classSynopsis ->appendChild ($ includeElement );
2806
+ $ parentName = $ parent ["name " ];
2807
+ $ parentMethodsynopsisTypes = $ parent ["types " ];
2808
+
2809
+ $ parentReference = self ::getClassSynopsisReference ($ parentName );
2810
+ $ escapedParentName = addslashes ($ parentName ->__toString ());
2811
+
2812
+ foreach ($ parentMethodsynopsisTypes as $ parentMethodsynopsisType ) {
2813
+ $ classSynopsis ->appendChild (new DOMText ("\n " ));
2814
+ $ includeElement = $ this ->createIncludeElement (
2815
+ $ doc ,
2816
+ "xmlns(db=http://docbook.org/ns/docbook) xpointer(id(' $ parentReference')/db:refentry/db:refsect1[@role='description']/descendant::db: {$ parentMethodsynopsisType }[@role=' $ escapedParentName']) "
2817
+ );
2818
+
2819
+ $ classSynopsis ->appendChild ($ includeElement );
2820
+ }
2813
2821
}
2814
2822
}
2815
2823
@@ -2818,6 +2826,31 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, itera
2818
2826
return $ classSynopsis ;
2819
2827
}
2820
2828
2829
+ /**
2830
+ * @param array<string, ClassInfo> $classMap
2831
+ */
2832
+ public function getNonExistentDefaultConstructorForManual (array $ classMap ): ?FuncInfo {
2833
+ if (!$ this ->isConcreteClassWithoutParentConstructor ($ classMap ) || $ this ->hasConstructor ()) {
2834
+ return null ;
2835
+ }
2836
+
2837
+ return new FuncInfo (
2838
+ new MethodName ($ this ->name , "__construct " ),
2839
+ $ this ->flags ,
2840
+ 0 ,
2841
+ null ,
2842
+ null ,
2843
+ false ,
2844
+ false ,
2845
+ true ,
2846
+ [],
2847
+ new ReturnInfo (false , null , null , false , null ),
2848
+ 0 ,
2849
+ null ,
2850
+ false
2851
+ );
2852
+ }
2853
+
2821
2854
private static function createOoElement (
2822
2855
DOMDocument $ doc ,
2823
2856
ClassInfo $ classInfo ,
@@ -2867,39 +2900,54 @@ public static function getClassSynopsisReference(Name $name): string {
2867
2900
}
2868
2901
2869
2902
/**
2870
- * @param Name[] $parentsWithInheritedConstants
2871
- * @param Name[] $parentsWithInheritedProperties
2872
- * @param Name[] $parentsWithInheritedMethods
2903
+ * @param array<string, Name> $parentsWithInheritedConstants
2904
+ * @param array<string, Name> $parentsWithInheritedProperties
2905
+ * @param array<string, array{name: Name, types: int[]}> $parentsWithInheritedMethods
2873
2906
* @param array<string, ClassInfo> $classMap
2874
2907
*/
2875
2908
private function collectInheritedMembers (
2876
2909
array &$ parentsWithInheritedConstants ,
2877
2910
array &$ parentsWithInheritedProperties ,
2878
2911
array &$ parentsWithInheritedMethods ,
2912
+ bool $ hasConstructor ,
2879
2913
array $ classMap
2880
2914
): void {
2881
2915
foreach ($ this ->extends as $ parent ) {
2882
2916
$ parentInfo = $ classMap [$ parent ->toString ()] ?? null ;
2917
+ $ parentName = $ parent ->toString ();
2918
+
2883
2919
if (!$ parentInfo ) {
2884
- throw new Exception ("Missing parent class " . $ parent -> toString () );
2920
+ throw new Exception ("Missing parent class $ parentName " );
2885
2921
}
2886
2922
2887
- if (!empty ($ parentInfo ->constInfos ) && !isset ($ parentsWithInheritedConstants [$ parent ->toString ()])) {
2888
- $ parentsWithInheritedConstants [$ parent ->toString ()] = $ parent ;
2923
+ if (!empty ($ parentInfo ->constInfos ) && !isset ($ parentsWithInheritedConstants [$ parentName ])) {
2924
+ $ parentsWithInheritedConstants [] = $ parent ;
2925
+ }
2926
+
2927
+ if (!empty ($ parentInfo ->propertyInfos ) && !isset ($ parentsWithInheritedProperties [$ parentName ])) {
2928
+ $ parentsWithInheritedProperties [$ parentName ] = $ parent ;
2889
2929
}
2890
2930
2891
- if (!empty ($ parentInfo ->propertyInfos ) && !isset ($ parentsWithInheritedProperties [$ parent ->toString ()])) {
2892
- $ parentsWithInheritedProperties [$ parent ->toString ()] = $ parent ;
2931
+ if (!$ hasConstructor && $ parentInfo ->hasConstructor ()) {
2932
+ $ parentsWithInheritedMethods [$ parentName ]["name " ] = $ parent ;
2933
+ $ parentsWithInheritedMethods [$ parentName ]["types " ][] = "constructorsynopsis " ;
2893
2934
}
2894
2935
2895
- if (!isset ($ parentsWithInheritedMethods [$ parent ->toString ()]) && $ parentInfo ->hasMethods ()) {
2896
- $ parentsWithInheritedMethods [$ parent ->toString ()] = $ parent ;
2936
+ if ($ parentInfo ->hasMethods ()) {
2937
+ $ parentsWithInheritedMethods [$ parentName ]["name " ] = $ parent ;
2938
+ $ parentsWithInheritedMethods [$ parentName ]["types " ][] = "methodsynopsis " ;
2939
+ }
2940
+
2941
+ if ($ parentInfo ->hasDestructor ()) {
2942
+ $ parentsWithInheritedMethods [$ parentName ]["name " ] = $ parent ;
2943
+ $ parentsWithInheritedMethods [$ parentName ]["types " ][] = "destructorsynopsis " ;
2897
2944
}
2898
2945
2899
2946
$ parentInfo ->collectInheritedMembers (
2900
2947
$ parentsWithInheritedConstants ,
2901
2948
$ parentsWithInheritedProperties ,
2902
2949
$ parentsWithInheritedMethods ,
2950
+ $ hasConstructor ,
2903
2951
$ classMap
2904
2952
);
2905
2953
}
@@ -2921,6 +2969,7 @@ private function collectInheritedMembers(
2921
2969
$ parentsWithInheritedConstants ,
2922
2970
$ unusedParentsWithInheritedProperties ,
2923
2971
$ unusedParentsWithInheritedMethods ,
2972
+ $ hasConstructor ,
2924
2973
$ classMap
2925
2974
);
2926
2975
}
@@ -2937,6 +2986,29 @@ private function hasConstructor(): bool
2937
2986
return false ;
2938
2987
}
2939
2988
2989
+ /**
2990
+ * @param array<string, ClassInfo> $classMap
2991
+ */
2992
+ private function hasParentConstructor (array $ classMap ): bool
2993
+ {
2994
+ foreach ($ this ->extends as $ parentName ) {
2995
+ $ parent = $ classMap [$ parentName ->toString ()] ?? null ;
2996
+ if ($ parent === null ) {
2997
+ throw new Exception ("Missing parent class " . $ parent ->toString ());
2998
+ }
2999
+
3000
+ if ($ parent ->hasConstructor ()) {
3001
+ return true ;
3002
+ }
3003
+
3004
+ if ($ parent ->hasParentConstructor ($ classMap )) {
3005
+ return true ;
3006
+ }
3007
+ }
3008
+
3009
+ return false ;
3010
+ }
3011
+
2940
3012
private function hasDestructor (): bool
2941
3013
{
2942
3014
foreach ($ this ->funcInfos as $ funcInfo ) {
@@ -2959,6 +3031,13 @@ private function hasMethods(): bool
2959
3031
return false ;
2960
3032
}
2961
3033
3034
+ /**
3035
+ * @param array<string, ClassInfo> $classMap
3036
+ */
3037
+ private function isConcreteClassWithoutParentConstructor (array $ classMap ) {
3038
+ return $ this ->type === "class " && !($ this ->flags & Class_::MODIFIER_ABSTRACT ) && !$ this ->hasParentConstructor ($ classMap );
3039
+ }
3040
+
2962
3041
private function createIncludeElement (DOMDocument $ doc , string $ query ): DOMElement
2963
3042
{
2964
3043
$ includeElement = $ doc ->createElement ("xi:include " );
@@ -3036,6 +3115,18 @@ public function getAllFuncInfos(): iterable {
3036
3115
}
3037
3116
}
3038
3117
3118
+ /**
3119
+ * @return array<string, ClassInfo> $classMap
3120
+ */
3121
+ public function getAllNonExistentDefaultConstructorsForManual (array $ classMap ): iterable {
3122
+ foreach ($ this ->classInfos as $ classInfo ) {
3123
+ $ funcInfo = $ classInfo ->getNonExistentDefaultConstructorForManual ($ classMap );
3124
+ if ($ funcInfo !== null ) {
3125
+ yield $ funcInfo ;
3126
+ }
3127
+ }
3128
+ }
3129
+
3039
3130
/**
3040
3131
* @return iterable<ConstInfo>
3041
3132
*/
@@ -4058,14 +4149,14 @@ static function (FuncInfo $funcInfo) use ($allConstInfos) {
4058
4149
);
4059
4150
}
4060
4151
4061
- /** @param FuncInfo <string, FuncInfo> $funcInfos */
4062
- function generateOptimizerInfo (array $ funcInfos ): string {
4152
+ /** @param array <string, FuncInfo> $funcMap */
4153
+ function generateOptimizerInfo (array $ funcMap ): string {
4063
4154
4064
4155
$ code = "/* This is a generated file, edit the .stub.php files instead. */ \n\n" ;
4065
4156
4066
4157
$ code .= "static const func_info_t func_infos[] = { \n" ;
4067
4158
4068
- $ code .= generateCodeWithConditions ($ funcInfos , "" , static function (FuncInfo $ funcInfo ) {
4159
+ $ code .= generateCodeWithConditions ($ funcMap , "" , static function (FuncInfo $ funcInfo ) {
4069
4160
return $ funcInfo ->getOptimizerInfo ();
4070
4161
});
4071
4162
@@ -4688,7 +4779,6 @@ function initPhpParser() {
4688
4779
4689
4780
foreach ($ fileInfos as $ fileInfo ) {
4690
4781
foreach ($ fileInfo ->getAllFuncInfos () as $ funcInfo ) {
4691
- /** @var FuncInfo $funcInfo */
4692
4782
$ funcMap [$ funcInfo ->name ->__toString ()] = $ funcInfo ;
4693
4783
4694
4784
// TODO: Don't use aliasMap for methodsynopsis?
@@ -4702,6 +4792,15 @@ function initPhpParser() {
4702
4792
}
4703
4793
}
4704
4794
4795
+ /** @var array<string, FuncInfo> $funcMapForManual */
4796
+ $ funcMapForManual = $ funcMap ;
4797
+
4798
+ foreach ($ fileInfos as $ fileInfo ) {
4799
+ foreach ($ fileInfo ->getAllNonExistentDefaultConstructorsForManual ($ classMap ) as $ funcInfo ) {
4800
+ $ funcMapForManual [$ funcInfo ->name ->__toString ()] = $ funcInfo ;
4801
+ }
4802
+ }
4803
+
4705
4804
if ($ verify ) {
4706
4805
$ errors = [];
4707
4806
@@ -4817,7 +4916,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc
4817
4916
if ($ generateMethodSynopses ) {
4818
4917
$ methodSynopsesDirectory = getcwd () . "/methodsynopses " ;
4819
4918
4820
- $ methodSynopses = generateMethodSynopses ($ funcMap , $ aliasMap );
4919
+ $ methodSynopses = generateMethodSynopses ($ funcMapForManual , $ aliasMap );
4821
4920
if (!empty ($ methodSynopses )) {
4822
4921
if (!file_exists ($ methodSynopsesDirectory )) {
4823
4922
mkdir ($ methodSynopsesDirectory );
@@ -4832,7 +4931,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc
4832
4931
}
4833
4932
4834
4933
if ($ replaceMethodSynopses ) {
4835
- $ methodSynopses = replaceMethodSynopses ($ targetSynopses , $ funcMap , $ aliasMap , $ verify );
4934
+ $ methodSynopses = replaceMethodSynopses ($ targetSynopses , $ funcMapForManual , $ aliasMap , $ verify );
4836
4935
4837
4936
foreach ($ methodSynopses as $ filename => $ content ) {
4838
4937
if (file_put_contents ($ filename , $ content )) {
0 commit comments