cluaupp 1.5.0 → 1.5.1

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 (323) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +10 -5
  3. package/api/CHANGELOG.md +3 -0
  4. package/api/chat.js +74 -0
  5. package/api/fixtures/roblox/README.md +6 -0
  6. package/api/fixtures/roblox/aux/sample.d.luau +6 -0
  7. package/api/fixtures/roblox/mini/Mini-API-Dump.json +72 -0
  8. package/api/generated/bench-latest.json +39 -0
  9. package/api/generated/capability-profile.json +76 -0
  10. package/api/generated/lsp-index.json +1 -0
  11. package/api/generated/luau/classes.d.luau +11221 -0
  12. package/api/generated/luau/datatypes.d.luau +327 -0
  13. package/api/generated/luau/enums.d.luau +4918 -0
  14. package/api/generated/luau/globals.d.luau +12 -0
  15. package/api/manifests/roblox-target.manifest.json +22 -0
  16. package/api/normalized/roblox-target.profile.json +237461 -0
  17. package/api/overrides/classes.json +8 -0
  18. package/api/overrides/compatibility.json +9 -0
  19. package/api/overrides/datatypes.json +1579 -0
  20. package/api/overrides/enums.json +8 -0
  21. package/api/overrides/globals.json +8 -0
  22. package/api/overrides/type-mappings.json +9 -0
  23. package/api/roblox-api.lock.json +9 -0
  24. package/data/Mini-API-Dump.json +1 -0
  25. package/editors/vscode/README.md +12 -10
  26. package/editors/vscode/extension.js +82 -0
  27. package/editors/vscode/icons/axiom.svg +4 -0
  28. package/editors/vscode/icons/bloom.svg +5 -0
  29. package/editors/vscode/icons/helm.svg +4 -0
  30. package/editors/vscode/icons/hive.svg +5 -0
  31. package/editors/vscode/icons/mint.svg +4 -0
  32. package/editors/vscode/icons/shift.svg +6 -0
  33. package/editors/vscode/language-configuration-schema.json +24 -0
  34. package/editors/vscode/package.json +172 -12
  35. package/editors/vscode/snippets/axiom.json +12 -0
  36. package/editors/vscode/snippets/bloom.json +12 -0
  37. package/editors/vscode/snippets/helm.json +12 -0
  38. package/editors/vscode/snippets/hive.json +12 -0
  39. package/editors/vscode/snippets/mint.json +12 -0
  40. package/editors/vscode/snippets/shift.json +17 -0
  41. package/editors/vscode/syntaxes/axiom.tmLanguage.json +5 -0
  42. package/editors/vscode/syntaxes/bloom.tmLanguage.json +5 -0
  43. package/editors/vscode/syntaxes/helm.tmLanguage.json +5 -0
  44. package/editors/vscode/syntaxes/hive.tmLanguage.json +5 -0
  45. package/editors/vscode/syntaxes/mint.tmLanguage.json +5 -0
  46. package/editors/vscode/syntaxes/schema.tmLanguage.json +89 -0
  47. package/editors/vscode/syntaxes/shift.tmLanguage.json +5 -0
  48. package/examples/game/.cluaupp/compile-cache/ReplicatedStorage__Shared__Constants__Datas__TemplateData.clh.json +1 -0
  49. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Boot__DataBoot.server.clpp.json +1 -0
  50. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Configuration__ServerConfig.clp.json +1 -0
  51. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__Guard.server.clpp.json +1 -0
  52. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__PlayerHandler.server.clpp.json +1 -0
  53. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterCharacterScripts__Character__CharacterReady.client.clpp.json +1 -0
  54. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterPlayerScripts__Controllers__DataController.client.clpp.json +1 -0
  55. package/examples/game/.cluaupp/compile-cache/index.json +12 -0
  56. package/examples/game/.cluaupp/datamodel-profile.json +94 -0
  57. package/examples/game/.vscode/settings.json +12 -1
  58. package/examples/game/include/clpp/datatypes.clh +337 -373
  59. package/examples/game/include/clpp/generated/datamodel.clh +25 -0
  60. package/examples/game/include/clpp/generated/enums.clh +1 -1
  61. package/examples/game/include/clpp/generated/instances.clh +41135 -41064
  62. package/examples/game/include/clpp/libs/axiom.clh +1 -1
  63. package/examples/game/include/clpp/libs/math.clh +14 -0
  64. package/examples/game/include/clpp/libs/spring.clh +17 -0
  65. package/examples/game/include/clpp/libs/ward.clh +1 -0
  66. package/examples/game/include/clpp/roblox.clh +3 -4
  67. package/examples/game/libs/ArrayIndexer/init.luau +209 -0
  68. package/examples/game/libs/Axiom/init.luau +608 -0
  69. package/examples/game/libs/Bloom/init.luau +433 -0
  70. package/examples/game/libs/Coil/init.luau +215 -0
  71. package/examples/game/libs/Crest/init.luau +426 -0
  72. package/examples/game/libs/Echo/init.luau +417 -0
  73. package/examples/game/libs/Ember/init.luau +365 -0
  74. package/examples/game/libs/Flare/init.luau +717 -0
  75. package/examples/game/libs/Gleam/init.luau +729 -0
  76. package/examples/game/libs/Guide/init.luau +215 -0
  77. package/examples/game/libs/Helm/init.luau +377 -0
  78. package/examples/game/libs/Hive/init.luau +241 -0
  79. package/examples/game/libs/Keep/Client.luau +114 -0
  80. package/examples/game/libs/Keep/Data.luau +883 -0
  81. package/examples/game/libs/Keep/Engine.luau +211 -0
  82. package/examples/game/libs/Keep/Enum.luau +6 -0
  83. package/examples/game/libs/Keep/Enums.luau +10 -0
  84. package/examples/game/libs/Keep/Path.luau +236 -0
  85. package/examples/game/libs/Keep/Replicator.luau +298 -0
  86. package/examples/game/libs/Keep/Server.luau +251 -0
  87. package/examples/game/libs/Keep/Store.luau +652 -0
  88. package/examples/game/libs/Keep/Trade.luau +455 -0
  89. package/examples/game/libs/Keep/init.luau +205 -0
  90. package/examples/game/libs/Lens/init.luau +609 -0
  91. package/examples/game/libs/Mint/init.luau +279 -0
  92. package/examples/game/libs/Net/init.luau +156 -0
  93. package/examples/game/libs/Net/src/codec.luau +224 -0
  94. package/examples/game/libs/Occlude/init.luau +117 -0
  95. package/examples/game/libs/Pin/init.luau +309 -0
  96. package/examples/game/libs/Promise/LICENSE +21 -0
  97. package/examples/game/libs/Promise/_impl/LICENSE +21 -0
  98. package/examples/game/libs/Promise/_impl/init.lua +1991 -0
  99. package/examples/game/libs/Promise/init.lua +1990 -0
  100. package/examples/game/libs/Promise/init.luau +13 -0
  101. package/examples/game/libs/Promise/types.luau +46 -0
  102. package/examples/game/libs/Roster/init.luau +686 -0
  103. package/examples/game/libs/SOURCES.md +31 -0
  104. package/examples/game/libs/Shift/init.luau +238 -0
  105. package/examples/game/libs/Spark/init.luau +487 -0
  106. package/examples/game/libs/Stage/init.luau +178 -0
  107. package/examples/game/libs/Sweep/init.luau +259 -0
  108. package/examples/game/libs/Trace/init.luau +213 -0
  109. package/examples/game/libs/Ward/init.luau +211 -0
  110. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +29 -0
  111. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +13 -0
  112. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +83 -0
  113. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +13 -0
  114. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +18 -0
  115. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +13 -0
  116. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +14 -0
  117. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +13 -0
  118. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +15 -0
  119. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +13 -0
  120. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +50 -0
  121. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +13 -0
  122. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +12 -0
  123. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +13 -0
  124. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +16 -0
  125. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +13 -0
  126. package/examples/game/src/ReplicatedStorage/Shared/Net/Net.clh +26 -0
  127. package/examples/game/src/ServerScriptService/Boot/DataBoot.server.clpp +1 -1
  128. package/examples/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  129. package/examples/game/stylua.toml +9 -0
  130. package/generated/api/build-profile.js +115 -0
  131. package/generated/api/cache.js +44 -0
  132. package/generated/api/coverage.js +32 -0
  133. package/generated/api/diff.js +125 -0
  134. package/generated/api/generators/clpp-headers.js +353 -0
  135. package/generated/api/generators/docs-reference.js +7 -0
  136. package/generated/api/generators/lsp-index.js +81 -0
  137. package/generated/api/generators/luau-defs.js +94 -0
  138. package/generated/api/ide.js +76 -0
  139. package/generated/api/identifier.js +47 -0
  140. package/generated/api/index.js +324 -0
  141. package/generated/api/loader.js +57 -0
  142. package/generated/api/merge.js +88 -0
  143. package/generated/api/model.js +5 -0
  144. package/generated/api/normalize.js +231 -0
  145. package/generated/api/overrides-validate.js +58 -0
  146. package/generated/api/perf.js +12 -0
  147. package/generated/api/registry.js +136 -0
  148. package/generated/api/release.js +44 -0
  149. package/generated/api/resolver.js +250 -0
  150. package/generated/api/sources/aux-types-diff.js +75 -0
  151. package/generated/api/sources/client-tracker.js +11 -0
  152. package/generated/api/sources/creator-docs.js +42 -0
  153. package/generated/api/sources/luau-types.js +34 -0
  154. package/generated/api/sources/mini-dump.js +17 -0
  155. package/generated/api/sources/studio-api.js +8 -0
  156. package/generated/api/sources/studio-apiv2.js +11 -0
  157. package/generated/api/sources/studio-full-api.js +8 -0
  158. package/generated/api/studio-smoke.js +80 -0
  159. package/generated/api/type-parse.js +49 -0
  160. package/generated/api/understander.js +51 -0
  161. package/generated/api/validate.js +135 -0
  162. package/generated/api-cli.js +421 -0
  163. package/generated/cli.js +16 -5
  164. package/generated/clpp/contract.js +3 -3
  165. package/generated/clpp/format-luau.js +236 -0
  166. package/generated/clpp/index.js +13 -1
  167. package/generated/clpp/modules.js +227 -0
  168. package/generated/clpp/postprocess.js +86 -5
  169. package/generated/clpp/rewrite-janitor.js +145 -0
  170. package/generated/clpp/runner.js +14 -2
  171. package/generated/compile.js +82 -0
  172. package/generated/flare/parse.js +12 -1
  173. package/generated/intellisense.js +57 -1
  174. package/generated/native/index.js +217 -16
  175. package/generated/target/authority-check.js +136 -0
  176. package/generated/target/authority-graph.js +74 -0
  177. package/generated/target/build-cache.js +112 -0
  178. package/generated/target/capabilities.js +89 -0
  179. package/generated/target/capability-profile.js +30 -0
  180. package/generated/target/component-contracts.js +60 -0
  181. package/generated/target/context-check.js +160 -0
  182. package/generated/target/datamodel-check.js +170 -0
  183. package/generated/target/datamodel-generate.js +74 -0
  184. package/generated/target/datamodel.js +233 -0
  185. package/generated/target/diagnostics.js +63 -0
  186. package/generated/target/doctor.js +152 -0
  187. package/generated/target/flare-version.js +58 -0
  188. package/generated/target/get-service.js +69 -0
  189. package/generated/target/lifetime-check.js +47 -0
  190. package/generated/target/luau-stamp.js +39 -0
  191. package/generated/target/optimizer-advise.js +88 -0
  192. package/generated/target/optimizer-apply.js +44 -0
  193. package/generated/target/optimizer-soa.js +254 -0
  194. package/generated/target/parallel-check.js +136 -0
  195. package/generated/target/pgo.js +148 -0
  196. package/generated/target/project-docs.js +69 -0
  197. package/generated/target/project-graph.js +71 -0
  198. package/generated/target/roblox.js +63 -0
  199. package/generated/target/security-check.js +41 -0
  200. package/generated/target/source-map.js +25 -0
  201. package/generated/target/studio-bridge.js +112 -0
  202. package/generated/utils/project.js +178 -8
  203. package/generated/utils/rojo-mapper.js +11 -3
  204. package/include/clpp/datatypes.clh +337 -373
  205. package/include/clpp/generated/enums.clh +1 -1
  206. package/include/clpp/generated/instances.clh +41135 -41064
  207. package/include/clpp/libs/axiom.clh +1 -1
  208. package/include/clpp/libs/hive.clh +1 -0
  209. package/include/clpp/libs/keep.clh +2 -0
  210. package/include/clpp/libs/math.clh +14 -0
  211. package/include/clpp/libs/spring.clh +17 -0
  212. package/include/clpp/libs/ward.clh +1 -0
  213. package/include/clpp/roblox.clh +3 -4
  214. package/package.json +10 -3
  215. package/plugins/CluauppNav/Plugin.luau +207 -0
  216. package/plugins/CluauppNav/ProfileLogger.luau +27 -0
  217. package/plugins/CluauppNav/README.md +24 -0
  218. package/runtime/Axiom/init.luau +10 -7
  219. package/runtime/Coil/init.luau +8 -2
  220. package/runtime/Crest/init.luau +1 -0
  221. package/runtime/Flare/init.luau +2 -1
  222. package/runtime/Gleam/init.luau +15 -4
  223. package/runtime/Hive/init.luau +36 -14
  224. package/runtime/Pin/init.luau +5 -2
  225. package/runtime/Roster/init.luau +2 -0
  226. package/runtime/Spark/init.luau +3 -0
  227. package/runtime/Sweep/init.luau +2 -0
  228. package/runtime/Trace/init.luau +3 -0
  229. package/runtime/Ward/init.luau +38 -5
  230. package/scripts/postinstall-editor.js +17 -0
  231. package/skills/README.md +13 -0
  232. package/skills/clpp-hive-flare/SKILL.md +79 -0
  233. package/skills/clpp-language/SKILL.md +123 -0
  234. package/skills/clpp-language/compiler.md +89 -0
  235. package/skills/clpp-style/SKILL.md +95 -0
  236. package/src/api/build-profile.ts +138 -0
  237. package/src/api/cache.ts +45 -0
  238. package/src/api/coverage.ts +46 -0
  239. package/src/api/diff.ts +143 -0
  240. package/src/api/generators/clpp-headers.ts +377 -0
  241. package/src/api/generators/docs-reference.ts +11 -0
  242. package/src/api/generators/lsp-index.ts +106 -0
  243. package/src/api/generators/luau-defs.ts +98 -0
  244. package/src/api/ide.ts +87 -0
  245. package/src/api/identifier.ts +47 -0
  246. package/src/api/index.ts +269 -0
  247. package/src/api/loader.ts +60 -0
  248. package/src/api/merge.ts +126 -0
  249. package/src/api/model.ts +283 -0
  250. package/src/api/normalize.ts +257 -0
  251. package/src/api/overrides-validate.ts +58 -0
  252. package/src/api/perf.ts +15 -0
  253. package/src/api/registry.ts +162 -0
  254. package/src/api/release.ts +47 -0
  255. package/src/api/resolver.ts +255 -0
  256. package/src/api/sources/aux-types-diff.ts +81 -0
  257. package/src/api/sources/client-tracker.ts +10 -0
  258. package/src/api/sources/creator-docs.ts +37 -0
  259. package/src/api/sources/luau-types.ts +30 -0
  260. package/src/api/sources/mini-dump.ts +50 -0
  261. package/src/api/sources/studio-api.ts +7 -0
  262. package/src/api/sources/studio-apiv2.ts +10 -0
  263. package/src/api/sources/studio-full-api.ts +7 -0
  264. package/src/api/studio-smoke.ts +82 -0
  265. package/src/api/type-parse.ts +48 -0
  266. package/src/api/understander.ts +72 -0
  267. package/src/api/validate.ts +160 -0
  268. package/src/api-cli.ts +493 -0
  269. package/src/api.generated.js +37 -22
  270. package/src/cli.ts +21 -6
  271. package/src/clpp/contract.ts +34 -3
  272. package/src/clpp/format-luau.ts +262 -0
  273. package/src/clpp/index.ts +13 -2
  274. package/src/clpp/modules.ts +252 -0
  275. package/src/clpp/postprocess.ts +100 -5
  276. package/src/clpp/rewrite-janitor.ts +156 -0
  277. package/src/clpp/runner.ts +14 -2
  278. package/src/compile.ts +87 -0
  279. package/src/flare/parse.ts +14 -1
  280. package/src/flare/types.ts +2 -0
  281. package/src/intellisense.ts +58 -1
  282. package/src/native/index.ts +225 -16
  283. package/src/target/authority-check.ts +162 -0
  284. package/src/target/authority-graph.ts +80 -0
  285. package/src/target/build-cache.ts +129 -0
  286. package/src/target/capabilities.ts +115 -0
  287. package/src/target/capability-profile.ts +25 -0
  288. package/src/target/component-contracts.ts +64 -0
  289. package/src/target/context-check.ts +177 -0
  290. package/src/target/datamodel-check.ts +188 -0
  291. package/src/target/datamodel-generate.ts +78 -0
  292. package/src/target/datamodel.ts +261 -0
  293. package/src/target/diagnostics.ts +67 -0
  294. package/src/target/doctor.ts +171 -0
  295. package/src/target/flare-version.ts +61 -0
  296. package/src/target/get-service.ts +85 -0
  297. package/src/target/lifetime-check.ts +45 -0
  298. package/src/target/luau-stamp.ts +33 -0
  299. package/src/target/optimizer-advise.ts +93 -0
  300. package/src/target/optimizer-apply.ts +63 -0
  301. package/src/target/optimizer-soa.ts +270 -0
  302. package/src/target/parallel-check.ts +135 -0
  303. package/src/target/pgo.ts +157 -0
  304. package/src/target/project-docs.ts +68 -0
  305. package/src/target/project-graph.ts +75 -0
  306. package/src/target/roblox.ts +78 -0
  307. package/src/target/security-check.ts +40 -0
  308. package/src/target/source-map.ts +36 -0
  309. package/src/target/studio-bridge.ts +140 -0
  310. package/src/types.ts +14 -0
  311. package/src/utils/project.ts +183 -9
  312. package/src/utils/rojo-mapper.ts +12 -3
  313. package/stylua.toml +9 -0
  314. package/templates/game/.vscode/settings.json +7 -1
  315. package/templates/game/include/clpp/datatypes.clh +337 -373
  316. package/templates/game/include/clpp/generated/enums.clh +1 -1
  317. package/templates/game/include/clpp/generated/instances.clh +41135 -41064
  318. package/templates/game/include/clpp/libs/axiom.clh +1 -1
  319. package/templates/game/include/clpp/libs/ward.clh +1 -0
  320. package/templates/game/include/clpp/roblox.clh +3 -4
  321. package/templates/game/src/ServerScriptService/Boot/DataBoot.server.clpp +1 -1
  322. package/templates/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  323. package/templates/game/stylua.toml +9 -0
