@@ -103,19 +103,20 @@ private function parseNode(SimpleXMLElement $node, Registry $fileRegistry, strin
103103 }
104104 $ isIntrinsic = (string ) ($ node ->attributes ()['intrinsic ' ] ?? '' ) === 'true ' ;
105105 $ isTemplate = (string ) ($ node ->attributes ()['virtual ' ] ?? '' ) === 'true ' ;
106+ $ isProtected = (string ) ($ node ->attributes ()['protected ' ] ?? '' ) === 'true ' ;
106107
107108 $ type = $ node ->getName ();
108109 if (isset (self ::TYPE_ALIASSES [$ type ])) {
109110 $ type = self ::TYPE_ALIASSES [$ type ];
110111 }
111112 if ($ isIntrinsic ) {
112- $ frame = new Intrinsic ($ name , $ type , $ node , $ parent );
113+ $ frame = new Intrinsic ($ name , $ type , $ node , $ isProtected , $ parent );
113114 $ this ->intrinsicRegistry ->register ($ frame ->getClassName (), $ frame );
114115 } elseif ($ isTemplate ) {
115- $ frame = new Template ($ name , $ type , $ node , $ parent );
116+ $ frame = new Template ($ name , $ type , $ node , $ isProtected , $ parent );
116117 $ this ->templateRegistry ->register ($ frame ->getClassName (), $ frame );
117118 } else {
118- $ frame = new Frame ($ name , $ type , $ node , $ parent );
119+ $ frame = new Frame ($ name , $ type , $ node , $ isProtected , $ parent );
119120 $ this ->frameRegistry ->register ($ frame ->getClassName (), $ frame );
120121 }
121122 if (!empty ($ name )) {
@@ -163,6 +164,51 @@ private function parseNode(SimpleXMLElement $node, Registry $fileRegistry, strin
163164 }
164165 }
165166
167+ public function prepareProtectionStatus (): void
168+ {
169+ foreach ($ this ->templateRegistry ->all () as $ template ) {
170+ $ this ->checkProtectionState ($ template );
171+ }
172+ foreach ($ this ->frameRegistry ->all () as $ frame ) {
173+ $ this ->checkProtectionState ($ frame );
174+ }
175+ }
176+
177+ private function checkProtectionState (Frame $ frame ): void
178+ {
179+ if ($ frame ->isExplicitlyProtected ()) {
180+ $ frame ->setProtected (ProtectedEnum::PROTECTED );
181+ } else {
182+ foreach ($ this ->iterateInherits ($ frame ) as $ template ) {
183+ if ($ template ->isExplicitlyProtected ()) {
184+ $ frame ->setProtected (ProtectedEnum::PROTECTED );
185+
186+ break ;
187+ }
188+ if ($ template ->getProtected () === ProtectedEnum::IMPLICIT ) {
189+ $ frame ->setProtected (ProtectedEnum::IMPLICIT );
190+ }
191+ }
192+ if ($ frame ->getProtected () === ProtectedEnum::UNPROTECTED ) {
193+ foreach ($ frame ->getChildren () as $ child ) {
194+ $ this ->checkProtectionState ($ child );
195+ if ($ child ->getProtected () !== ProtectedEnum::UNPROTECTED ) {
196+ $ frame ->setProtected (ProtectedEnum::IMPLICIT );
197+ }
198+ }
199+ }
200+ }
201+ if ($ frame ->getProtected () !== ProtectedEnum::UNPROTECTED ) {
202+ $ parent = $ frame ->getParent ();
203+ while ($ parent ) {
204+ if ($ parent ->getProtected () === ProtectedEnum::UNPROTECTED ) {
205+ $ parent ->setProtected (ProtectedEnum::IMPLICIT );
206+ }
207+ $ parent = $ parent ->getParent ();
208+ }
209+ }
210+ }
211+
166212 public function writeAnnotationsToFile (string $ filename , string $ outDir , string $ prefixToStrip , ?string $ linkPrefix , bool $ includeScripts ): void
167213 {
168214 $ fileRegistry = $ this ->perFileRegistry [$ filename ] ?? null ;
@@ -295,6 +341,13 @@ private function writeFrame(Frame $frame, ?string $linkPrefix, ?string $typeOver
295341 if ($ linkPrefix ) {
296342 $ data .= "--- [Source]( $ linkPrefix#L " . $ frame ->getLineNumber () . ") \n" ;
297343 }
344+ if ($ frame ->getProtected () !== ProtectedEnum::UNPROTECTED ) {
345+ $ text = match ($ frame ->getProtected ()) {
346+ ProtectedEnum::PROTECTED => 'Explicitly protected ' ,
347+ ProtectedEnum::IMPLICIT => 'Implicitly protected ' ,
348+ };
349+ $ data .= "--- $ text \n" ;
350+ }
298351 if ($ frame ->getParent ()) {
299352 $ data .= '--- child of ' . ($ frame ->getParent ()->getName () ?: $ frame ->getParent ()->getClassName ());
300353 if ($ frame ->getOriginalParent () && $ frame ->getOriginalParent () !== $ frame ->getParent ()) {
@@ -380,6 +433,7 @@ private function writeClassAndFieldHints(Frame $frame): string
380433 }
381434 $ allParentKeys = [];
382435 $ allParentArrays = [];
436+ $ protected = [];
383437 foreach ($ frame ->getChildren () as $ child ) {
384438 $ typehint = $ this ->childHasInterestingData ($ child ) ? $ child ->getClassName () : null ;
385439 if (empty ($ typehint ) && 1 === count ($ child ->getInherits ())) {
@@ -388,24 +442,40 @@ private function writeClassAndFieldHints(Frame $frame): string
388442 $ typehint = $ typehint ?: $ child ->getType ();
389443 $ parentKeys = [];
390444 if ($ child ->getParentKey ()) {
445+ $ key = $ child ->getParentKey ();
391446 $ parentKeys [$ child ->getParentKey ()] = $ typehint ?: 'table ' ;
447+ if ($ child ->getProtected () !== ProtectedEnum::UNPROTECTED ) {
448+ $ protected [$ key ] = $ child ->getProtected ();
449+ }
392450 }
393451 foreach ($ this ->iterateInherits ($ child ) as $ inherit ) {
394- if ($ inherit ->getParentKey ()) {
452+ $ key = $ inherit ->getParentKey ();
453+ if ($ key ) {
395454 $ inheritTypehint = $ typehint ?: $ inherit ->getClassName ();
396- $ parentKeys [$ inherit ->getParentKey ()] = $ inheritTypehint ;
455+ $ parentKeys [$ key ] = $ inheritTypehint ;
456+ if ($ inherit ->getProtected () !== ProtectedEnum::UNPROTECTED ) {
457+ $ protected [$ key ] = $ inherit ->getProtected ();
458+ }
397459 }
398460 }
399461 $ allParentKeys [] = $ parentKeys ;
400462
401463 $ parentArrays = [];
402464 if ($ child ->getParentArray ()) {
403- $ parentArrays [$ child ->getParentArray ()] = $ typehint ?: 'table ' ;
465+ $ key = $ child ->getParentArray ();
466+ $ parentArrays [$ key ] = $ typehint ?: 'table ' ;
467+ if ($ child ->getProtected () !== ProtectedEnum::UNPROTECTED ) {
468+ $ protected [$ key ] = $ child ->getProtected ();
469+ }
404470 }
405471 foreach ($ this ->iterateInherits ($ child ) as $ inherit ) {
406- if ($ inherit ->getParentArray ()) {
472+ $ key = $ inherit ->getParentArray ();
473+ if ($ key ) {
407474 $ inheritTypehint = $ typehint ?: $ inherit ->getClassName ();
408- $ parentArrays [$ inherit ->getParentArray ()] ??= $ inheritTypehint ;
475+ $ parentArrays [$ key ] ??= $ inheritTypehint ;
476+ if ($ inherit ->getProtected () !== ProtectedEnum::UNPROTECTED ) {
477+ $ protected [$ key ] = $ inherit ->getProtected ();
478+ }
409479 }
410480 }
411481 $ allParentArrays [] = $ parentArrays ;
@@ -418,7 +488,15 @@ private function writeClassAndFieldHints(Frame $frame): string
418488 }
419489 }
420490 foreach ($ mergedParentKeys as $ key => $ types ) {
421- $ data .= '--- @field ' . $ key . ' ' . implode (' | ' , array_unique ($ types )) . "\n" ;
491+ $ data .= sprintf (
492+ "--- @field %s %s%s \n" ,
493+ $ key ,
494+ implode (' | ' , array_unique ($ types )),
495+ isset ($ protected [$ key ]) ? (' # ' . match ($ protected [$ key ]) {
496+ ProtectedEnum::PROTECTED => 'Explicitly protected ' ,
497+ ProtectedEnum::IMPLICIT => 'Implicitly protected ' ,
498+ }) : '' ,
499+ );
422500 }
423501
424502 $ mergedParentArrays = [];
0 commit comments