@@ -2217,10 +2217,10 @@ public function enterNode(Node $expr)
2217
2217
$isUnknownConstValue = false;
2218
2218
2219
2219
$evaluator = new ConstExprEvaluator(
2220
- static function (Expr $expr) use ($allConstInfos, &$isUnknownConstValue) {
2221
- // $expr is a ConstFetch with a name of a C macro here
2220
+ function (Expr $expr) use ($allConstInfos, &$isUnknownConstValue) {
2221
+ // $expr is a ConstFetch with a name of a C macro here. Class constants are not supported yet
2222
2222
if (!$expr instanceof Expr\ConstFetch) {
2223
- throw new Exception($this->getVariableTypeName() . " " . $this->name->__toString() . " has an unsupported value ");
2223
+ throw new Exception("Cannot evaluate expression ");
2224
2224
}
2225
2225
2226
2226
$constName = $expr->name->__toString();
@@ -2379,7 +2379,7 @@ abstract protected function getFieldSynopsisDefaultLinkend(): string;
2379
2379
abstract protected function getFieldSynopsisName(): string;
2380
2380
2381
2381
/** @param array<string, ConstInfo> $allConstInfos */
2382
- abstract protected function getFieldSynopsisValueString(array $allConstInfos): ?string;
2382
+ abstract public function getFieldSynopsisValueString(array $allConstInfos): ?string;
2383
2383
2384
2384
abstract public function discardInfoForOldPhpVersions(?int $minimumPhpVersionIdCompatibility): void;
2385
2385
@@ -2604,7 +2604,7 @@ protected function getFieldSynopsisName(): string
2604
2604
}
2605
2605
2606
2606
/** @param array<string, ConstInfo> $allConstInfos */
2607
- protected function getFieldSynopsisValueString(array $allConstInfos): ?string
2607
+ public function getFieldSynopsisValueString(array $allConstInfos): ?string
2608
2608
{
2609
2609
$value = EvaluatedValue::createFromExpression($this->value, null, $this->cValue, $allConstInfos);
2610
2610
if ($value->isUnknownConstValue) {
@@ -2939,7 +2939,7 @@ protected function getFieldSynopsisName(): string
2939
2939
}
2940
2940
2941
2941
/** @param array<string, ConstInfo> $allConstInfos */
2942
- protected function getFieldSynopsisValueString(array $allConstInfos): ?string
2942
+ public function getFieldSynopsisValueString(array $allConstInfos): ?string
2943
2943
{
2944
2944
return $this->defaultValueString;
2945
2945
}
@@ -3061,10 +3061,12 @@ public function __clone()
3061
3061
class EnumCaseInfo {
3062
3062
public string $name;
3063
3063
public ?Expr $value;
3064
+ public ?string $valueString;
3064
3065
3065
- public function __construct(string $name, ?Expr $value) {
3066
+ public function __construct(string $name, ?Expr $value, ?string $valueString ) {
3066
3067
$this->name = $name;
3067
3068
$this->value = $value;
3069
+ $this->valueString = $valueString;
3068
3070
}
3069
3071
3070
3072
/** @param array<string, ConstInfo> $allConstInfos */
@@ -3082,6 +3084,51 @@ public function getDeclaration(array $allConstInfos): string {
3082
3084
3083
3085
return $code;
3084
3086
}
3087
+
3088
+ /** @param array<string, ConstInfo> $allConstInfos */
3089
+ public function getEnumItemElement(DOMDocument $doc, array $allConstInfos): DOMElement
3090
+ {
3091
+ $enumItemElement = $doc->createElement("enumitem");
3092
+
3093
+ $enumItemElement->appendChild(new DOMText("\n "));
3094
+ $enumIdentifierElement = $doc->createElement("enumidentifier");
3095
+ $enumIdentifierElement->appendChild(new DOMText($this->name));
3096
+ $enumItemElement->appendChild($enumIdentifierElement);
3097
+
3098
+ $valueString = $this->getEnumValueString($allConstInfos);
3099
+ if ($valueString) {
3100
+ $enumValueElement = $doc->createElement("enumvalue");
3101
+ $enumItemElement->appendChild(new DOMText("\n "));
3102
+ $initializerElement = $doc->createElement("initializer", $valueString);
3103
+ $enumValueElement->appendChild($initializerElement);
3104
+ $enumItemElement->appendChild($enumValueElement);
3105
+ }
3106
+
3107
+ $enumItemElement->appendChild(new DOMText("\n "));
3108
+
3109
+ return $enumItemElement;
3110
+ }
3111
+
3112
+ /** @param array<string, ConstInfo> $allConstInfos */
3113
+ protected function getEnumValueString(array $allConstInfos): ?string
3114
+ {
3115
+ if ($this->value === null) {
3116
+ return null;
3117
+ };
3118
+
3119
+ $value = EvaluatedValue::createFromExpression($this->value, null, null, $allConstInfos);
3120
+ if ($value->isUnknownConstValue) {
3121
+ return null;
3122
+ }
3123
+
3124
+ if ($value->originatingConsts) {
3125
+ return implode("\n", array_map(function (ConstInfo $const) use ($allConstInfos) {
3126
+ return $const->getFieldSynopsisValueString($allConstInfos);
3127
+ }, $value->originatingConsts));
3128
+ }
3129
+
3130
+ return $this->valueString;
3131
+ }
3085
3132
}
3086
3133
3087
3134
class AttributeInfo {
@@ -3468,17 +3515,36 @@ public function getClassSynopsisDocument(array $classMap, array $allConstInfos):
3468
3515
* @param array<string, ConstInfo> $allConstInfos
3469
3516
*/
3470
3517
public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array $allConstInfos): ?DOMElement {
3518
+ $isEnum = $this->type === "enum";
3519
+
3520
+ $classSynopsis = $doc->createElement($isEnum ? "enumsynopsis" : "classsynopsis");
3521
+ $synopsisInfoName = $isEnum ? "synopsisinfo" : "classsynopsisinfo";
3471
3522
3472
- $classSynopsis = $doc->createElement("classsynopsis");
3473
- $classSynopsis->setAttribute("class", $this->type === "interface" ? "interface" : "class");
3523
+ if (!$isEnum) {
3524
+ $classSynopsis->setAttribute("class", $this->type);
3525
+ }
3474
3526
3475
3527
$exceptionOverride = $this->type === "class" && $this->isException($classMap) ? "exception" : null;
3528
+ $classSynopsis->appendChild(new DOMText("\n "));
3529
+
3476
3530
$ooElement = self::createOoElement($doc, $this, $exceptionOverride, true, null, 4);
3477
- if (!$ooElement) {
3478
- return null;
3531
+ if ($ooElement) {
3532
+ $classSynopsis->appendChild($ooElement);
3533
+ }
3534
+
3535
+ if ($isEnum) {
3536
+ $enumNameElement = $doc->createElement("enumname");
3537
+ $enumNameElement->appendChild(new DOMText($this->name->toString()));
3538
+ $classSynopsis->appendChild($enumNameElement);
3539
+
3540
+ if ($this->enumBackingType) {
3541
+ $classSynopsis->appendChild(new DOMText("\n "));
3542
+ $enumNameElement = $doc->createElement("modifier");
3543
+ $enumNameElement->setAttribute("role", "enum_backing_type");
3544
+ $enumNameElement->appendChild(new DOMText($this->enumBackingType->name));
3545
+ $classSynopsis->appendChild($enumNameElement);
3546
+ }
3479
3547
}
3480
- $classSynopsis->appendChild(new DOMText("\n "));
3481
- $classSynopsis->appendChild($ooElement);
3482
3548
3483
3549
foreach ($this->extends as $k => $parent) {
3484
3550
$parentInfo = $classMap[$parent->toString()] ?? null;
@@ -3502,6 +3568,11 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
3502
3568
$classSynopsis->appendChild($ooElement);
3503
3569
}
3504
3570
3571
+ // Enums implicitly implement either UnitEnum or BackEnum. This way inherited methods can be displayed.
3572
+ if ($isEnum) {
3573
+ $this->implements[] = new Name\FullyQualified($this->enumBackingType ? "BackedEnum" : "UnitEnum");
3574
+ }
3575
+
3505
3576
foreach ($this->implements as $k => $interface) {
3506
3577
$interfaceInfo = $classMap[$interface->toString()] ?? null;
3507
3578
if (!$interfaceInfo) {
@@ -3535,13 +3606,14 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
3535
3606
$doc,
3536
3607
$classSynopsis,
3537
3608
$parentsWithInheritedConstants,
3609
+ $synopsisInfoName,
3538
3610
"&Constants;",
3539
3611
"&InheritedConstants;"
3540
3612
);
3541
3613
3542
3614
if (!empty($this->constInfos)) {
3543
3615
$classSynopsis->appendChild(new DOMText("\n\n "));
3544
- $classSynopsisInfo = $doc->createElement("classsynopsisinfo" , "&Constants;");
3616
+ $classSynopsisInfo = $doc->createElement($synopsisInfoName , "&Constants;");
3545
3617
$classSynopsisInfo->setAttribute("role", "comment");
3546
3618
$classSynopsis->appendChild($classSynopsisInfo);
3547
3619
@@ -3552,9 +3624,22 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
3552
3624
}
3553
3625
}
3554
3626
3627
+ if (!empty($this->enumCaseInfos)) {
3628
+ $classSynopsis->appendChild(new DOMText("\n\n "));
3629
+ $classSynopsisInfo = $doc->createElement($synopsisInfoName, "&EnumCases;");
3630
+ $classSynopsisInfo->setAttribute("role", "comment");
3631
+ $classSynopsis->appendChild($classSynopsisInfo);
3632
+
3633
+ foreach ($this->enumCaseInfos as $enumCaseInfo) {
3634
+ $classSynopsis->appendChild(new DOMText("\n "));
3635
+ $enumItemElement = $enumCaseInfo->getEnumItemElement($doc, $allConstInfos);
3636
+ $classSynopsis->appendChild($enumItemElement);
3637
+ }
3638
+ }
3639
+
3555
3640
if (!empty($this->propertyInfos)) {
3556
3641
$classSynopsis->appendChild(new DOMText("\n\n "));
3557
- $classSynopsisInfo = $doc->createElement("classsynopsisinfo" , "&Properties;");
3642
+ $classSynopsisInfo = $doc->createElement($synopsisInfoName , "&Properties;");
3558
3643
$classSynopsisInfo->setAttribute("role", "comment");
3559
3644
$classSynopsis->appendChild($classSynopsisInfo);
3560
3645
@@ -3569,13 +3654,14 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
3569
3654
$doc,
3570
3655
$classSynopsis,
3571
3656
$parentsWithInheritedProperties,
3657
+ $synopsisInfoName,
3572
3658
"&Properties;",
3573
3659
"&InheritedProperties;"
3574
3660
);
3575
3661
3576
3662
if (!empty($this->funcInfos)) {
3577
3663
$classSynopsis->appendChild(new DOMText("\n\n "));
3578
- $classSynopsisInfo = $doc->createElement("classsynopsisinfo" , "&Methods;");
3664
+ $classSynopsisInfo = $doc->createElement($synopsisInfoName , "&Methods;");
3579
3665
$classSynopsisInfo->setAttribute("role", "comment");
3580
3666
$classSynopsis->appendChild($classSynopsisInfo);
3581
3667
@@ -3612,7 +3698,7 @@ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array
3612
3698
3613
3699
if (!empty($parentsWithInheritedMethods)) {
3614
3700
$classSynopsis->appendChild(new DOMText("\n\n "));
3615
- $classSynopsisInfo = $doc->createElement("classsynopsisinfo" , "&InheritedMethods;");
3701
+ $classSynopsisInfo = $doc->createElement($synopsisInfoName , "&InheritedMethods;");
3616
3702
$classSynopsisInfo->setAttribute("role", "comment");
3617
3703
$classSynopsis->appendChild($classSynopsisInfo);
3618
3704
@@ -3650,8 +3736,7 @@ private static function createOoElement(
3650
3736
): ?DOMElement {
3651
3737
$indentation = str_repeat(" ", $indentationLevel);
3652
3738
3653
- if ($classInfo->type !== "class" && $classInfo->type !== "interface") {
3654
- echo "Class synopsis generation is not implemented for " . $classInfo->type . "\n";
3739
+ if ($classInfo->type === "enum") {
3655
3740
return null;
3656
3741
}
3657
3742
@@ -3745,6 +3830,8 @@ private function collectInheritedMembers(
3745
3830
);
3746
3831
}
3747
3832
3833
+ $isEnum = $this->type === "enum";
3834
+
3748
3835
foreach ($this->implements as $parent) {
3749
3836
$parentInfo = $classMap[$parent->toString()] ?? null;
3750
3837
if (!$parentInfo) {
@@ -3758,13 +3845,25 @@ private function collectInheritedMembers(
3758
3845
$unusedParentsWithInheritedProperties = [];
3759
3846
$unusedParentsWithInheritedMethods = [];
3760
3847
3761
- $parentInfo->collectInheritedMembers(
3762
- $parentsWithInheritedConstants,
3763
- $unusedParentsWithInheritedProperties,
3764
- $unusedParentsWithInheritedMethods,
3765
- $hasConstructor,
3766
- $classMap
3767
- );
3848
+ if ($isEnum) {
3849
+ $parentInfo->collectInheritedMembers(
3850
+ $parentsWithInheritedConstants,
3851
+ $unusedParentsWithInheritedProperties,
3852
+ // We only want to collect inherited methods in case of enums
3853
+ $parentsWithInheritedMethods,
3854
+ $hasConstructor,
3855
+ $classMap
3856
+ );
3857
+ } else {
3858
+ $parentInfo->collectInheritedMembers(
3859
+ $parentsWithInheritedConstants,
3860
+ $unusedParentsWithInheritedProperties,
3861
+ // We only want to collect inherited methods in case of enums
3862
+ $unusedParentsWithInheritedMethods,
3863
+ $hasConstructor,
3864
+ $classMap
3865
+ );
3866
+ }
3768
3867
}
3769
3868
}
3770
3869
@@ -3886,14 +3985,14 @@ public function __clone()
3886
3985
/**
3887
3986
* @param Name[] $parents
3888
3987
*/
3889
- private function appendInheritedMemberSectionToClassSynopsis(DOMDocument $doc, DOMElement $classSynopsis, array $parents, string $label, string $inheritedLabel): void
3988
+ private function appendInheritedMemberSectionToClassSynopsis(DOMDocument $doc, DOMElement $classSynopsis, array $parents, string $synopsisInfoName, string $ label, string $inheritedLabel): void
3890
3989
{
3891
3990
if (empty($parents)) {
3892
3991
return;
3893
3992
}
3894
3993
3895
3994
$classSynopsis->appendChild(new DOMText("\n\n "));
3896
- $classSynopsisInfo = $doc->createElement("classsynopsisinfo" , "$inheritedLabel");
3995
+ $classSynopsisInfo = $doc->createElement($synopsisInfoName , "$inheritedLabel");
3897
3996
$classSynopsisInfo->setAttribute("role", "comment");
3898
3997
$classSynopsis->appendChild($classSynopsisInfo);
3899
3998
@@ -4738,7 +4837,10 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac
4738
4837
);
4739
4838
} else if ($classStmt instanceof Stmt\EnumCase) {
4740
4839
$enumCaseInfos[] = new EnumCaseInfo(
4741
- $classStmt->name->toString(), $classStmt->expr);
4840
+ $classStmt->name->toString(),
4841
+ $classStmt->expr,
4842
+ $prettyPrinter->prettyPrintExpr($classStmt->expr)
4843
+ );
4742
4844
} else {
4743
4845
throw new Exception("Not implemented {$classStmt->getType()}");
4744
4846
}
0 commit comments