cluaupp 1.5.2 → 2.0.0-beta.2

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 (210) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +29 -41
  3. package/api/generated/bench-latest.json +43 -21
  4. package/api/generated/lsp-index.json +1 -1
  5. package/api/manifests/roblox-target.manifest.json +5 -5
  6. package/api/normalized/roblox-target.profile.json +8729 -267
  7. package/api/roblox/luau-builtins.d.luau +185 -0
  8. package/api/roblox/surface.json +1 -0
  9. package/api/roblox-api.lock.json +11 -2
  10. package/bin/cluaupp.js +38 -0
  11. package/editors/vscode/README.md +1 -1
  12. package/editors/vscode/package.json +50 -15
  13. package/editors/vscode/snippets/flare.json +1 -1
  14. package/editors/vscode/snippets/hive.json +1 -1
  15. package/editors/vscode/syntaxes/clpp.tmLanguage.json +211 -0
  16. package/examples/README.md +9 -9
  17. package/examples/game/cluaupp.config.json +2 -2
  18. package/examples/game/default.project.json +4 -15
  19. package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau +8 -0
  20. package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau.map.json +13 -0
  21. package/examples/game/out/ServerScriptService/Leaderstats.server.luau +26 -0
  22. package/examples/game/out/ServerScriptService/Leaderstats.server.luau.map.json +13 -0
  23. package/examples/game/out/ServerScriptService/Main.server.luau +15 -0
  24. package/examples/game/out/ServerScriptService/Main.server.luau.map.json +13 -0
  25. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau +10 -0
  26. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau.map.json +13 -0
  27. package/examples/game/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
  28. package/examples/game/src/ServerScriptService/Leaderstats.server.clp +18 -0
  29. package/examples/game/src/ServerScriptService/Main.server.clp +9 -0
  30. package/examples/game/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
  31. package/generated/api/build-profile.js +1 -1
  32. package/generated/api/loader.js +2 -2
  33. package/generated/api/surface/build.js +328 -0
  34. package/generated/api/surface/luau-defs.js +595 -0
  35. package/generated/api/surface/model.js +8 -0
  36. package/generated/api-cli.js +2 -2
  37. package/generated/cli.js +18 -17
  38. package/generated/clpp/contract.js +6 -3
  39. package/generated/clpp/handshake.js +36 -0
  40. package/generated/clpp/modules.js +20 -9
  41. package/generated/clpp/runner.js +62 -31
  42. package/generated/compile.js +18 -1
  43. package/generated/compiler/ast.js +3 -0
  44. package/generated/compiler/checker/calls.js +999 -0
  45. package/generated/compiler/checker/checker.js +1215 -0
  46. package/generated/compiler/checker/exprs.js +791 -0
  47. package/generated/compiler/checker/flow.js +168 -0
  48. package/generated/compiler/checker/members.js +763 -0
  49. package/generated/compiler/checker/statements.js +792 -0
  50. package/generated/compiler/checker/symbols.js +90 -0
  51. package/generated/compiler/checker/typeops.js +348 -0
  52. package/generated/compiler/checker/yields.js +115 -0
  53. package/generated/compiler/diagnostics.js +138 -0
  54. package/generated/compiler/emit/emitter.js +2356 -0
  55. package/generated/compiler/emit/luau-types.js +137 -0
  56. package/generated/compiler/emit/names.js +130 -0
  57. package/generated/compiler/emit/runtime.js +432 -0
  58. package/generated/compiler/lexer.js +403 -0
  59. package/generated/compiler/parser.js +1881 -0
  60. package/generated/compiler/project.js +332 -0
  61. package/generated/compiler/roblox/api.js +388 -0
  62. package/generated/compiler/roblox/context.js +100 -0
  63. package/generated/compiler/source.js +59 -0
  64. package/generated/compiler/stdlib.js +232 -0
  65. package/generated/compiler/types.js +250 -0
  66. package/generated/intellisense.js +1 -15
  67. package/generated/lsp.js +1 -1
  68. package/generated/target/build-cache.js +4 -4
  69. package/generated/target/datamodel-generate.js +12 -0
  70. package/generated/target/gen-rojo-tree.js +15 -0
  71. package/generated/target/source-map.js +61 -8
  72. package/generated/target/studio-bridge.js +1 -0
  73. package/generated/utils/project.js +104 -31
  74. package/include/README.md +5 -0
  75. package/native/bin/.gitkeep +1 -0
  76. package/package.json +17 -6
  77. package/plugins/CluauppNav/Plugin.luau +28 -4
  78. package/rust/cluaupp/Cargo.lock +795 -0
  79. package/rust/cluaupp/Cargo.toml +17 -0
  80. package/rust/cluaupp/src/main.rs +717 -0
  81. package/scripts/postinstall-native.js +56 -0
  82. package/skills/README.md +3 -3
  83. package/skills/clpp-hive-flare/SKILL.md +30 -26
  84. package/skills/clpp-language/SKILL.md +67 -74
  85. package/skills/clpp-language/compiler.md +24 -36
  86. package/skills/clpp-style/SKILL.md +31 -44
  87. package/src/api/build-profile.ts +1 -1
  88. package/src/api/loader.ts +2 -2
  89. package/src/api/surface/build.ts +374 -0
  90. package/src/api/surface/luau-defs.ts +635 -0
  91. package/src/api/surface/model.ts +96 -0
  92. package/src/api-cli.ts +2 -2
  93. package/src/cli.ts +19 -18
  94. package/src/clpp/contract.ts +20 -3
  95. package/src/clpp/handshake.ts +25 -0
  96. package/src/clpp/modules.ts +17 -10
  97. package/src/clpp/runner.ts +52 -34
  98. package/src/compile.ts +20 -2
  99. package/src/compiler/ast.ts +336 -0
  100. package/src/compiler/checker/calls.ts +1025 -0
  101. package/src/compiler/checker/checker.ts +1352 -0
  102. package/src/compiler/checker/exprs.ts +805 -0
  103. package/src/compiler/checker/flow.ts +174 -0
  104. package/src/compiler/checker/members.ts +793 -0
  105. package/src/compiler/checker/statements.ts +802 -0
  106. package/src/compiler/checker/symbols.ts +219 -0
  107. package/src/compiler/checker/typeops.ts +355 -0
  108. package/src/compiler/checker/yields.ts +120 -0
  109. package/src/compiler/diagnostics.ts +163 -0
  110. package/src/compiler/emit/emitter.ts +2486 -0
  111. package/src/compiler/emit/luau-types.ts +143 -0
  112. package/src/compiler/emit/names.ts +130 -0
  113. package/src/compiler/emit/runtime.ts +438 -0
  114. package/src/compiler/lexer.ts +444 -0
  115. package/src/compiler/parser.ts +1943 -0
  116. package/src/compiler/project.ts +354 -0
  117. package/src/compiler/roblox/api.ts +408 -0
  118. package/src/compiler/roblox/context.ts +108 -0
  119. package/src/compiler/source.ts +67 -0
  120. package/src/compiler/stdlib.ts +256 -0
  121. package/src/compiler/types.ts +313 -0
  122. package/src/intellisense.ts +1 -13
  123. package/src/lsp.ts +1 -1
  124. package/src/target/build-cache.ts +5 -8
  125. package/src/target/datamodel-generate.ts +12 -1
  126. package/src/target/gen-rojo-tree.ts +15 -0
  127. package/src/target/source-map.ts +65 -27
  128. package/src/target/studio-bridge.ts +3 -0
  129. package/src/types.ts +3 -0
  130. package/src/utils/project.ts +99 -37
  131. package/templates/README.md +7 -0
  132. package/templates/{game → game-modern}/cluaupp.config.json +2 -2
  133. package/templates/{game → game-modern}/package.json +1 -2
  134. package/templates/game-modern/rokit.toml +2 -0
  135. package/templates/game-modern/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
  136. package/templates/game-modern/src/ServerScriptService/Handlers/Guard.server.clp +4 -0
  137. package/templates/game-modern/src/ServerScriptService/Main.server.clp +8 -0
  138. package/templates/game-modern/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
  139. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +0 -29
  140. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +0 -13
  141. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +0 -83
  142. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +0 -13
  143. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +0 -18
  144. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +0 -13
  145. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +0 -14
  146. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +0 -13
  147. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +0 -15
  148. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +0 -13
  149. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +0 -50
  150. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +0 -13
  151. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +0 -12
  152. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +0 -13
  153. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +0 -16
  154. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +0 -13
  155. package/examples/game/src/Client/Controllers/DataController.client.clpp +0 -7
  156. package/examples/game/src/Client/Main.client.clpp +0 -4
  157. package/examples/game/src/Declarations/Net.flare +0 -5
  158. package/examples/game/src/Include/GameTypes.clh +0 -40
  159. package/examples/game/src/Modules/Core/Guard.server.clpp +0 -7
  160. package/examples/game/src/Modules/Core/PlayerHandler.server.clpp +0 -23
  161. package/examples/game/src/Server/Boot/DataBoot.server.clpp +0 -13
  162. package/examples/game/src/Server/Main.server.clpp +0 -4
  163. package/templates/game/.clangd +0 -25
  164. package/templates/game/.vscode/extensions.json +0 -8
  165. package/templates/game/.vscode/settings.json +0 -17
  166. package/templates/game/Packages/.gitkeep +0 -0
  167. package/templates/game/compile_flags.txt +0 -6
  168. package/templates/game/default.project.json +0 -41
  169. package/templates/game/include/clpp/datatypes.clh +0 -575
  170. package/templates/game/include/clpp/generated/enums.clh +0 -4920
  171. package/templates/game/include/clpp/generated/instances.clh +0 -87182
  172. package/templates/game/include/clpp/libs/arrayindexer.clh +0 -12
  173. package/templates/game/include/clpp/libs/axiom.clh +0 -154
  174. package/templates/game/include/clpp/libs/bloom.clh +0 -58
  175. package/templates/game/include/clpp/libs/coil.clh +0 -37
  176. package/templates/game/include/clpp/libs/crest.clh +0 -22
  177. package/templates/game/include/clpp/libs/echo.clh +0 -52
  178. package/templates/game/include/clpp/libs/ember.clh +0 -17
  179. package/templates/game/include/clpp/libs/flare.clh +0 -65
  180. package/templates/game/include/clpp/libs/gleam.clh +0 -111
  181. package/templates/game/include/clpp/libs/guide.clh +0 -42
  182. package/templates/game/include/clpp/libs/helm.clh +0 -31
  183. package/templates/game/include/clpp/libs/hive.clh +0 -20
  184. package/templates/game/include/clpp/libs/keep.clh +0 -158
  185. package/templates/game/include/clpp/libs/lens.clh +0 -24
  186. package/templates/game/include/clpp/libs/mint.clh +0 -28
  187. package/templates/game/include/clpp/libs/net.clh +0 -31
  188. package/templates/game/include/clpp/libs/occlude.clh +0 -15
  189. package/templates/game/include/clpp/libs/pin.clh +0 -28
  190. package/templates/game/include/clpp/libs/promise.clh +0 -24
  191. package/templates/game/include/clpp/libs/roster.clh +0 -123
  192. package/templates/game/include/clpp/libs/shift.clh +0 -22
  193. package/templates/game/include/clpp/libs/spark.clh +0 -28
  194. package/templates/game/include/clpp/libs/stage.clh +0 -23
  195. package/templates/game/include/clpp/libs/sweep.clh +0 -23
  196. package/templates/game/include/clpp/libs/trace.clh +0 -18
  197. package/templates/game/include/clpp/libs/ward.clh +0 -19
  198. package/templates/game/include/clpp/libs.clh +0 -31
  199. package/templates/game/include/clpp/roblox.clh +0 -41
  200. package/templates/game/rokit.toml +0 -5
  201. package/templates/game/src/Client/Controllers/DataController.client.clpp +0 -7
  202. package/templates/game/src/Client/Main.client.clpp +0 -4
  203. package/templates/game/src/Declarations/Net.flare +0 -5
  204. package/templates/game/src/Include/GameTypes.clh +0 -40
  205. package/templates/game/src/Modules/Core/Guard.server.clpp +0 -7
  206. package/templates/game/src/Modules/Core/PlayerHandler.server.clpp +0 -24
  207. package/templates/game/src/Server/Boot/DataBoot.server.clpp +0 -13
  208. package/templates/game/src/Server/Main.server.clpp +0 -4
  209. package/templates/game/stylua.toml +0 -9
  210. package/templates/game/wally.toml +0 -12
