Skip to content

Commit 70f58cc

Browse files
committed
Fix #69 show realm and wiki link on structs, enums, classes + fix inconsistent realm texts + workaround duplicate STENCIL enum definition on wiki
1 parent 0f3934e commit 70f58cc

File tree

10 files changed

+128
-83
lines changed

10 files changed

+128
-83
lines changed

__tests__/api-writer/glua-api-writer.spec.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ describe('GLua API Writer', () => {
102102
parent: '_G',
103103
dontDefineParent: true,
104104
description: 'Explodes with an optional intensity.',
105-
realm: 'Shared',
105+
realm: 'shared',
106106
type: 'libraryfunc',
107107
url: 'na',
108108
arguments: [
@@ -156,7 +156,7 @@ describe('GLua API Writer', () => {
156156
name: 'MATERIAL_FOG',
157157
address: 'Enums/MATERIAL_FOG',
158158
description: 'The fog mode.',
159-
realm: 'Client',
159+
realm: 'client',
160160
items: [
161161
{
162162
key: 'MATERIAL_FOG_NONE',
@@ -180,7 +180,7 @@ describe('GLua API Writer', () => {
180180
],
181181
});
182182

183-
expect(api).toEqual(`---@alias MATERIAL_FOG 0|1|-2147483648\n--- No fog\nMATERIAL_FOG_NONE = 0\n--- Linear fog\nMATERIAL_FOG_LINEAR = 1\nMATERIAL_FOG_LINEAR_BELOW_FOG_Z = -2147483648\n\n\n`);
183+
expect(api).toEqual(`---![(Client)](https://github.com/user-attachments/assets/a5f6ba64-374d-42f0-b2f4-50e5c964e808) The fog mode.\n---@alias MATERIAL_FOG 0|1|-2147483648\n--- No fog\nMATERIAL_FOG_NONE = 0\n--- Linear fog\nMATERIAL_FOG_LINEAR = 1\nMATERIAL_FOG_LINEAR_BELOW_FOG_Z = -2147483648\n\n\n`);
184184
});
185185

186186
it('should create enums for table enumerations', () => {
@@ -190,7 +190,7 @@ describe('GLua API Writer', () => {
190190
name: 'SCREENFADE',
191191
address: 'Enums/SCREENFADE',
192192
description: 'The screen fade mode.',
193-
realm: 'Client',
193+
realm: 'client',
194194
items: [
195195
{
196196
key: '',
@@ -224,7 +224,7 @@ describe('GLua API Writer', () => {
224224
],
225225
});
226226

227-
expect(api).toEqual(`---@enum SCREENFADE\n--- The screen fade mode.\nSCREENFADE = {\n --- Instant fade in\n IN = 1,\n --- Slowly fade in\n OUT = 2,\n MODULATE = 4,\n --- Never disappear\n STAYOUT = 8,\n --- Used to purge all currently active screen fade effects...\n --- Multiple\n --- Lines\n PURGE = 16,\n}\n\n`);
227+
expect(api).toEqual(`---![(Client)](https://github.com/user-attachments/assets/a5f6ba64-374d-42f0-b2f4-50e5c964e808) The screen fade mode.\n---@enum SCREENFADE\nSCREENFADE = {\n --- Instant fade in\n IN = 1,\n --- Slowly fade in\n OUT = 2,\n MODULATE = 4,\n --- Never disappear\n STAYOUT = 8,\n --- Used to purge all currently active screen fade effects...\n --- Multiple\n --- Lines\n PURGE = 16,\n}\n\n`);
228228
});
229229

230230
it('should convert table<type> to type[]', () => {
@@ -235,7 +235,7 @@ describe('GLua API Writer', () => {
235235
parent: 'player',
236236
dontDefineParent: true,
237237
description: 'Returns a table of all bots on the server.',
238-
realm: 'Shared',
238+
realm: 'shared',
239239
type: 'libraryfunc',
240240
url: 'na',
241241
returns: [
@@ -257,7 +257,7 @@ describe('GLua API Writer', () => {
257257
parent: 'player',
258258
dontDefineParent: true,
259259
description: 'Returns a table of all bots on the server.',
260-
realm: 'Shared',
260+
realm: 'shared',
261261
type: 'libraryfunc',
262262
url: 'na',
263263
returns: [
@@ -277,7 +277,7 @@ describe('GLua API Writer', () => {
277277
parent: 'test',
278278
dontDefineParent: true,
279279
description: 'Just for testing.',
280-
realm: 'Shared',
280+
realm: 'shared',
281281
type: 'libraryfunc',
282282
url: 'na',
283283
};
@@ -383,7 +383,7 @@ describe('GLua API Writer', () => {
383383
parent: 'Vector',
384384
dontDefineParent: true,
385385
description: 'Returns where on the screen the specified position vector would appear.',
386-
realm: 'Client',
386+
realm: 'client',
387387
type: 'libraryfunc',
388388
url: 'na',
389389
returns: [
@@ -406,7 +406,7 @@ describe('GLua API Writer', () => {
406406
parent: 'render',
407407
dontDefineParent: true,
408408
description: 'Sets the fog mode.',
409-
realm: 'Client',
409+
realm: 'client',
410410
type: 'libraryfunc',
411411
url: 'na',
412412
arguments: [

__tests__/test-data/offline-sites/gmod-wiki/class-function-weapon-allowsautoswitchto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const json = {
1313
name: 'AllowsAutoSwitchTo',
1414
address: 'Weapon:AllowsAutoSwitchTo',
1515
description: 'Returns whether the weapon allows to being switched to when a better ( [Weapon:GetWeight](https://wiki.facepunch.com/gmod/Weapon:GetWeight) ) weapon is being picked up.',
16-
realm: 'Shared',
16+
realm: 'shared',
1717
arguments: [],
1818
returns: [
1919
{

__tests__/test-data/offline-sites/gmod-wiki/enums-use.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const json = {
1515
name: 'USE',
1616
address: 'USE',
1717
description: `\nEnumerations used by [ENTITY:Use](https://wiki.facepunch.com/gmod/ENTITY:Use).\n\nNot to be confused with [Enums/_USE](https://wiki.facepunch.com/gmod/Enums/_USE) used by [Entity:SetUseType](https://wiki.facepunch.com/gmod/Entity:SetUseType).\n`,
18-
realm: 'Shared',
18+
realm: 'shared',
1919
items: [
2020
{
2121
key: 'USE_OFF',

__tests__/test-data/offline-sites/gmod-wiki/hook-player-initial-spawn.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ net.Receive( "cool_addon_client_ready", function( len, ply )
129129
-- Send what you need here!
130130
end )
131131
\`\`\`\n\n`,
132-
realm: 'Server',
132+
realm: 'server',
133133
arguments: [ { args: [
134134
{
135135
name: 'player',

__tests__/test-data/offline-sites/gmod-wiki/library-function-ai-getscheduleid.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const json = {
1616
name: 'GetScheduleID',
1717
address: 'ai.GetScheduleID',
1818
description: 'Translates a schedule name to its corresponding ID.',
19-
realm: 'Server',
19+
realm: 'server',
2020
arguments: [
2121
{ args: [ {
2222
name: 'sched',

__tests__/test-data/offline-sites/gmod-wiki/struct-ang-pos.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const json = {
1515
name: 'AngPos',
1616
address: 'AngPos',
1717
description: 'Table used by various functions, such as [Entity:GetAttachment](https://wiki.facepunch.com/gmod/Entity:GetAttachment).',
18-
realm: 'Shared',
18+
realm: 'shared',
1919
fields: [
2020
{
2121
name: 'Ang',

__tests__/test-data/offline-sites/gmod-wiki/struct-custom-entity-fields.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export const apiDefinition =
5252
---
5353
--- See also [Structures/ENT](https://wiki.facepunch.com/gmod/Structures/ENT)
5454
---
55+
---
56+
---[View wiki](https://wiki.facepunch.com/gmod/Custom_Entity_Fields)
5557
---@class Custom_Entity_Fields
5658
local Custom_Entity_Fields = {}
5759

custom/class.TOOL.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
--- Ensure that all tool file names are entirely lowercase. Including capital letters can lead to unintended behavior.
99
---
1010
---@class TOOL : Tool
11-
TOOL = {}
11+
TOOL = {}

src/api-writer/glua-api-writer.ts

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type IndexedWikiPage = {
4545

4646
export class GluaApiWriter {
4747
private readonly writtenClasses: Set<string> = new Set();
48+
private readonly writtenEnums: Set<string> = new Set();
4849
private readonly writtenLibraryGlobals: Set<string> = new Set();
4950
private readonly pageOverrides: Map<string, string> = new Map();
5051

@@ -81,7 +82,7 @@ export class GluaApiWriter {
8182
let api = '';
8283

8384
if (isClassFunction(page))
84-
api += this.writeClassStart(page.parent, undefined, page.deprecated);
85+
api += this.writeClassStart(page.parent, undefined, undefined, undefined, page.deprecated);
8586
else if (isLibraryFunction(page))
8687
api += this.writeLibraryGlobalFallback(page);
8788

@@ -108,15 +109,23 @@ export class GluaApiWriter {
108109
return this.writeClassGlobal(page);
109110
}
110111

111-
private writeClassStart(className: string, parent?: string, deprecated?: string, description?: string) {
112+
private writeClassStart(className: string, realm?: Realm, url?: string, parent?: string, deprecated?: string, description?: string) {
112113
let api: string = '';
113114

114115
if (!this.writtenClasses.has(className)) {
115116
const classOverride = `class.${className}`;
116117
if (this.pageOverrides.has(classOverride)) {
117118
api += this.pageOverrides.get(classOverride)!.replace(/\n$/g, '') + '\n\n';
118119
} else {
119-
api += description ? `${putCommentBeforeEachLine(description, false)}\n` : '';
120+
if (realm) {
121+
api += `---${this.formatRealm(realm)} ${description ? `${putCommentBeforeEachLine(description)}\n` : ''}\n`;
122+
} else {
123+
api += description ? `${putCommentBeforeEachLine(description, false)}\n` : '';
124+
}
125+
126+
if (url) {
127+
api += `---\n---[View wiki](${url})\n`;
128+
}
120129

121130
if (deprecated)
122131
api += `---@deprecated ${removeNewlines(deprecated)}\n`;
@@ -174,11 +183,11 @@ export class GluaApiWriter {
174183
}
175184

176185
private writeClassGlobal(page: TypePage) {
177-
return this.writeClassStart(page.name, page.parent, page.deprecated, page.description);
186+
return this.writeClassStart(page.name, page.realm, page.url, page.parent, page.deprecated, page.description);
178187
}
179188

180189
private writeClassFunction(func: ClassFunction) {
181-
let api: string = this.writeClassStart(func.parent, undefined, func.deprecated);
190+
let api: string = this.writeClassStart(func.parent, undefined, undefined, undefined, func.deprecated);
182191

183192
if (!func.arguments || func.arguments.length === 0) func.arguments = [{}];
184193
for (const argSet of func.arguments) {
@@ -206,7 +215,7 @@ export class GluaApiWriter {
206215
}
207216

208217
private writePanel(panel: Panel) {
209-
let api: string = this.writeClassStart(panel.name, panel.parent, panel.deprecated, panel.description);
218+
let api: string = this.writeClassStart(panel.name, undefined, undefined, panel.parent, panel.deprecated, panel.description);
210219

211220
return api;
212221
}
@@ -232,22 +241,32 @@ export class GluaApiWriter {
232241
? _enum.items[1]?.key.includes('.')
233242
: _enum.items[0]?.key.includes('.');
234243

244+
api += `---${this.formatRealm(_enum.realm)} ${_enum.description ? `${putCommentBeforeEachLine(_enum.description.trim())}` : ''}\n`;
245+
235246
if (_enum.deprecated)
236247
api += `---@deprecated ${removeNewlines(_enum.deprecated)}\n`;
237248

238249
if (isContainedInTable) {
239250
api += `---@enum ${_enum.name}\n`;
240251
} else {
252+
// TODO: Clean up this workaround when LuaLS supports global enumerations.
241253
// Until LuaLS supports global enumerations (https://github.com/LuaLS/lua-language-server/issues/2721) we
242-
// will use @alias as a workaround
243-
const validEnumerations = _enum.items.map(item => item.value)
244-
.filter(value => !isNaN(Number(value)))
245-
.join('|');
246-
api += `---@alias ${_enum.name} ${validEnumerations}\n`;
254+
// will use @alias as a workaround.
255+
// However since https://wiki.facepunch.com/gmod/Enums/STENCIL defines multiple enums in one page, we need to
256+
// be careful to only define an enum once.
257+
// TODO: This only works because both enum definitions for STENCIL have the values 1-8. If the latter enum
258+
// TODO: had different values, only the values of the first enum would be used.
259+
if (!this.writtenEnums.has(_enum.name)) {
260+
const validEnumerations = _enum.items.map(item => item.value)
261+
.filter(value => !isNaN(Number(value)))
262+
.join('|');
263+
api += `---@alias ${_enum.name} ${validEnumerations}\n`;
264+
}
247265
}
248266

267+
this.writtenEnums.add(_enum.name);
268+
249269
if (isContainedInTable) {
250-
api += _enum.description ? `${putCommentBeforeEachLine(_enum.description.trim(), false)}\n` : '';
251270
api += `${_enum.name} = {\n`;
252271
}
253272

@@ -301,7 +320,7 @@ export class GluaApiWriter {
301320
}
302321

303322
private writeStruct(struct: Struct) {
304-
let api: string = this.writeClassStart(struct.name, undefined, struct.deprecated, struct.description);
323+
let api: string = this.writeClassStart(struct.name, struct.realm, struct.url, undefined, struct.deprecated, struct.description);
305324

306325
for (const field of struct.fields) {
307326
if (field.deprecated)
@@ -321,7 +340,7 @@ export class GluaApiWriter {
321340
if (!this.files.has(filePath)) this.files.set(filePath, []);
322341

323342
pages.forEach(page => {
324-
this.files.get(filePath)!.push({index: index, page: page});
343+
this.files.get(filePath)!.push({ index: index, page: page });
325344
});
326345
}
327346

@@ -334,13 +353,22 @@ export class GluaApiWriter {
334353

335354
pages.sort((a, b) => a.index - b.index);
336355

337-
// First we write the "header" types
338-
for (const page of pages.filter(x => isClass(x.page) || isLibrary(x.page) || isPanel(x.page))) {
356+
// First we write the "header" types
357+
for (const page of pages.filter(x => isClass(x.page) || isLibrary(x.page) || isPanel(x.page))) {
358+
try {
339359
api += this.writePage(page.page);
360+
} catch (e) {
361+
console.error(`Failed to write 'header' page ${page.page.address}: ${e}`);
340362
}
341-
for (const page of pages.filter(x => !isClass(x.page) && !isLibrary(x.page) && !isPanel(x.page))) {
363+
}
364+
365+
for (const page of pages.filter(x => !isClass(x.page) && !isLibrary(x.page) && !isPanel(x.page))) {
366+
try {
342367
api += this.writePage(page.page);
368+
} catch (e) {
369+
console.error(`Failed to write page ${page.page.address}: ${e}`);
343370
}
371+
}
344372

345373
return api;
346374
}
@@ -410,17 +438,17 @@ export class GluaApiWriter {
410438
private formatRealm(realm: Realm) {
411439
// Formats to show the image, with the realm as the alt text
412440
switch (realm) {
413-
case 'Menu':
441+
case 'menu':
414442
return '![(Menu)](https://github.com/user-attachments/assets/62703d98-767e-4cf2-89b3-390b1c2c5cd9)';
415-
case 'Client':
443+
case 'client':
416444
return '![(Client)](https://github.com/user-attachments/assets/a5f6ba64-374d-42f0-b2f4-50e5c964e808)';
417-
case 'Server':
445+
case 'server':
418446
return '![(Server)](https://github.com/user-attachments/assets/d8fbe13a-6305-4e16-8698-5be874721ca1)';
419-
case 'Shared':
447+
case 'shared':
420448
return '![(Shared)](https://github.com/user-attachments/assets/a356f942-57d7-4915-a8cc-559870a980fc)';
421-
case 'Client and menu':
449+
case 'client and menu':
422450
return '![(Client and menu)](https://github.com/user-attachments/assets/25d1a1c8-4288-4a51-9867-5e3bb51b9981)';
423-
case 'Shared and Menu':
451+
case 'shared and menu':
424452
return '![(Shared and Menu)](https://github.com/user-attachments/assets/8f5230ff-38f7-493b-b9fc-cc70ffd5b3f4)';
425453
default:
426454
throw new Error(`Unknown realm: ${realm}`);

0 commit comments

Comments
 (0)