cluaupp 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +12 -7
  3. package/bin/cluau.js +1 -1
  4. package/bin/cluaupp.js +1 -1
  5. package/docs/README.md +1 -1
  6. package/docs/architecture.md +52 -77
  7. package/docs/cli.md +29 -9
  8. package/docs/comparison.md +3 -3
  9. package/docs/config.md +6 -6
  10. package/docs/cpp-organization.md +2 -2
  11. package/docs/examples/index.md +2 -0
  12. package/docs/getting-started.md +7 -5
  13. package/docs/intellisense.md +49 -31
  14. package/docs/intro.md +2 -2
  15. package/docs/oop/file-tags.md +16 -17
  16. package/docs/oop/index.md +2 -2
  17. package/docs/oop/modules.md +3 -1
  18. package/docs/oop/services.md +7 -14
  19. package/docs/syntax.md +6 -5
  20. package/editors/vscode/extension.js +97 -146
  21. package/editors/vscode/package.json +6 -6
  22. package/examples/README.md +18 -0
  23. package/examples/game/.clangd +25 -0
  24. package/examples/game/.vscode/c_cpp_properties.json +27 -0
  25. package/examples/game/.vscode/extensions.json +5 -0
  26. package/examples/game/.vscode/settings.json +27 -0
  27. package/examples/game/Packages/.gitkeep +0 -0
  28. package/examples/game/cluaupp.config.json +6 -0
  29. package/examples/game/compile_flags.txt +6 -0
  30. package/examples/game/default.project.json +39 -0
  31. package/examples/game/package.json +9 -0
  32. package/examples/game/rokit.toml +5 -0
  33. package/examples/game/src/client/hud.client.cpp +12 -0
  34. package/{src → examples/game/src}/client/init.client.cpp +1 -0
  35. package/examples/game/src/server/combat.server.cpp +23 -0
  36. package/{src → examples/game/src}/server/leaderstats.server.cpp +1 -0
  37. package/examples/game/wally.toml +11 -0
  38. package/generated/api.js +51 -0
  39. package/generated/architecture.js +473 -0
  40. package/generated/ast.js +2 -0
  41. package/generated/cli.js +191 -0
  42. package/generated/compile.js +115 -0
  43. package/generated/editor-install.js +170 -0
  44. package/generated/emit.js +503 -0
  45. package/generated/emitter/luau-codegen.js +167 -0
  46. package/generated/emitter/translators.js +164 -0
  47. package/generated/headers.js +220 -0
  48. package/generated/index.html +49 -0
  49. package/generated/intellisense.js +277 -0
  50. package/generated/layout.js +112 -0
  51. package/generated/lex.js +146 -0
  52. package/generated/libs.js +484 -0
  53. package/generated/lsp.js +55 -0
  54. package/generated/package-info.js +11 -0
  55. package/generated/parse.js +607 -0
  56. package/generated/parser/collector.js +100 -0
  57. package/generated/parser/index.js +30 -0
  58. package/generated/preprocess.js +181 -0
  59. package/generated/system-understander.js +443 -0
  60. package/generated/transpile.js +66 -0
  61. package/generated/types.js +2 -0
  62. package/generated/understand.js +298 -0
  63. package/generated/utils/process-orchestrator.js +63 -0
  64. package/generated/utils/project.js +491 -0
  65. package/generated/utils/rojo-mapper.js +181 -0
  66. package/generated/utils/safe-paths.js +104 -0
  67. package/package.json +25 -8
  68. package/src/api.ts +53 -0
  69. package/src/{architecture.js → architecture.ts} +80 -33
  70. package/src/ast.ts +37 -0
  71. package/src/cli.ts +214 -0
  72. package/src/compile.ts +118 -0
  73. package/src/editor-install.ts +182 -0
  74. package/src/{emit.js → emit.ts} +5 -6
  75. package/src/emitter/luau-codegen.ts +187 -0
  76. package/src/emitter/translators.ts +168 -0
  77. package/src/headers.ts +233 -0
  78. package/src/intellisense.ts +286 -0
  79. package/src/{layout.js → layout.ts} +114 -129
  80. package/src/{lex.js → lex.ts} +4 -6
  81. package/src/{libs.js → libs.ts} +119 -46
  82. package/src/lsp.ts +60 -0
  83. package/src/package-info.ts +7 -0
  84. package/src/{parse.js → parse.ts} +3 -4
  85. package/src/parser/collector.ts +115 -0
  86. package/src/parser/index.ts +27 -0
  87. package/src/{preprocess.js → preprocess.ts} +64 -32
  88. package/src/system-understander.ts +501 -0
  89. package/src/transpile.ts +64 -0
  90. package/src/tree-sitter-cpp.d.ts +4 -0
  91. package/src/types.ts +81 -0
  92. package/src/{understand.js → understand.ts} +24 -213
  93. package/src/utils/process-orchestrator.ts +72 -0
  94. package/src/utils/project.ts +506 -0
  95. package/src/utils/rojo-mapper.ts +190 -0
  96. package/src/utils/safe-paths.ts +98 -0
  97. package/templates/game/.clangd +9 -0
  98. package/templates/game/.vscode/c_cpp_properties.json +1 -1
  99. package/templates/game/.vscode/extensions.json +5 -6
  100. package/templates/game/.vscode/settings.json +7 -6
  101. package/templates/game/cluaupp.config.json +2 -2
  102. package/templates/game/compile_flags.txt +1 -0
  103. package/templates/game/rokit.toml +5 -0
  104. package/templates/game/src/client/init.client.cpp +1 -0
  105. package/templates/game/src/server/leaderstats.server.cpp +1 -0
  106. package/src/api.js +0 -57
  107. package/src/cli.js +0 -481
  108. package/src/compile.js +0 -56
  109. package/src/editor-install.js +0 -218
  110. package/src/intellisense.js +0 -1368
  111. package/src/lsp.js +0 -227
  112. /package/{src → examples/game/src}/shared/config.cpp +0 -0
  113. /package/{src → examples/game/src}/shared/config.h +0 -0