@@ -0,0 +1,595 @@
1
+ "use strict";
2
+ /**
3
+ * Parser for Luau definition files (`*.d.luau`, the luau-lsp format):
4
+ * `declare extern type X [extends Y] with … end`, `declare name: Type`, `declare function f(…): R`,
5
+ * `type Alias = Type`, `export type Alias<T> = Type`, `@deprecated` / `@[deprecated {use = "…"}]`.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.parseDefinitions = parseDefinitions;
9
+ const OPS = ["...", "->", "::", "@[", "(", ")", "{", "}", "[", "]", "<", ">", ",", ":", ";", "?", "|", "&", "=", ".", "@"];
10
+ function lex(text) {
11
+ const out = [];
12
+ let i = 0;
13
+ let line = 1;
14
+ while (i < text.length) {
15
+ const c = text[i];
16
+ if (c === "\n") {
17
+ line++;
18
+ i++;
19
+ continue;
20
+ }
21
+ if (c === " " || c === "\t" || c === "\r") {
22
+ i++;
23
+ continue;
24
+ }
25
+ if (c === "-" && text[i + 1] === "-") {
26
+ if (text.startsWith("--[[", i) || text.startsWith("--[=[", i)) {
27
+ const close = text.indexOf("]]", i);
28
+ const chunk = text.slice(i, close < 0 ? text.length : close + 2);
29
+ line += chunk.split("\n").length - 1;
30
+ i = close < 0 ? text.length : close + 2;
31
+ continue;
32
+ }
33
+ while (i < text.length && text[i] !== "\n") {
34
+ i++;
35
+ }
36
+ continue;
37
+ }
38
+ if (/[A-Za-z_]/.test(c)) {
39
+ let j = i + 1;
40
+ while (j < text.length && /[A-Za-z0-9_]/.test(text[j])) {
41
+ j++;
42
+ }
43
+ out.push({ t: "name", v: text.slice(i, j), line });
44
+ i = j;
45
+ continue;
46
+ }
47
+ if (/[0-9]/.test(c)) {
48
+ let j = i + 1;
49
+ while (j < text.length && /[0-9.]/.test(text[j])) {
50
+ j++;
51
+ }
52
+ out.push({ t: "number", v: text.slice(i, j), line });
53
+ i = j;
54
+ continue;
55
+ }
56
+ if (c === '"' || c === "'") {
57
+ let j = i + 1;
58
+ while (j < text.length && text[j] !== c) {
59
+ if (text[j] === "\\") {
60
+ j++;
61
+ }
62
+ j++;
63
+ }
64
+ out.push({ t: "string", v: text.slice(i + 1, j), line });
65
+ i = j + 1;
66
+ continue;
67
+ }
68
+ const op = OPS.find((o) => text.startsWith(o, i));
69
+ if (op) {
70
+ out.push({ t: "op", v: op, line });
71
+ i += op.length;
72
+ continue;
73
+ }
74
+ i++;
75
+ }
76
+ out.push({ t: "eof", v: "", line });
77
+ return out;
78
+ }
79
+ class DefParser {
80
+ toks;
81
+ i = 0;
82
+ /** Defaults of the generic parameters read last (`<T = BasePart>`). */
83
+ lastDefaults = {};
84
+ constructor(toks) {
85
+ this.toks = toks;
86
+ }
87
+ peek(n = 0) {
88
+ return this.toks[Math.min(this.i + n, this.toks.length - 1)];
89
+ }
90
+ next() {
91
+ return this.toks[this.i++] ?? this.toks[this.toks.length - 1];
92
+ }
93
+ is(v, n = 0) {
94
+ const t = this.peek(n);
95
+ return (t.t === "op" || t.t === "name") && t.v === v;
96
+ }
97
+ eat(v) {
98
+ if (this.is(v)) {
99
+ this.i++;
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ expect(v) {
105
+ if (!this.eat(v)) {
106
+ const t = this.peek();
107
+ throw new Error(`definitions: expected '${v}' at line ${t.line}, found '${t.v}'`);
108
+ }
109
+ }
110
+ name() {
111
+ const t = this.next();
112
+ if (t.t !== "name") {
113
+ throw new Error(`definitions: expected name at line ${t.line}, found '${t.v}'`);
114
+ }
115
+ return t.v;
116
+ }
117
+ file() {
118
+ const out = { metadata: {}, externs: [], declares: [], aliases: {}, aliasParams: {} };
119
+ while (this.peek().t !== "eof") {
120
+ const deprecated = this.attributes();
121
+ if (this.is("declare")) {
122
+ this.next();
123
+ if (this.is("extern")) {
124
+ this.next();
125
+ this.expect("type");
126
+ out.externs.push(this.externType());
127
+ continue;
128
+ }
129
+ if (this.is("class")) {
130
+ this.next();
131
+ out.externs.push(this.externType(true));
132
+ continue;
133
+ }
134
+ if (this.is("function")) {
135
+ this.next();
136
+ const name = this.name();
137
+ const fn = this.funcSignature(false);
138
+ out.declares.push({ name, type: fn, ...(deprecated ? { deprecated } : {}) });
139
+ continue;
140
+ }
141
+ const name = this.name();
142
+ this.expect(":");
143
+ const type = this.type();
144
+ out.declares.push({ name, type, ...(deprecated ? { deprecated } : {}) });
145
+ continue;
146
+ }
147
+ if (this.is("export")) {
148
+ this.next();
149
+ }
150
+ if (this.is("type")) {
151
+ this.next();
152
+ const name = this.name();
153
+ this.lastDefaults = {};
154
+ const params = this.genericParamNames();
155
+ const defaults = this.lastDefaults;
156
+ this.expect("=");
157
+ out.aliases[name] = substituteNames(this.type(), defaults);
158
+ if (params.length) {
159
+ out.aliasParams[name] = params;
160
+ }
161
+ continue;
162
+ }
163
+ this.next();
164
+ }
165
+ return out;
166
+ }
167
+ /** `@deprecated`, `@[deprecated {use = "X"}]`, `@checked` … — returns the deprecation, if any. */
168
+ attributes() {
169
+ let deprecated;
170
+ for (;;) {
171
+ if (this.is("@[")) {
172
+ this.next();
173
+ let depth = 1;
174
+ let sawDeprecated = false;
175
+ while (depth > 0 && this.peek().t !== "eof") {
176
+ const t = this.next();
177
+ if (t.t === "op" && (t.v === "[" || t.v === "@[")) {
178
+ depth++;
179
+ }
180
+ else if (t.t === "op" && t.v === "]") {
181
+ depth--;
182
+ }
183
+ else if (t.t === "name" && t.v === "deprecated") {
184
+ sawDeprecated = true;
185
+ deprecated = true;
186
+ }
187
+ else if (sawDeprecated && t.t === "string") {
188
+ deprecated = t.v;
189
+ }
190
+ }
191
+ continue;
192
+ }
193
+ if (this.is("@")) {
194
+ this.next();
195
+ const word = this.name();
196
+ if (word === "deprecated") {
197
+ deprecated = true;
198
+ }
199
+ continue;
200
+ }
201
+ return deprecated;
202
+ }
203
+ }
204
+ genericParamNames() {
205
+ const names = [];
206
+ if (this.eat("<")) {
207
+ while (!this.is(">") && this.peek().t !== "eof") {
208
+ const t = this.next();
209
+ if (t.t === "name") {
210
+ names.push(t.v);
211
+ }
212
+ if (this.eat("=")) {
213
+ const def = this.type();
214
+ if (t.t === "name") {
215
+ this.lastDefaults[t.v] = def;
216
+ }
217
+ }
218
+ this.eat("...");
219
+ this.eat(",");
220
+ }
221
+ this.expect(">");
222
+ }
223
+ return names;
224
+ }
225
+ externType(isClass = false) {
226
+ const line = this.peek().line;
227
+ const name = this.name();
228
+ let ext = null;
229
+ if (this.eat("extends")) {
230
+ ext = this.name();
231
+ }
232
+ if (!isClass) {
233
+ this.expect("with");
234
+ }
235
+ const members = [];
236
+ while (!this.is("end") && this.peek().t !== "eof") {
237
+ const deprecated = this.attributes();
238
+ if (this.is("function")) {
239
+ this.next();
240
+ const mname = this.name();
241
+ const fn = this.funcSignature(true);
242
+ members.push({ name: mname, fn, ...(deprecated ? { deprecated } : {}) });
243
+ continue;
244
+ }
245
+ if (this.is("[")) {
246
+ // indexer `[string]: any`
247
+ this.next();
248
+ this.type();
249
+ this.expect("]");
250
+ this.expect(":");
251
+ this.type();
252
+ continue;
253
+ }
254
+ if (this.peek().t === "name" && (this.is(":", 1))) {
255
+ const mname = this.name();
256
+ this.expect(":");
257
+ const type = this.type();
258
+ members.push({ name: mname, type, ...(deprecated ? { deprecated } : {}) });
259
+ continue;
260
+ }
261
+ if (this.is("read") || this.is("write")) {
262
+ this.next();
263
+ continue;
264
+ }
265
+ this.next();
266
+ }
267
+ this.expect("end");
268
+ return { name, extends: ext, members, line };
269
+ }
270
+ /** `(self, a: T, b: U?, ...: V): R` after the function name. */
271
+ funcSignature(method) {
272
+ const generics = this.genericParamNames();
273
+ this.expect("(");
274
+ const params = [];
275
+ let variadic;
276
+ let first = true;
277
+ while (!this.is(")") && this.peek().t !== "eof") {
278
+ if (this.eat("...")) {
279
+ variadic = this.eat(":") ? this.type() : { k: "name", name: "any" };
280
+ this.eat(",");
281
+ continue;
282
+ }
283
+ const pname = this.name();
284
+ if (first && method && pname === "self") {
285
+ if (this.eat(":")) {
286
+ this.type();
287
+ }
288
+ first = false;
289
+ this.eat(",");
290
+ continue;
291
+ }
292
+ first = false;
293
+ let t = { k: "name", name: "any" };
294
+ if (this.eat(":")) {
295
+ t = this.type();
296
+ }
297
+ params.push({ name: pname, t });
298
+ this.eat(",");
299
+ }
300
+ this.expect(")");
301
+ const fn = { k: "fn", params, returns: [] };
302
+ if (variadic) {
303
+ fn.variadic = variadic;
304
+ }
305
+ if (generics.length) {
306
+ fn.generics = generics;
307
+ }
308
+ if (this.eat(":")) {
309
+ this.returnTypes(fn);
310
+ }
311
+ return fn;
312
+ }
313
+ returnTypes(fn) {
314
+ if (this.is("(")) {
315
+ // tuple `(A, B)` or a parenthesized function type `((a) -> b)`
316
+ const mark = this.i;
317
+ this.next();
318
+ if (this.eat(")")) {
319
+ if (this.is("->")) {
320
+ this.i = mark;
321
+ fn.returns = [this.type()];
322
+ }
323
+ return;
324
+ }
325
+ const list = [];
326
+ let tail;
327
+ while (!this.is(")") && this.peek().t !== "eof") {
328
+ if (this.eat("...")) {
329
+ tail = this.type();
330
+ }
331
+ else {
332
+ list.push(this.type());
333
+ }
334
+ this.eat(",");
335
+ }
336
+ this.expect(")");
337
+ if (this.is("->") || this.is("|") || this.is("?") || this.is("&")) {
338
+ this.i = mark;
339
+ fn.returns = [this.type()];
340
+ return;
341
+ }
342
+ fn.returns = list;
343
+ if (tail) {
344
+ fn.returnsVariadic = tail;
345
+ }
346
+ return;
347
+ }
348
+ if (this.eat("...")) {
349
+ fn.returnsVariadic = this.type();
350
+ return;
351
+ }
352
+ const t = this.type();
353
+ if (t.k === "name" && (t.name === "nil" || t.name === "()")) {
354
+ return;
355
+ }
356
+ fn.returns = [t];
357
+ }
358
+ type() {
359
+ this.eat("|");
360
+ const first = this.intersection();
361
+ if (!this.is("|")) {
362
+ return first;
363
+ }
364
+ const ts = [first];
365
+ while (this.eat("|")) {
366
+ ts.push(this.intersection());
367
+ }
368
+ return { k: "union", ts };
369
+ }
370
+ intersection() {
371
+ const first = this.postfix();
372
+ if (!this.is("&")) {
373
+ return first;
374
+ }
375
+ const ts = [first];
376
+ while (this.eat("&")) {
377
+ ts.push(this.postfix());
378
+ }
379
+ return { k: "inter", ts };
380
+ }
381
+ postfix() {
382
+ let t = this.primary();
383
+ while (this.eat("?")) {
384
+ t = { k: "opt", t };
385
+ }
386
+ return t;
387
+ }
388
+ primary() {
389
+ const tok = this.peek();
390
+ if (tok.t === "string") {
391
+ this.next();
392
+ return { k: "lit", value: tok.v };
393
+ }
394
+ if (this.is("typeof")) {
395
+ this.next();
396
+ this.expect("(");
397
+ let depth = 1;
398
+ while (depth > 0 && this.peek().t !== "eof") {
399
+ const t = this.next();
400
+ if (t.v === "(") {
401
+ depth++;
402
+ }
403
+ else if (t.v === ")") {
404
+ depth--;
405
+ }
406
+ }
407
+ return { k: "name", name: "any" };
408
+ }
409
+ if (this.is("{")) {
410
+ return this.table();
411
+ }
412
+ if (this.is("<")) {
413
+ // generic function type `<T>(a: T) -> T`
414
+ const generics = this.genericParamNames();
415
+ const fn = this.parenType();
416
+ if (fn.k === "fn" && generics.length) {
417
+ fn.generics = generics;
418
+ }
419
+ return fn;
420
+ }
421
+ if (this.is("(")) {
422
+ return this.parenType();
423
+ }
424
+ if (this.is("...")) {
425
+ this.next();
426
+ const inner = this.type();
427
+ return inner.k === "name" ? { k: "pack", name: inner.name } : inner;
428
+ }
429
+ if (tok.t === "name") {
430
+ this.next();
431
+ let name = tok.v;
432
+ while (this.is(".") && this.peek(1).t === "name") {
433
+ this.next();
434
+ name += `.${this.next().v}`;
435
+ }
436
+ if (name === "true" || name === "false") {
437
+ return { k: "lit", value: name === "true" };
438
+ }
439
+ if (this.eat("...")) {
440
+ return { k: "pack", name };
441
+ }
442
+ if (this.is("<")) {
443
+ this.next();
444
+ const args = [];
445
+ while (!this.is(">") && this.peek().t !== "eof") {
446
+ if (this.is("(") && this.is(")", 1)) {
447
+ this.next();
448
+ this.next();
449
+ args.push({ k: "name", name: "()" });
450
+ }
451
+ else {
452
+ const arg = this.type();
453
+ if (arg.k === "name" && arg.name === "__pack") {
454
+ args.push(...(arg.args || []));
455
+ }
456
+ else {
457
+ args.push(arg);
458
+ }
459
+ }
460
+ this.eat(",");
461
+ }
462
+ this.expect(">");
463
+ return { k: "name", name, args };
464
+ }
465
+ return { k: "name", name };
466
+ }
467
+ throw new Error(`definitions: unexpected '${tok.v}' at line ${tok.line}`);
468
+ }
469
+ /** `( … )` — a function type when followed by `->`, else grouping. */
470
+ parenType() {
471
+ this.expect("(");
472
+ const params = [];
473
+ let variadic;
474
+ while (!this.is(")") && this.peek().t !== "eof") {
475
+ if (this.eat("...")) {
476
+ variadic = this.is(",") || this.is(")") ? { k: "name", name: "any" } : this.type();
477
+ this.eat(",");
478
+ continue;
479
+ }
480
+ let pname;
481
+ if (this.peek().t === "name" && this.is(":", 1)) {
482
+ pname = this.next().v;
483
+ this.next();
484
+ }
485
+ const t = this.type();
486
+ if (t.k === "pack") {
487
+ variadic = { k: "name", name: "any" };
488
+ this.eat(",");
489
+ continue;
490
+ }
491
+ params.push(pname ? { name: pname, t } : { t });
492
+ this.eat(",");
493
+ }
494
+ this.expect(")");
495
+ if (this.eat("->")) {
496
+ const fn = { k: "fn", params, returns: [] };
497
+ if (variadic) {
498
+ fn.variadic = variadic;
499
+ }
500
+ this.returnTypes(fn);
501
+ return fn;
502
+ }
503
+ if (params.length === 1 && !variadic) {
504
+ return params[0].t;
505
+ }
506
+ if (params.length === 0) {
507
+ return { k: "name", name: "()" };
508
+ }
509
+ // a type pack `(A, B)`, as in RBXScriptSignal<(InputObject, boolean)>
510
+ return { k: "name", name: "__pack", args: params.map((p) => p.t) };
511
+ }
512
+ table() {
513
+ this.expect("{");
514
+ if (this.eat("}")) {
515
+ return { k: "table", fields: {} };
516
+ }
517
+ // `{ T }` array
518
+ const mark = this.i;
519
+ const isField = (this.peek().t === "name" && this.is(":", 1)) || this.is("[") || ((this.is("read") || this.is("write")) && this.peek(1).t === "name");
520
+ if (!isField) {
521
+ const elem = this.type();
522
+ if (this.eat("}")) {
523
+ return { k: "array", t: elem };
524
+ }
525
+ this.i = mark;
526
+ }
527
+ const fields = {};
528
+ let indexer;
529
+ while (!this.is("}") && this.peek().t !== "eof") {
530
+ if ((this.is("read") || this.is("write")) && this.peek(1).t === "name" && this.is(":", 2)) {
531
+ this.next();
532
+ }
533
+ if (this.eat("[")) {
534
+ const key = this.type();
535
+ this.expect("]");
536
+ this.expect(":");
537
+ indexer = [key, this.type()];
538
+ }
539
+ else {
540
+ const fname = this.name();
541
+ this.expect(":");
542
+ fields[fname] = this.type();
543
+ }
544
+ if (!this.eat(",")) {
545
+ this.eat(";");
546
+ }
547
+ }
548
+ this.expect("}");
549
+ if (indexer && Object.keys(fields).length === 0) {
550
+ return { k: "map", key: indexer[0], value: indexer[1] };
551
+ }
552
+ return { k: "table", fields };
553
+ }
554
+ }
555
+ /** Replace generic parameter names by their defaults (`RaycastResult<T = BasePart>` → BasePart). */
556
+ function substituteNames(t, map) {
557
+ if (Object.keys(map).length === 0) {
558
+ return t;
559
+ }
560
+ const sub = (x) => substituteNames(x, map);
561
+ switch (t.k) {
562
+ case "name":
563
+ return map[t.name] && !t.args ? map[t.name] : t.args ? { ...t, args: t.args.map(sub) } : t;
564
+ case "opt":
565
+ return { k: "opt", t: sub(t.t) };
566
+ case "union":
567
+ case "inter":
568
+ return { k: t.k, ts: t.ts.map(sub) };
569
+ case "array":
570
+ return { k: "array", t: sub(t.t) };
571
+ case "map":
572
+ return { k: "map", key: sub(t.key), value: sub(t.value) };
573
+ case "table":
574
+ return { k: "table", fields: Object.fromEntries(Object.entries(t.fields).map(([k, v]) => [k, sub(v)])) };
575
+ case "fn":
576
+ return { ...t, params: t.params.map((p) => ({ ...p, t: sub(p.t) })), returns: t.returns.map(sub) };
577
+ default:
578
+ return t;
579
+ }
580
+ }
581
+ function parseDefinitions(text) {
582
+ let metadata = {};
583
+ const first = text.split("\n", 1)[0];
584
+ if (first.startsWith("--#METADATA#")) {
585
+ try {
586
+ metadata = JSON.parse(first.slice("--#METADATA#".length));
587
+ }
588
+ catch {
589
+ metadata = {};
590
+ }
591
+ }
592
+ const file = new DefParser(lex(text)).file();
593
+ file.metadata = metadata;
594
+ return file;
595
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ /**
3
+ * Roblox surface: the typed Roblox API the CL++ checker validates against.
4
+ * Built from luau-lsp's Roblox definitions (types, nullability, overloads, operators) merged with
5
+ * the Roblox API dump profile (security, read-only, creatable, services, int vs float).
6
+ * Stored as `api/roblox/surface.json` and loaded once per process.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -30,7 +30,7 @@ function registerApiCommands(program) {
30
30
  .command("generate")
31
31
  .description("Build RobloxTargetProfile and regenerate CL++ / Luau projections")
32
32
  .option("--dump <path>", "Mini-API-Dump.json path")
33
- .option("--skip-headers", "Skip CL++ header generation")
33
+ .option("--skip-headers", "Skip legacy .clh API projections")
34
34
  .option("--skip-luau", "Skip .d.luau generation")
35
35
  .option("--docs", "No-op retained for CLI compat (Creator Docs are not mirrored)")
36
36
  .action((opts) => {
@@ -183,7 +183,7 @@ function registerTargetCommands(program) {
183
183
  });
184
184
  target
185
185
  .command("datamodel")
186
- .description("Build Typed DataModel profile + generated datamodel.clh from Rojo project")
186
+ .description("Build Typed DataModel profile (legacy projects also get .clh)")
187
187
  .argument("[folder]", "game root with default.project.json", ".")
188
188
  .option("-r, --rojo <path>", "Rojo project json")
189
189
  .action((folder, options) => {
package/generated/cli.js CHANGED
@@ -12,7 +12,6 @@ const node_path_1 = __importDefault(require("node:path"));
12
12
  const package_info_js_1 = require("./package-info.js");
13
13
  const lsp_js_1 = require("./lsp.js");
14
14
  const paths_js_1 = require("./clpp/paths.js");
15
- const contract_js_1 = require("./clpp/contract.js");
16
15
  const runner_js_1 = require("./clpp/runner.js");
17
16
  Object.defineProperty(exports, "hasClpp", { enumerable: true, get: function () { return runner_js_1.hasClpp; } });
18
17
  const intellisense_js_1 = require("./intellisense.js");
@@ -101,7 +100,8 @@ program
101
100
  });
102
101
  program
103
102
  .command("lsp")
104
- .description("Language server stdio — Flare `.flare` IntelliSense. CL++ still uses `clpp setup`.")
103
+ .description("Schema language server over stdio")
104
+ .option("--stdio", "Use standard input/output (default)")
105
105
  .argument("[folder]", "project folder", ".")
106
106
  .action((folder) => {
107
107
  (0, lsp_js_1.start)({ projectRoot: node_path_1.default.resolve(process.cwd(), folder) });
@@ -109,7 +109,7 @@ program
109
109
  program
110
110
  .command("intellisense")
111
111
  .alias("intelisense")
112
- .description("Install schema IntelliSense (.flare .hive .mint .bloom .helm .shift .axiom) + sync .vscode; CL++ via clpp install")
112
+ .description("Install schema editor support and sync .vscode")
113
113
  .argument("[folder]", "project folder", ".")
114
114
  .action(async (folder) => {
115
115
  try {
@@ -117,7 +117,6 @@ program
117
117
  (0, intellisense_js_1.syncEditorSupport)(root, (0, project_js_1.loadConfig)(root));
118
118
  await (0, intellisense_js_1.installEditorSupport)();
119
119
  console.log("cluaupp: editor associations written in", root);
120
- console.log("cluaupp:", contract_js_1.CLPP_INSTALL_HINT);
121
120
  }
122
121
  catch (err) {
123
122
  console.error(err instanceof Error ? err.message : err);
@@ -126,20 +125,22 @@ program
126
125
  });
127
126
  program
128
127
  .command("language")
129
- .description("CL++ manifest (`clpp api manifest`)")
130
- .action(() => {
128
+ .description("Describe the Roblox .clp target; --legacy probes external clpp")
129
+ .option("--legacy", "Read the manifest of the compatible legacy compiler")
130
+ .action((options) => {
131
131
  try {
132
- const bin = (0, runner_js_1.resolveClppBinary)();
133
- const version = (0, runner_js_1.clppVersion)();
134
- if (version) {
135
- console.log(version, `(${bin})`);
136
- }
137
- for (const install of (0, runner_js_1.clppInstalls)()) {
138
- if (!install.selected) {
139
- console.log(`skipped ${install.bin} (${install.version || "unknown"})`);
140
- }
141
- }
142
- console.log(JSON.stringify((0, runner_js_1.clppManifest)(), null, "\t"));
132
+ const manifest = options.legacy ? (0, runner_js_1.clppManifest)() : {
133
+ name: "Cluaupp Roblox target",
134
+ version: package_info_js_1.pkg.version,
135
+ status: "experimental",
136
+ sourceExtensions: [".clp"],
137
+ fileTags: { server: ".server.clp", client: ".client.clp", plugin: ".plugin.clp" },
138
+ importSyntax: "link",
139
+ headers: false,
140
+ builtinLinks: ["@clpp.roblox", "@clpp.libs.<Library>"],
141
+ legacy: { sourceExtensions: [".clpp", ".clh"], command: "cluaupp language --legacy" },
142
+ };
143
+ console.log(JSON.stringify(manifest, null, "\t"));
143
144
  }
144
145
  catch (err) {
145
146
  console.error(err instanceof Error ? err.message : err);