Skip to content

Commit 9ad46b6

Browse files
committed
Added some rudimentary EnumUtil.MakeEnum support
1 parent adc1152 commit 9ad46b6

File tree

5 files changed

+122
-4
lines changed

5 files changed

+122
-4
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ Generated annotations are limited to
2020
- Frame Templates
2121
- Intrinsic Frame Templates
2222
- Limited support for inheritance, children, and <KeyValues>
23-
- Globals with a name ending in `Mixin`; some mixins may be missing
23+
- Mixins - some mixins, especially local ones, may be missing
2424
- "methods" for a given mixin
2525
- inheritance through `CreateFromMixins`
26+
- Enums created with `EnumUtil.MakeEnum`
2627

2728
Disclaimer: Generated annotations by their very nature are not 100% accurate and may be imprecise or missing altogether.
2829

annotation_branch_readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ Generated annotations are limited to
2222
- Frame Templates
2323
- Intrinsic Frame Templates
2424
- Limited support for inheritance, children, and <KeyValues>
25-
- Globals with a name ending in `Mixin`; some mixins may be missing
25+
- Mixins - some mixins, especially local ones, may be missing
2626
- "methods" for a given mixin
2727
- inheritance through `CreateFromMixins`
28+
- Enums created with `EnumUtil.MakeEnum`
2829

2930
Disclaimer: Generated annotations by their very nature are not 100% accurate and may be imprecise or missing altogether.
3031

bin/annotate

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ require_once __DIR__ . '/../vendor/autoload.php';
118118
$progressBar->advance();
119119
}
120120
$xmlFileParser->writeTemplatesFile('_templates.lua', $outputDir);
121+
$luaFileParser->writeEnumsFile('_enums.lua', $outputDir);
121122
$progressBar->finish();
122123

123124
$io->success('Done!');

src/LuaFileParser.php

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44

55
namespace App;
66