@@ -2,14 +2,31 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import type { BuildOptions, BuildResult, ProjectConfig } from "../types.js";
4
4
  import { pkg } from "../package-info.js";
5
+ import { rewriteClppEmit } from "../clpp/postprocess.js";
5
6
  import { collectSources, toLuauPath } from "../clpp/paths.js";
6
7
  import { collectFlareFiles, compileFlareFile } from "../flare/index.js";
7
8
  import { collectNativeSchemaFiles, compileNativeSchemaFile } from "../native/index.js";
8
- import { syncEditorSupport } from "../intellisense.js";
9
+ import { installEditorExtension, syncEditorSupport } from "../intellisense.js";
9
10
  import { ProcessOrchestrator } from "./process-orchestrator.js";
10
11
  import { RojoMapper } from "./rojo-mapper.js";
11
12
  import { transpileSource, transpileSourceAsync } from "../transpile.js";
12
13
  import { assertInitDest, assertInside, isInside, safeProjectSubdir, safeRelPath } from "./safe-paths.js";
14
+ import { writeSourceMap } from "../target/source-map.js";
15
+ import { stampLuauFromClpp } from "../target/luau-stamp.js";
16
+ import { collectSoaPlansFromProject, writeSoaArtifacts } from "../target/optimizer-soa.js";
17
+ import { verifyLock } from "../api/index.js";
18
+ import { checkFlareVersions } from "../target/flare-version.js";
19
+ import { checkComponentContracts } from "../target/component-contracts.js";
20
+ import { loadPlatformPolicy } from "../target/authority-check.js";
21
+ import { buildDatamodelProfile } from "../target/datamodel.js";
22
+ import {
23
+ defaultJobCount,
24
+ hashText,
25
+ mapPool,
26
+ readCachedJob,
27
+ writeCachedJob,
28
+ } from "../target/build-cache.js";
29
+ import { fingerprintSourceWithDeps } from "../clpp/modules.js";
13
30
 