@@ -0,0 +1,484 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MODULE_COLON = exports.LIBRARY_METHODS = exports.LIBRARY_TYPES = exports.EXTRA_TYPE_EXPORTS = exports.TYPE_EXPORTS = exports.INCLUDE_TO_MODULE = exports.MODULES = void 0;
7
+ exports.isLibraryType = isLibraryType;
8
+ exports.isLibraryMethod = isLibraryMethod;
9
+ exports.collectLibraries = collectLibraries;
10
+ exports.requireCluauppLib = requireCluauppLib;
11
+ exports.emitRequires = emitRequires;
12
+ exports.insertRequires = insertRequires;
13
+ exports.insertModuleRequires = insertModuleRequires;
14
+ exports.insertPreamble = insertPreamble;
15
+ // @ts-nocheck
16
+ const node_path_1 = __importDefault(require("node:path"));
17
+ const TYPE_EXPORTS = {
18
+ Janitor: "Janitor",
19
+ Promise: "Promise",
20
+ Net: "Net",
21
+ Icon: "Icon",
22
+ StateMachine: "StateMachine",
23
+ Spring: "Spring",
24
+ StickyBillboard: "StickyBillboard",
25
+ EzVisualz: "EzVisualz",
26
+ Module3D: "Module3D",
27
+ MathUtils: "MathUtils",
28
+ Twinkle: "Twinkle",
29
+ VfxUtil: "VfxUtil",
30
+ FormatNumber: "FormatNumber",
31
+ Fusion: "Fusion",
32
+ Iris: "Iris",
33
+ Cmdr: "Cmdr",
34
+ Chrono: "Chrono",
35
+ DataService: "DataService",
36
+ Display: "Display",
37
+ };
38
+ exports.TYPE_EXPORTS = TYPE_EXPORTS;
39
+ const EXTRA_TYPE_EXPORTS = {
40
+ DataService: {
41
+ Data: "Data",
42
+ DataPath: "Path",
43
+ DataServiceServer: "ServerApi",
44
+ DataServiceClient: "ClientApi",
45
+ },
46
+ };
47
+ exports.EXTRA_TYPE_EXPORTS = EXTRA_TYPE_EXPORTS;
48
+ const MODULES = {
49
+ Janitor: { file: "Janitor", bind: "Janitor" },
50
+ Promise: { file: "Promise", bind: "Promise" },
51
+ Net: { file: "Net", bind: "Net" },
52
+ NetEvent: { file: "Net", bind: "Net" },
53
+ NetFunction: { file: "Net", bind: "Net" },
54
+ MathUtils: { file: "MathUtils", bind: "MathUtils" },
55
+ FormatNumber: { file: "FormatNumber", bind: "FormatNumber" },
56
+ Module3D: { file: "Module3D", bind: "Module3D" },
57
+ Model3D: { file: "Module3D", bind: "Module3D" },
58
+ Twinkle: { file: "Twinkle", bind: "Twinkle" },
59
+ DataService: { file: "DataService", bind: "DataService" },
60
+ EzVisualz: { file: "EzVisualz", bind: "EzVisualz" },
61
+ EzVisual: { file: "EzVisualz", bind: "EzVisualz" },
62
+ Spring: { file: "Spring", bind: "Spring" },
63
+ Display: { file: "Display", bind: "Display" },
64
+ StickyBillboard: { file: "StickyBillboard", bind: "StickyBillboard" },
65
+ Icon: { file: "TopbarPlus", bind: "Icon" },
66
+ TopbarPlus: { file: "TopbarPlus", bind: "Icon" },
67
+ Cmdr: { file: "Cmdr", bind: "Cmdr" },
68
+ Chrono: { file: "Chrono", bind: "Chrono" },
69
+ Iris: { file: "Iris", bind: "Iris" },
70
+ Fusion: { file: "Fusion", bind: "Fusion" },
71
+ StateMachine: { file: "StateMachine", bind: "StateMachine" },
72
+ VfxUtil: { file: "VfxUtil", bind: "VfxUtil" },
73
+ ArrayIndexer: { file: "ArrayIndexer", bind: "ArrayIndexer" },
74
+ Occlude: { file: "Occlude", bind: "Occlude" },
75
+ };
76
+ exports.MODULES = MODULES;
77
+ const INCLUDE_TO_MODULE = {
78
+ janitor: "Janitor",
79
+ promise: "Promise",
80
+ net: "Net",
81
+ math: "MathUtils",
82
+ mathutils: "MathUtils",
83
+ formatnumber: "FormatNumber",
84
+ module3d: "Module3D",
85
+ dataservice: "DataService",
86
+ dataservicev2: "DataService",
87
+ ezvisual: "EzVisualz",
88
+ ezvisualz: "EzVisualz",
89
+ twinkle: "Twinkle",
90
+ spring: "Spring",
91
+ display: "Display",
92
+ stickybillboard: "StickyBillboard",
93
+ topbarplus: "Icon",
94
+ icon: "Icon",
95
+ cmdr: "Cmdr",
96
+ chrono: "Chrono",
97
+ iris: "Iris",
98
+ fusion: "Fusion",
99
+ statemachine: "StateMachine",
100
+ robloxstatemachine: "StateMachine",
101
+ vfx: "VfxUtil",
102
+ vfxutil: "VfxUtil",
103
+ arrayindexer: "ArrayIndexer",
104
+ occlude: "Occlude",
105
+ libs: null,
106
+ };
107
+ exports.INCLUDE_TO_MODULE = INCLUDE_TO_MODULE;
108
+ const LIBRARY_TYPES = new Set(Object.keys(MODULES));
109
+ exports.LIBRARY_TYPES = LIBRARY_TYPES;
110
+ const LIBRARY_METHODS = new Set([
111
+ "Add",
112
+ "AddObject",
113
+ "AddPromise",
114
+ "Remove",
115
+ "RemoveNoClean",
116
+ "RemoveList",
117
+ "RemoveListNoClean",
118
+ "GetAll",
119
+ "Cleanup",
120
+ "Destroy",
121
+ "LinkToInstance",
122
+ "LinkToInstances",
123
+ "Then",
124
+ "Catch",
125
+ "Finally",
126
+ "Await",
127
+ "Cancel",
128
+ "Fire",
129
+ "FireAll",
130
+ "On",
131
+ "OnClient",
132
+ "OnServer",
133
+ "Invoke",
134
+ "InvokeServer",
135
+ "InvokeClient",
136
+ "Attach3D",
137
+ "Update",
138
+ "SetCFrame",
139
+ "GetCFrame",
140
+ "SetDepthMultiplier",
141
+ "GetDepthMultiplier",
142
+ "GetPersisted",
143
+ "GetTransient",
144
+ "HasTransient",
145
+ "SetTransient",
146
+ "UpdateTransient",
147
+ "ClearTransient",
148
+ "ArrayInsert",
149
+ "ArrayInsertTransient",
150
+ "ArrayRemove",
151
+ "ArrayRemoveTransient",
152
+ "GetOrderedList",
153
+ "GetOrderedListWithPriority",
154
+ "GetChangedSignal",
155
+ "GetPathChangedSignal",
156
+ "GetIndexChangedSignal",
157
+ "GetArrayInsertedSignal",
158
+ "GetArrayRemovedSignal",
159
+ "Typed",
160
+ "WaitFor",
161
+ "WaitForData",
162
+ "HasData",
163
+ "GetProfile",
164
+ "GetBufferStats",
165
+ "Init",
166
+ "Observe",
167
+ "Impulse",
168
+ "SetGoal",
169
+ "Set",
170
+ "Get",
171
+ "Step",
172
+ "Fade",
173
+ "FrameSlide",
174
+ "FrameZoom",
175
+ "FrameBounce",
176
+ "ShowText",
177
+ "SetButtonStyle",
178
+ "FadeSlideRunoff",
179
+ "Abbreviate",
180
+ "Comma",
181
+ "Compact",
182
+ "Play",
183
+ "Pause",
184
+ "Resume",
185
+ "Stop",
186
+ "BindEvent",
187
+ "bindEvent",
188
+ "BindFunction",
189
+ "RegisterDefaultCommands",
190
+ "RegisterHook",
191
+ "RegisterType",
192
+ "RegisterCommand",
193
+ "ChangeState",
194
+ "GetState",
195
+ "GetCurrentState",
196
+ "GetPreviousState",
197
+ "GetData",
198
+ "ChangeData",
199
+ "LoadDirectory",
200
+ "setLabel",
201
+ "setImage",
202
+ "setEnabled",
203
+ "setName",
204
+ "setOrder",
205
+ "setWidth",
206
+ "align",
207
+ "setLeft",
208
+ "setMid",
209
+ "setRight",
210
+ "bindToggleItem",
211
+ "modifyTheme",
212
+ "setTheme",
213
+ "notify",
214
+ "clearNotices",
215
+ "select",
216
+ "deselect",
217
+ "autoDeselect",
218
+ "SetText",
219
+ "SetEnabled",
220
+ "SetMaxDistance",
221
+ "SetActive",
222
+ "GetActive",
223
+ "End",
224
+ "Scale",
225
+ "DestroyAfter",
226
+ "Burst",
227
+ "CloneOnto",
228
+ "Shutdown",
229
+ "Append",
230
+ "PushConfig",
231
+ "PopConfig",
232
+ "ForceRefresh",
233
+ ]);
234
+ exports.LIBRARY_METHODS = LIBRARY_METHODS;
235
+ const MODULE_COLON = new Set(["Attach3D", "RegisterDefaultCommands", "RegisterHook", "Connect", "LoadDirectory"]);
236
+ exports.MODULE_COLON = MODULE_COLON;
237
+ function isLibraryType(name) {
238
+ return LIBRARY_TYPES.has(name);
239
+ }
240
+ function isLibraryMethod(name) {
241
+ return LIBRARY_METHODS.has(name);
242
+ }
243
+ function walk(node, visit) {
244
+ if (!node || typeof node !== "object") {
245
+ return;
246
+ }
247
+ visit(node);
248
+ for (const value of Object.values(node)) {
249
+ if (Array.isArray(value)) {
250
+ for (const item of value) {
251
+ walk(item, visit);
252
+ }
253
+ }
254
+ else if (value && typeof value === "object") {
255
+ walk(value, visit);
256
+ }
257
+ }
258
+ }
259
+ function modulesFromIncludes(source) {
260
+ const found = new Set();
261
+ for (const line of String(source).split(/\r?\n/)) {
262
+ const match = line.match(/^\s*#\s*include\s+<cluaupp\/(?:libs\/)?([A-Za-z0-9]+)\.hpp>/);
263
+ if (!match) {
264
+ continue;
265
+ }
266
+ const key = match[1].toLowerCase();
267
+ const mapped = INCLUDE_TO_MODULE[key];
268
+ if (mapped) {
269
+ found.add(mapped);
270
+ }
271
+ if (key === "libs") {
272
+ found.add("Janitor");
273
+ found.add("Promise");
274
+ found.add("Net");
275
+ found.add("MathUtils");
276
+ found.add("FormatNumber");
277
+ found.add("Module3D");
278
+ found.add("Twinkle");
279
+ found.add("DataService");
280
+ }
281
+ }
282
+ return found;
283
+ }
284
+ function collectLibraries(source, ast) {
285
+ const used = modulesFromIncludes(source);
286
+ walk(ast, (node) => {
287
+ if (node.type === "ident" && MODULES[node.name]) {
288
+ used.add(node.name === "NetEvent" || node.name === "NetFunction" ? "Net" : node.name);
289
+ }
290
+ if (node.type === "new" && MODULES[node.className]) {
291
+ used.add(node.className === "NetEvent" || node.className === "NetFunction" ? "Net" : node.className);
292
+ }
293
+ if (node.type === "call" && node.object && node.object.type === "ident" && MODULES[node.object.name]) {
294
+ const name = node.object.name;
295
+ used.add(name === "NetEvent" || name === "NetFunction" ? "Net" : name);
296
+ }
297
+ });
298
+ const unique = [];
299
+ const seenBind = new Set();
300
+ for (const name of used) {
301
+ const spec = MODULES[name];
302
+ if (!spec || seenBind.has(spec.bind)) {
303
+ continue;
304
+ }
305
+ seenBind.add(spec.bind);
306
+ unique.push(spec);
307
+ }
308
+ return unique;
309
+ }
310
+ const ROJO_ROOTS = {
311
+ shared: { service: "ReplicatedStorage", expr: "ReplicatedStorage.Cluaupp" },
312
+ server: { service: "ServerScriptService", expr: "ServerScriptService.Cluaupp" },
313
+ client: { service: "StarterPlayer", expr: "StarterPlayer.StarterPlayerScripts.Cluaupp" },
314
+ };
315
+ const SERVICE_ORDER = ["ReplicatedStorage", "ServerScriptService", "StarterPlayer"];
316
+ const SERVICE_GET = {
317
+ ReplicatedStorage: 'const ReplicatedStorage = game:GetService("ReplicatedStorage")',
318
+ ServerScriptService: 'const ServerScriptService = game:GetService("ServerScriptService")',
319
+ StarterPlayer: 'const StarterPlayer = game:GetService("StarterPlayer")',
320
+ };
321
+ function requireCluauppLib(name) {
322
+ return `require(ReplicatedStorage.CluauppLibs.${name})`;
323
+ }
324
+ function parseOutRel(toOutRel) {
325
+ const posix = String(toOutRel || "module.luau")
326
+ .replace(/\\/g, "/")
327
+ .replace(/\.luau$/i, "");
328
+ const parts = posix.split("/").filter(Boolean);
329
+ const tree = parts[0];
330
+ const root = ROJO_ROOTS[tree] || null;
331
+ const rest = root ? parts.slice(1) : parts;
332
+ return { tree, root, rest, posix };
333
+ }
334
+ function robloxRequireFrom(_fromOutRel, toOutRel) {
335
+ const { root, rest } = parseOutRel(toOutRel);
336
+ if (root) {
337
+ const tail = rest.join(".");
338
+ return tail ? `require(${root.expr}.${tail})` : `require(${root.expr})`;
339
+ }
340
+ const fromDir = node_path_1.default.posix.dirname(String(_fromOutRel || "module.luau").replace(/\\/g, "/"));
341
+ const toMod = String(toOutRel || "module.luau")
342
+ .replace(/\\/g, "/")
343
+ .replace(/\.luau$/i, "");
344
+ let rel = node_path_1.default.posix.relative(fromDir, toMod);
345
+ if (!rel || rel === ".") {
346
+ rel = node_path_1.default.posix.basename(toMod);
347
+ }
348
+ const parts = rel.split("/");
349
+ let expr = "script.Parent";
350
+ for (const part of parts) {
351
+ if (part === "..") {
352
+ expr += ".Parent";
353
+ }
354
+ else if (part && part !== ".") {
355
+ expr += `.${part}`;
356
+ }
357
+ }
358
+ return `require(${expr})`;
359
+ }
360
+ function emitLibraryLines(libraries) {
361
+ const api = [];
362
+ const types = [];
363
+ for (const spec of libraries) {
364
+ api.push(`const ${spec.bind} = ${requireCluauppLib(spec.file)}`);
365
+ const exported = TYPE_EXPORTS[spec.bind];
366
+ if (exported) {
367
+ types.push(`type ${spec.bind} = ${spec.bind}.${exported}`);
368
+ }
369
+ const extra = EXTRA_TYPE_EXPORTS[spec.bind];
370
+ if (extra) {
371
+ for (const [alias, exportedName] of Object.entries(extra)) {
372
+ types.push(`type ${alias} = ${spec.bind}.${exportedName}`);
373
+ }
374
+ }
375
+ }
376
+ return { api, types };
377
+ }
378
+ function emitRequireParts(libraries) {
379
+ if (!libraries.length) {
380
+ return { api: "", types: "" };
381
+ }
382
+ const { api, types } = emitLibraryLines(libraries);
383
+ api.unshift(SERVICE_GET.ReplicatedStorage);
384
+ return {
385
+ api: `${api.join("\n")}\n`,
386
+ types: types.length ? `${types.join("\n")}\n` : "",
387
+ };
388
+ }
389
+ function emitRequires(libraries) {
390
+ const { api, types } = emitRequireParts(libraries);
391
+ return [api, types].filter((part) => Boolean(part && part.trim())).join("\n");
392
+ }
393
+ function insertRequires(luau, libraries) {
394
+ const block = emitRequires(libraries).trimEnd();
395
+ if (!block) {
396
+ return luau;
397
+ }
398
+ return insertBlock(luau, block);
399
+ }
400
+ function moduleIsUsed(luau, spec) {
401
+ if (String(luau).includes(spec.name)) {
402
+ return true;
403
+ }
404
+ const exported = [...((spec.exports && spec.exports.consts) || []), ...((spec.exports && spec.exports.structs) || [])];
405
+ return exported.some((name) => String(luau).includes(name));
406
+ }
407
+ function moduleRequireLines(modules, fromOutRel, luau) {
408
+ const lines = [];
409
+ const services = new Set();
410
+ const seen = new Set();
411
+ for (const spec of modules || []) {
412
+ if (!spec || !spec.name || seen.has(spec.name)) {
413
+ continue;
414
+ }
415
+ if (fromOutRel && !moduleIsUsed(luau, spec)) {
416
+ continue;
417
+ }
418
+ seen.add(spec.name);
419
+ const { root } = parseOutRel(spec.outRel);
420
+ if (root) {
421
+ services.add(root.service);
422
+ }
423
+ lines.push(`const ${spec.name} = ${robloxRequireFrom(fromOutRel, spec.outRel)}`);
424
+ for (const name of (spec.exports && spec.exports.consts) || []) {
425
+ if (name !== spec.name) {
426
+ lines.push(`const ${name} = ${spec.name}.${name}`);
427
+ }
428
+ }
429
+ if (((spec.exports && spec.exports.structs) || []).includes(spec.name) || (spec.exports && spec.exports.hasProtos)) {
430
+ lines.push(`type ${spec.name} = ${spec.name}.${spec.name}`);
431
+ }
432
+ }
433
+ return { lines, services };
434
+ }
435
+ function insertModuleRequires(luau, modules, fromOutRel) {
436
+ return insertPreamble(luau, modules, [], fromOutRel);
437
+ }
438
+ function stripServiceGets(luau, services) {
439
+ let next = String(luau);
440
+ for (const name of services) {
441
+ const line = SERVICE_GET[name];
442
+ if (!line) {
443
+ continue;
444
+ }
445
+ next = next.replace(new RegExp(`^${line.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n?`, "m"), "");
446
+ }
447
+ return next;
448
+ }
449
+ function insertPreamble(luau, modules, libraries, fromOutRel) {
450
+ const text = String(luau || "");
451
+ const trimmed = text.trim();
452
+ if (trimmed.startsWith("{") || trimmed.startsWith("[") || /\.json$/i.test(String(fromOutRel || ""))) {
453
+ return luau;
454
+ }
455
+ const { lines: moduleLines, services } = moduleRequireLines(modules, fromOutRel, luau);
456
+ const libList = libraries || [];
457
+ if (libList.length) {
458
+ services.add("ReplicatedStorage");
459
+ }
460
+ if (moduleLines.length === 0 && libList.length === 0) {
461
+ return luau;
462
+ }
463
+ const { api: libApi, types: libTypes } = emitLibraryLines(libList);
464
+ const blockLines = [];
465
+ for (const name of SERVICE_ORDER) {
466
+ if (services.has(name)) {
467
+ blockLines.push(SERVICE_GET[name]);
468
+ }
469
+ }
470
+ blockLines.push(...moduleLines);
471
+ blockLines.push(...libApi);
472
+ blockLines.push(...libTypes);
473
+ const body = stripServiceGets(luau, services);
474
+ return insertBlock(body, blockLines.join("\n"));
475
+ }
476
+ function insertBlock(luau, block) {
477
+ const match = String(luau).match(/^(?:--[^\n]*\n)+/);
478
+ if (!match) {
479
+ return `${block}\n${luau}`;
480
+ }
481
+ const insertAt = match[0].length;
482
+ const rest = luau.slice(insertAt).replace(/^\n*/, "\n");
483
+ return `${luau.slice(0, insertAt)}\n${block}\n${rest}`;
484
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.start = start;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const node_1 = require("vscode-languageserver/node");
9
+ const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
10
+ const intellisense_js_1 = require("./intellisense.js");
11
+ const package_info_js_1 = require("./package-info.js");
12
+ function uriPath(uri) {
13
+ let file = String(uri || "").replace(/^file:\/\//, "");
14
+ if (/^\/[A-Za-z]:/.test(file)) {
15
+ file = file.slice(1);
16
+ }
17
+ return decodeURIComponent(file);
18
+ }
19
+ function start(options = {}) {
20
+ const projectRoot = options.projectRoot || process.cwd();
21
+ const connection = (0, node_1.createConnection)(node_1.ProposedFeatures.all);
22
+ const documents = new node_1.TextDocuments(vscode_languageserver_textdocument_1.TextDocument);
23
+ connection.onInitialize(() => ({
24
+ capabilities: {
25
+ textDocumentSync: node_1.TextDocumentSyncKind.Full,
26
+ },
27
+ serverInfo: { name: "cluaupp", version: package_info_js_1.pkg.version },
28
+ }));
29
+ const publish = (document) => {
30
+ const file = uriPath(document.uri);
31
+ const items = (0, intellisense_js_1.diagnosticsFor)(document.getText(), file, {
32
+ filePath: file,
33
+ includeDirs: [node_path_1.default.dirname(file), node_path_1.default.join(projectRoot, "src"), node_path_1.default.join(projectRoot, "include")],
34
+ });
35
+ connection.sendDiagnostics({
36
+ uri: document.uri,
37
+ diagnostics: items.map((item) => ({
38
+ range: {
39
+ start: { line: Math.max(0, (item.line || 1) - 1), character: Math.max(0, (item.col || 1) - 1) },
40
+ end: { line: Math.max(0, (item.line || 1) - 1), character: Math.max(1, item.col || 1) },
41
+ },
42
+ severity: 1,
43
+ source: "cluaupp",
44
+ message: item.message,
45
+ })),
46
+ });
47
+ };
48
+ documents.onDidOpen((event) => publish(event.document));
49
+ documents.onDidChangeContent((event) => publish(event.document));
50
+ documents.onDidClose((event) => {
51
+ connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] });
52
+ });
53
+ documents.listen(connection);
54
+ connection.listen();
55
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pkg = exports.projectRoot = void 0;
7
+ const node_module_1 = require("node:module");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ exports.projectRoot = node_path_1.default.resolve(__dirname, "..");
10
+ const fromPkg = (0, node_module_1.createRequire)(node_path_1.default.join(exports.projectRoot, "package.json"));
11
+ exports.pkg = fromPkg("./package.json");