7+
/**
8+
* @phpstan-type AnnotationData array{lineNr: int, classAnnotation: string, annotated: string}
9+
*/
710
class LuaFileParser
811
{
912
/** @var array<string, array<string, array{lineNr: int, classAnnotation: string, annotated: string}> [filename => [mixin name => mixin data]] */
1013
private array $mixins = [];
14+
/** @var array<string, list<array{lineNr: int, enumAnnotation: null|string, typeAnnotation: string}>> [filename => list of enum data] */
15+
private array $enums = [];
1116
/** @var array<string, array<string, string> [filename => [function name => function data]] */
1217
private array $functions = [];
1318

@@ -21,7 +26,9 @@ public function parse(string $filename, string $prefixToStrip, ?string $linkPref
2126
$fileContents = file_get_contents($filename);
2227
if (str_starts_with($filename, $prefixToStrip)) {
2328
$linkFilename = substr($filename, strlen($prefixToStrip));
24-
$linkPrefix = $linkPrefix ? str_replace('//', '/', $linkPrefix . '/' . $linkFilename) : null;
29+
$linkPrefix = $linkPrefix
30+
? sprintf('%s/%s', rtrim($linkPrefix, '/'), ltrim($linkFilename, '/'))
31+
: null;
2532
}
2633

2734
$mixins = $this->extractMixins($fileContents, $linkPrefix);
@@ -30,6 +37,8 @@ public function parse(string $filename, string $prefixToStrip, ?string $linkPref
3037
if (!$this->mixAnnotationsIntoSource) {
3138
$functions = $this->extractFunctions($fileContents, $mixins, $linkPrefix);
3239
$this->functions[$filename] = $functions;
40+
} else {
41+
$this->enums[$filename] = $this->extractEnums($fileContents, $linkPrefix);
3342
}
3443
}
3544

@@ -41,6 +50,9 @@ public function writeAnnotationsToFile(string $filename, string $outDir, string
4150
foreach ($this->mixins[$filename] ?? [] as $funcInfo) {
4251
$byLine[$funcInfo['lineNr'] - 1] .= $funcInfo['classAnnotation'];
4352
}
53+
foreach ($this->enums[$filename] ?? [] as $enumInfo) {
54+
$byLine[$enumInfo['lineNr'] - 1] .= $enumInfo['typeAnnotation'];
55+
}
4456
$data = implode("\n", $byLine);
4557
} else {
4658
if (empty($this->mixins[$filename]) && empty($this->functions[$filename])) {
@@ -62,6 +74,25 @@ public function writeAnnotationsToFile(string $filename, string $outDir, string
6274
file_put_contents($targetFile, $data);
6375
}
6476

77+
public function writeEnumsFile(string $filename, string $outDir): void
78+
{
79+
$targetFile = $outDir . '/' . $filename . '.annotated.lua';
80+
if (!is_dir(dirname($targetFile))) {
81+
mkdir($outDir . '/' . dirname($filename), recursive: true);
82+
}
83+
84+
$data = "--- @meta _\n\n";
85+
foreach ($this->enums as $enums) {
86+
foreach ($enums as $enumInfo) {
87+
if ($enumInfo['enumAnnotation']) {
88+
$data .= $enumInfo['enumAnnotation'] . "\n\n";
89+
}
90+
}
91+
}
92+
93+
file_put_contents($targetFile, $data);
94+
}
95+
6596
private function extractMixins(string $fileContents, ?string $linkPrefix): array
6697
{
6798
$mixins = [];
@@ -194,6 +225,88 @@ private function extractFunctions(string $fileContents, array $mixins, ?string $
194225
return $functions;
195226
}
196227

228+
private function extractEnums(string $fileContents, ?string $linkPrefix): array
229+
{
230+
$enums = [];
231+
// e.g. `local foo = EnumUtil.MakeEnum("firstValue", "secondValue", "Value3")`
232+
// e.g. `foo = EnumUtil.MakeEnum("firstValue", "secondValue", "Value3")`
233+
// e.g. `Something.Foo = EnumUtil.MakeEnum("firstValue", "secondValue", "Value3")`
234+
$regex = '/^(?<local>local )?(?<name>\S+) = EnumUtil\.MakeEnum\((?<values>(?:\s*"[^",]+?",?\s*(?:--\s*(?<comment>[^\n]+\n))?)+)\)/m';
235+
$valueRegex = '/(?<value>"[^",]+?"),?\s*(?:--\s*(?<comment>[^\n]+))?/m';
236+
$matches = [];
237+
preg_match_all(
238+
$regex,
239+
$fileContents,
240+
$matches,
241+
PREG_SET_ORDER | PREG_OFFSET_CAPTURE,
242+
);
243+
foreach ($matches as $match) {
244+
$isLocal = $match['local'][1] !== -1;
245+
$enumName = $match['name'][0];
246+
$enumValuesRaw = $match['values'][0];
247+
$enumValues = [];
248+
$valueComments = [];
249+
$valueMatches = [];
250+
preg_match_all($valueRegex, $enumValuesRaw, $valueMatches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
251+
foreach ($valueMatches as $valueMatch) {
252+
$value = $valueMatch['value'][0];
253+
if (isset($valueMatch['comment']) && $valueMatch['comment'][1] !== -1) {
254+
$valueComments[] = ' -- ' . $valueMatch['comment'][0];
255+
} else {
256+
$valueComments[] = '';
257+
}
258+
$enumValues[] = $value;
259+
}
260+
261+
// --- @type {["firstValue"] = 1, ["secondValue"] = 2, ["value3"] = 3}
262+
$typeAnnotation = sprintf(
263+
'--- @type {%s}',
264+
implode(
265+
', ',
266+
array_map(
267+
fn (string $v, int $i) => sprintf(
268+
'[%s]: %d',
269+
str_replace("\n", ' ', $v),
270+
$i + 1,
271+
),
272+
$enumValues,
273+
array_keys($enumValues),
274+
),
275+
),
276+
);
277+
$lineNr = $this->getLineNrFromOffset($fileContents, $match['name'][1]);
278+
if ($isLocal) {
279+
$enumAnnotation = null;
280+
} else {
281+
$typeAnnotation .= sprintf(' See [%s](lua://%s)', $enumName, $enumName);
282+
$enumAnnotation = sprintf(
283+
"--- @enum %s\nlocal %s = {\n %s\n}",
284+
$enumName,
285+
str_replace('.', '_', $enumName),
286+
implode(
287+
"\n ",
288+
array_map(
289+
fn (string $v, int $i, string $comment) => sprintf('[%s] = %d,%s', $v, $i + 1, $comment),
290+
$enumValues,
291+
array_keys($enumValues),
292+
$valueComments,
293+
),
294+
),
295+
);
296+
if ($linkPrefix) {
297+
$enumAnnotation = "--- [Source]($linkPrefix#L$lineNr)\n$enumAnnotation";
298+
}
299+
}
300+
$enums[] = [
301+
'lineNr' => $lineNr,
302+
'enumAnnotation' => $enumAnnotation,
303+
'typeAnnotation' => $typeAnnotation,
304+
];
305+
}
306+
307+
return $enums;
308+
}
309+
197310
private function getLineNrFromOffset(string $file, int $offset): int
198311
{
199312
return substr_count($file, "\n", 0, $offset) + 1;

src/XmlFileParser.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ public function writeAnnotationsToFile(string $filename, string $outDir, string
173173

174174
if (str_starts_with($filename, $prefixToStrip)) {
175175
$filename = substr($filename, strlen($prefixToStrip));
176-
$linkPrefix = $linkPrefix ? str_replace('//', '/', $linkPrefix . '/' . $filename) : null;
176+
$linkPrefix = $linkPrefix
177+
? sprintf('%s/%s', rtrim($linkPrefix, '/'), ltrim($filename, '/'))
178+
: null;
177179
}
178180
$targetFile = $outDir . '/' . $filename . '.annotated.lua';
179181
if (!is_dir(dirname($targetFile))) {

0 commit comments

Comments
 (0)