14
31
  function readProjectConfig(file: string): Partial<ProjectConfig> {
15
32
  const raw = JSON.parse(fs.readFileSync(file, "utf8"));
@@ -30,6 +47,12 @@ function readProjectConfig(file: string): Partial<ProjectConfig> {
30
47
  if (typeof data.architecture === "boolean") {
31
48
  parsed.architecture = data.architecture;
32
49
  }
50
+ if (data.rules && typeof data.rules === "object") {
51
+ parsed.rules = data.rules as ProjectConfig["rules"];
52
+ }
53
+ if (Array.isArray(data.components)) {
54
+ parsed.components = data.components as ProjectConfig["components"];
55
+ }
33
56
  return parsed;
34
57
  }
35
58
 
@@ -361,45 +384,131 @@ function compileFlareJobs(root: string, config: ProjectConfig, srcDir: string) {
361
384
  return { jobs, errors };
362
385
  }
363
386
 
364
- function compileProject(root: string, config: ProjectConfig, mapper: RojoMapper) {
387
+ function configFingerprint(config: ProjectConfig): string {
388
+ return JSON.stringify({
389
+ strict: config.strict === true,
390
+ architecture: config.architecture === true,
391
+ rootDir: config.rootDir,
392
+ outDir: config.outDir,
393
+ v: pkg.version,
394
+ });
395
+ }
396
+
397
+ function compileProject(root: string, config: ProjectConfig, mapper: RojoMapper, options: BuildOptions = {}) {
365
398
  const srcDir = path.join(root, config.rootDir);
366
399
  const schema = compileSchemaJobs(root, config, srcDir);
367
400
  const files = collectSources(srcDir);
368
401
  const jobs = [...schema.jobs];
369
402
  const errors = [...schema.errors];
403
+ const incremental = options.incremental !== false;
404
+ const cfgKey = configFingerprint(config);
405
+ let cacheHits = 0;
370
406
 
371
407
  for (const file of files) {
372
408
  const source = fs.readFileSync(file, "utf8");
373
409
  const rel = posixRel(srcDir, file);
410
+ const sourceHash = fingerprintSourceWithDeps(source, file, cfgKey, srcDir, hashText);
374
411
  try {
412
+ if (incremental) {
413
+ const cached = readCachedJob(root, rel, sourceHash);
414
+ if (cached) {
415
+ jobs.push({ rel, files: cached.files, stale: cached.stale || [] });
416
+ cacheHits++;
417
+ continue;
418
+ }
419
+ }
375
420
  const result = transpileSource(source, rel, compileOptions(root, config, file, rel), mapper);
376
421
  jobs.push({ rel, files: result.files, stale: result.stale || [] });
422
+ if (incremental) {
423
+ writeCachedJob(root, {
424
+ rel,
425
+ sourceHash,
426
+ files: result.files,
427
+ stale: result.stale || [],
428
+ });
429
+ }
377
430
  } catch (err) {
378
431
  errors.push({ rel, prefixes: sourcePrefixes(rel), message: (err as Error).message });
379
432
  }
380
433
  }
381
434
 
435
+ if (cacheHits > 0) {
436
+ console.log(`cluaupp: incremental cache hit ${cacheHits}/${files.length}`);
437
+ }
382
438
  return { files, jobs, errors };
383
439
  }
384
440
 
385
- async function compileProjectAsync(root: string, config: ProjectConfig, mapper: RojoMapper) {
441
+ async function compileProjectAsync(root: string, config: ProjectConfig, mapper: RojoMapper, options: BuildOptions = {}) {
386
442
  const srcDir = path.join(root, config.rootDir);
387
443
  const schema = compileSchemaJobs(root, config, srcDir);
388
444
  const files = collectSources(srcDir);
389
445
  const jobs = [...schema.jobs];
390
446
  const errors = [...schema.errors];
447
+ const incremental = options.incremental !== false;
448
+ const cfgKey = configFingerprint(config);
449
+ const concurrency = options.jobs ?? defaultJobCount();
450
+ let cacheHits = 0;
391
451
 
392
- for (const file of files) {
452
+ const compiled = await mapPool(files, concurrency, async (file) => {
393
453
  const source = fs.readFileSync(file, "utf8");
394
454
  const rel = posixRel(srcDir, file);
455
+ const sourceHash = fingerprintSourceWithDeps(source, file, cfgKey, srcDir, hashText);
395
456
  try {
457
+ if (incremental) {
458
+ const cached = readCachedJob(root, rel, sourceHash);
459
+ if (cached) {
460
+ return {
461
+ ok: true as const,
462
+ rel,
463
+ files: cached.files,
464
+ stale: cached.stale || [],
465
+ cached: true,
466
+ sourceHash,
467
+ };
468
+ }
469
+ }
396
470
  const result = await transpileSourceAsync(source, rel, compileOptions(root, config, file, rel), mapper);
397
- jobs.push({ rel, files: result.files, stale: result.stale || [] });
471
+ return {
472
+ ok: true as const,
473
+ rel,
474
+ files: result.files,
475
+ stale: result.stale || [],
476
+ cached: false,
477
+ sourceHash,
478
+ };
398
479
  } catch (err) {
399
- errors.push({ rel, prefixes: sourcePrefixes(rel), message: (err as Error).message });
480
+ return {
481
+ ok: false as const,
482
+ rel,
483
+ prefixes: sourcePrefixes(rel),
484
+ message: (err as Error).message,
485
+ };
486
+ }
487
+ });
488
+
489
+ for (const item of compiled) {
490
+ if (item.ok) {
491
+ jobs.push({ rel: item.rel, files: item.files, stale: item.stale });
492
+ if (item.cached) {
493
+ cacheHits++;
494
+ } else if (incremental) {
495
+ writeCachedJob(root, {
496
+ rel: item.rel,
497
+ sourceHash: item.sourceHash,
498
+ files: item.files,
499
+ stale: item.stale,
500
+ });
501
+ }
502
+ } else {
503
+ errors.push({ rel: item.rel, prefixes: item.prefixes, message: item.message });
400
504
  }
401
505
  }
402
506
 
507
+ if (cacheHits > 0) {
508
+ console.log(`cluaupp: incremental cache hit ${cacheHits}/${files.length} (jobs=${concurrency})`);
509
+ } else if (files.length > 1 && concurrency > 1) {
510
+ console.log(`cluaupp: parallel compile jobs=${concurrency}`);
511
+ }
403
512
  return { files, jobs, errors };
404
513
  }
405
514
 
@@ -435,11 +544,25 @@ function writeJobs(root: string, config: ProjectConfig, jobs: Array<{ rel: strin
435
544
  if (!dest) {
436
545
  continue;
437
546
  }
438
- const changed = writeTextIfChanged(dest, artifact.contents);
547
+ let contents = artifact.contents;
548
+ if (/\.luau$/i.test(dest)) {
549
+ const srcFile = path.join(root, config.rootDir, job.rel);
550
+ const clppSource = fs.existsSync(srcFile) ? fs.readFileSync(srcFile, "utf8") : undefined;
551
+ contents = stampLuauFromClpp(rewriteClppEmit(contents), job.rel, clppSource);
552
+ }
553
+ const changed = writeTextIfChanged(dest, contents);
439
554
  written.add(resolveKey(dest));
440
555
  if (changed) {
441
556
  console.log("cluaupp:", job.rel, "→", path.relative(root, dest));
442
557
  }
558
+ if (/\.luau$/i.test(dest)) {
559
+ const mapPath = writeSourceMap({
560
+ outLuauPath: dest,
561
+ sourceClppRel: job.rel,
562
+ projectRoot: root,
563
+ });
564
+ written.add(resolveKey(mapPath));
565
+ }
443
566
  if (format && /\.luau$/i.test(dest)) {
444
567
  ProcessOrchestrator.formatWithStyLuaSync(dest);
445
568
  }
@@ -486,6 +609,17 @@ function finishBuild(
486
609
  }
487
610
 
488
611
  const written = writeJobs(root, config, compiled.jobs, format);
612
+ try {
613
+ const soaPlans = collectSoaPlansFromProject(root, config.rootDir);
614
+ if (soaPlans.length) {
615
+ const files = writeSoaArtifacts(root, soaPlans, { useBuffer: false });
616
+ for (const f of files) {
617
+ console.log("cluaupp: SoA", path.relative(root, f));
618
+ }
619
+ }
620
+ } catch (err) {
621
+ console.error("cluaupp: SoA emit failed", (err as Error).message);
622
+ }
489
623
  const failedPrefixes = compiled.errors.flatMap((err) => err.prefixes);
490
624
  pruneOut(root, config, written, failedPrefixes);
491
625
  try {
@@ -535,21 +669,51 @@ function prepareBuild(root: string, options: BuildOptions) {
535
669
  return { config, mapper: createMapper(root, config, options.rojo) };
536
670
  }
537
671
 
672
+ function enforceFrozen(root: string, config: ProjectConfig): void {
673
+ const lock = verifyLock();
674
+ if (!lock.ok) {
675
+ throw new Error(`cluaupp build --frozen: API lock failed\n${lock.messages.join("\n")}`);
676
+ }
677
+ const flare = checkFlareVersions(root, config.rootDir);
678
+ if (flare.conflicts.length) {
679
+ throw new Error(`cluaupp build --frozen: Flare version conflicts\n${flare.conflicts.map((c) => c.message).join("\n")}`);
680
+ }
681
+ const policy = loadPlatformPolicy(root);
682
+ const components = config.components || policy.components || [];
683
+ if (components.length) {
684
+ const dm = buildDatamodelProfile(root);
685
+ if (dm) {
686
+ const bad = checkComponentContracts(dm, components).filter((d) => d.severity === "error");
687
+ if (bad.length) {
688
+ throw new Error(`cluaupp build --frozen: component contracts\n${bad.map((b) => b.message).join("\n")}`);
689
+ }
690
+ }
691
+ }
692
+ }
693
+
538
694
  export function build(root: string, options: BuildOptions = {}): BuildResult {
695
+ if (options.frozen) {
696
+ const config = loadConfig(root);
697
+ enforceFrozen(root, config);
698
+ }
539
699
  const prepared = prepareBuild(root, options);
540
700
  if (!prepared) {
541
701
  return { failed: 0, written: new Set() };
542
702
  }
543
- const compiled = compileProject(root, prepared.config, prepared.mapper);
703
+ const compiled = compileProject(root, prepared.config, prepared.mapper, options);
544
704
  return finishBuild(root, prepared.config, compiled, options);
545
705
  }
546
706
 
547
707
  export async function buildAsync(root: string, options: BuildOptions = {}): Promise<BuildResult> {
708
+ if (options.frozen) {
709
+ const config = loadConfig(root);
710
+ enforceFrozen(root, config);
711
+ }
548
712
  const prepared = prepareBuild(root, options);
549
713
  if (!prepared) {
550
714
  return { failed: 0, written: new Set() };
551
715
  }
552
- const compiled = await compileProjectAsync(root, prepared.config, prepared.mapper);
716
+ const compiled = await compileProjectAsync(root, prepared.config, prepared.mapper, options);
553
717
  return finishBuild(root, prepared.config, compiled, options);
554
718
  }
555
719
 
@@ -559,10 +723,20 @@ export async function init(dest: string): Promise<void> {
559
723
  const include = path.join(__dirname, "..", "..", "include");
560
724
  copyDir(template, target);
561
725
  copyDir(include, path.join(target, "include"));
726
+ const skills = path.join(__dirname, "..", "..", "skills");
727
+ if (fs.existsSync(skills)) {
728
+ copyDir(skills, path.join(target, ".cursor", "skills"));
729
+ }
562
730
  copyRuntime(target);
563
731
  syncEditorSupport(target);
732
+ try {
733
+ installEditorExtension();
734
+ } catch {
735
+ // editor homes may be missing in CI
736
+ }
564
737
  console.log("Cluaupp ready in", target);
565
738
  console.log(" clpp install (CL++ highlighting + IntelliSense)");
739
+ console.log(" cluaupp intellisense (schema .flare .hive .mint .bloom .helm .shift .axiom)");
566
740
  console.log(" rokit install");
567
741
  console.log(" cluaupp build");
568
742
  console.log(" rojo serve");
@@ -86,7 +86,9 @@ export class RojoMapper {
86
86
  if (!raw) {
87
87
  return null;
88
88
  }
89
- const cleanPath = posix(raw).replace(/\.h(pp|h)?$/i, "");
89
+ const cleanPath = posix(raw)
90
+ .replace(/\.(clpp|clp|clh)$/i, "")
91
+ .replace(/\.h(pp|h)?$/i, "");
90
92
  const baseName = path.posix.basename(cleanPath);
91
93
  const key = baseName.toLowerCase();
92
94
 
@@ -102,7 +104,9 @@ export class RojoMapper {
102
104
  const resolvedFile = this.resolveQuotedFile(raw, fromFile);
103
105
  const lookupPath =
104
106
  resolvedFile && this.srcDir
105
- ? posix(path.relative(this.srcDir, resolvedFile)).replace(/\.h(pp|h)?$/i, "")
107
+ ? posix(path.relative(this.srcDir, resolvedFile))
108
+ .replace(/\.(clpp|clp|clh)$/i, "")
109
+ .replace(/\.h(pp|h)?$/i, "")
106
110
  : cleanPath;
107
111
 
108
112
  const fromTree = this.resolveFromRojoTree(lookupPath, baseName);
@@ -133,6 +137,11 @@ export class RojoMapper {
133
137
  return { alias, path: `ReplicatedStorage.${segments.join(".")}` };
134
138
  }
135
139
 
140
+ /** Alias for CL++ 0.8 named `import { } from` paths. */
141
+ public resolveImportToRequire(modulePath: string, fromFile?: string): RequireBinding | null {
142
+ return this.resolveIncludeToRequire(modulePath, fromFile);
143
+ }
144
+
136
145
  private resolveLibrary(cleanPath: string, key: string): RequireBinding | null {
137
146
  const mapped = (INCLUDE_TO_MODULE as Record<string, string | null>)[key]
138
147
  ?? (INCLUDE_TO_MODULE as Record<string, string | null>)[path.posix.basename(cleanPath).toLowerCase()];
@@ -180,7 +189,7 @@ export class RojoMapper {
180
189
 
181
190
  private guessOutRel(cleanPath: string): string | null {
182
191
  const relative = posix(cleanPath).replace(/^src\//, "");
183
- const outName = relative.replace(/\.(cpp|cc|cxx|c|h|hpp|hh)$/i, "");
192
+ const outName = relative.replace(/\.(cpp|cc|cxx|c|h|hpp|hh|clpp|clp|clh)$/i, "");
184
193
  if (this.outDir) {
185
194
  return posix(path.join(this.outDir, outName));
186
195
  }
package/stylua.toml ADDED
@@ -0,0 +1,9 @@
1
+ # cluaupp roblox luau
2
+ syntax = "Luau"
3
+ column_width = 120
4
+ line_endings = "Unix"
5
+ indent_type = "Tabs"
6
+ indent_width = 4
7
+ quote_style = "AutoPreferDouble"
8
+ call_parentheses = "Always"
9
+ collapse_simple_statement = "Never"
@@ -6,6 +6,12 @@
6
6
  "*.server.clpp": "clpp",
7
7
  "*.client.clpp": "clpp",
8
8
  "*.plugin.clpp": "clpp",
9
- "*.flare": "flare"
9
+ "*.flare": "flare",
10
+ "*.hive": "hive",
11
+ "*.mint": "mint",
12
+ "*.bloom": "bloom",
13
+ "*.helm": "helm",
14
+ "*.shift": "shift",
15
+ "*.axiom": "axiom"
10
16
  }
11
17
  }