Skip to content

Commit 41e0440

Browse files
committed
[fix] ib-writer
1. Add Enum documentation blocks for all Enum types referenced by, ImmutableBase properties, displaying case names and backing values 2. Add default value column to property tables: #[Defaults] shows literal values, defaultValues() shows "(dynamic)", BackedEnum shows backing value, UnitEnum shows case name, ImmutableBase sub-objects show class name 3. Collect referenced Enums during type resolution and append Enum blocks after class blocks
1 parent 9292f91 commit 41e0440

2 files changed

Lines changed: 84 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# CHANGELOG
22

3+
## [4.1.1] - 2025-03-07
4+
5+
### Fixed
6+
#### ib-writer
7+
- Property tables now include a `default` column displaying default
8+
values from `#[Defaults]` attributes and `defaultValues()` overrides
9+
- Enum types referenced as property types now generate their own
10+
documentation blocks with case listings and backing values
11+
- BackedEnum defaults display the backing value; UnitEnum defaults
12+
display the case name; dynamic defaults from `defaultValues()`
13+
display as `(dynamic)`
14+
315
## [v4.1.0] - 2026-03-07
416

517
### Added

src/CLI/writer/Markdown.php

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use ReallifeKip\ImmutableBase\Attributes\Spec;
66
use ReallifeKip\ImmutableBase\CLI\Writer;
7+
use ReallifeKip\ImmutableBase\ImmutableBase;
78
use ReallifeKip\ImmutableBase\Types;
89
use ReflectionProperty;
910

@@ -25,6 +26,7 @@
2526
abstract class Markdown
2627
{
2728
public static array $header = [];
29+
public static array $enums = [];
2830
/**
2931
* Iterates all namespace groups and delegates each class to
3032
* Writer::buildClassBlock() for Markdown table generation.
@@ -42,6 +44,7 @@ public static function namespaceBlocksGenerate(array $namespaceGroups, array $cl
4244
$content = array_merge($content ?? [], Writer::buildClassBlock($entry, $classMap, $shortNameCount));
4345
}
4446
}
47+
$content = array_merge($content ?? [], self::enumBlocksGenerate());
4548

4649
return $content;
4750
}
@@ -71,8 +74,8 @@ public static function contentBlocksGenerate(array $classMap, array $entry)
7174
$content[] = $spec;
7275
}
7376
$content[] = '';
74-
$content[] = '|name|required|type|description|';
75-
$content[] = '|--|--|--|--|';
77+
$content[] = '|name|required|type|default|description|';
78+
$content[] = '|--|--|--|--|--|';
7679
foreach ($types as $type) {
7780
/** @var ReflectionProperty $propRef */
7881
$propRef = $type['propertyRef'] ?? $ref->getProperty($type['propertyName']);
@@ -90,8 +93,26 @@ public static function contentBlocksGenerate(array $classMap, array $entry)
9093
$shortname = end($shortname);
9194
$typename = "[$shortname](#$typename)";
9295
}
96+
if (enum_exists($type['typename']['string'])) {
97+
self::$enums[$type['typename']['string']] = true;
98+
}
99+
}
100+
$desc = $propDocs['desc'] ?: '-';
101+
$default = '-';
102+
if (isset($type['defaults'])) {
103+
$default = $type['defaults'];
104+
$default = match (true) {
105+
$default instanceof \BackedEnum => (string) $default->value,
106+
$default instanceof \UnitEnum => $default->name,
107+
$default instanceof ImmutableBase => $default::class,
108+
is_callable($default) => '(dynamic)',
109+
\is_array($default) => json_encode($default),
110+
$default === null => 'null',
111+
$default === false => 'false',
112+
default => (string) $default
113+
};
93114
}
94-
$content[] = "| {$type['propertyName']} | $required | $typename | " . ($propDocs['desc'] ?: '-') . ' |';
115+
$content[] = "| {$type['propertyName']} | $required | $typename | $default | $desc |";
95116
}
96117
$content[] = '';
97118
$content[] = '---';
@@ -136,9 +157,57 @@ final protected static function unionTypeNamesParser(array $type): string
136157
$shortname = explode('\\', $typename);
137158
$shortname = end($shortname);
138159

160+
if (enum_exists($typename)) {
161+
self::$enums[$typename] = true;
162+
}
163+
139164
return "[$shortname](#$typename)";
140165
}
141166

142167
return $typename;
143168
}
169+
/**
170+
* Generates Markdown documentation blocks for all Enum classes
171+
* referenced by ImmutableBase property types. Only Enums actually
172+
* used as property types are included. BackedEnum cases display
173+
* both name and backing value; UnitEnum cases display name only.
174+
*
175+
* @return list<string>
176+
*/
177+
public static function enumBlocksGenerate(): array
178+
{
179+
$content = [];
180+
181+
foreach (self::$enums as $enumClass => $_) {
182+
$ref = new \ReflectionEnum($enumClass);
183+
$shortName = $ref->getShortName();
184+
$isBacked = $ref->isBacked();
185+
186+
$content[] = "# {$shortName} {#{$enumClass}}";
187+
$content[] = '';
188+
189+
if ($isBacked) {
190+
$backingType = $ref->getBackingType()->getName();
191+
$content[] = "| case | value ({$backingType}) |";
192+
$content[] = '|--|--|';
193+
foreach ($ref->getCases() as $case) {
194+
/** @var \ReflectionEnumBackedCase $case */
195+
$value = $case->getBackingValue();
196+
$content[] = "| {$case->getName()} | {$value} |";
197+
}
198+
} else {
199+
$content[] = '| case |';
200+
$content[] = '|--|';
201+
foreach ($ref->getCases() as $case) {
202+
$content[] = "| {$case->getName()} |";
203+
}
204+
}
205+
206+
$content[] = '';
207+
$content[] = '---';
208+
$content[] = '';
209+
}
210+
211+
return $content;
212+
}
144213
}

0 commit comments

Comments
 (0)