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
package/CHANGELOG.md CHANGED
@@ -1,9 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 0.2.0
6
+
7
+ - CLI rewritten as a TypeScript collector-emitter pipeline: Tree-sitter collection, Rojo-mapped `require`s, ordered Luau blocks (Services → Requires → Types → Constants → Code), then optional StyLua / `luau-analyze`. Commands `init`, `build`, `watch`, `lsp`, and `intellisense` stay. `cluaupp build -i file.cpp -o out.luau --rojo default.project.json` is the single-file path.
8
+ - C++ IntelliSense is **clangd** only. The old tokenizer/`completeAt` engine is gone. Tree-sitter is the compiler frontend. `cluaupp lsp` publishes subset parse errors only.
9
+ - `SystemUnderstander` scans identifiers, scores Roblox intents, and stamps Controller / Manager / utility plus `GetService` injections. Filename tags still decide Script vs LocalScript vs ModuleScript.
10
+ - Sample game C++ lives in `examples/game/` (`src/server`, `src/client`, `src/shared`). Compiler `src/` is TypeScript only.
11
+ - CLI security: StyLua / luau-analyze via `spawn` without a shell; emitted paths cannot leave the project; `.env*` stays out of git and the npm pack.
12
+ - Docs / GitHub Pages: clangd, SystemUnderstander, one-file-out emit, `examples/game`. Rojo **7.7.0**.
13
+ - Tests cover `out/` tree, types, modules, path safety, and understander roles.
14
+
15
+ ## 0.1.5
16
+
17
+ - Default emit is one tagged `.cpp` → one `.server.luau` / `.client.luau`. `"architecture": true` keeps the old ForeverHD service folders.
18
+ - `--!strict` is opt-in: `#pragma strict`, `#pragma nstrict`, or `"strict": true` in config (default `false`).
19
+ - `.h` / `.hpp` emit type ModuleScripts (`export type` + typed table). A sibling `.cpp` becomes `*Impl.luau`; the header binds those functions.
20
+ - Shared `#include` modules `require` game-rooted paths (`ReplicatedStorage.Cluaupp...` / `ServerScriptService.Cluaupp...`).
21
+
3
22
  ## 0.1.4
4
23
 
5
24
  - Quoted `#include "Header.h"` of project files becomes `const Header = require(...)`. Header-only structs emit a constructor (`TemplateData()`); const headers bind `PLAYER_DATA_VERSION` from the module. Boot scripts require services (`LeaderstatsServer:init()`).
6
25
  - Keep `const` for injected `require` / `GetService` and `const function` for C++ functions (not `local`).
26
+ - `init.meta.json` stays pure JSON. Library `require` injection no longer prepends Luau onto Rojo meta files (which made `rojo serve` fail with a JSONC parse error).
27
+ - Server services emit `init.server.luau` + `init.meta.json` with **only** `RunContext.Server`. Rojo forbids `className` when an `init.*` script exists (the folder is already a Script, not a Folder). `init.luau` is pruned so the instance is not a ModuleScript.
7
28
 
8
29
  ## 0.1.3
9
30
 
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  [![Node.js](https://img.shields.io/node/v/cluaupp.svg)](https://nodejs.org)
13
13
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
14
14
 
15
- Source-to-source transpiler: you write a C++ subset, Cluaupp emits modern [Luau](https://luau.org/getting-started) (`--!strict`, `local`, `const`). C++ structure, Luau quality, one language.
15
+ Source-to-source transpiler: you write a C++ subset, Cluaupp emits modern [Luau](https://luau.org/getting-started) (`local`, `const`, optional `--!strict`). C++ structure, Luau quality, one language.
16
16
 
17
17
  No WASM. No Emscripten. No `lua_call`. Roblox APIs come out as they do in Studio: `game:GetService("Players")`, `player:FindFirstChild("leaderstats")`, `players:GetPlayers()`.
18
18
 
@@ -42,7 +42,7 @@ players.PlayerAdded:Connect(CreateLeaderstats)
42
42
 
43
43
  ## Install
44
44
 
45
- Node.js 18+ and [Rojo](https://rojo.space/) for Studio sync.
45
+ Node.js 18+ and [Rojo](https://rojo.space/) **7.7.0** for Studio sync (`rokit.toml` in the game template).
46
46
 
47
47
  ```bash
48
48
  npm install -g cluaupp
@@ -59,19 +59,24 @@ npx cluaupp init my-game
59
59
  ```bash
60
60
  cluaupp init my-game
61
61
  cd my-game
62
+ rokit install
62
63
  cluaupp build
63
64
  rojo serve
64
65
  ```
65
66
 
66
67
  Connect the Rojo plugin in Roblox Studio. Edit `src/**/*.{cpp,h,hpp}`, run `cluaupp watch` to rebuild on save.
67
68
 
69
+ C++ autocomplete is **clangd**, not a Cluaupp tokenizer and not Microsoft cpptools. Put `#include <cluaupp/roblox.hpp>` at the top of each script; `cluaupp init` writes `.clangd` / `compile_flags.txt` / `compile_commands.json` with `-Iinclude` so clangd finds that header. Tree-sitter is only used to compile. See [IntelliSense](docs/intellisense.md).
70
+
68
71
  ```
69
- src/server/*.server.cpp → out/server/LeaderStats/ Script + ModuleScripts
70
- src/client/*.client.cpp → out/client/*.client.luau LocalScript (or a service folder)
71
- src/shared/config.* → out/shared/Config.luau typed config module
72
+ src/server/*.server.cpp → out/server/*.server.luau Script
73
+ src/client/*.client.cpp → out/client/*.client.luau LocalScript
74
+ src/shared/*.cpp → out/shared/*.luau ModuleScript
72
75
  ```
73
76
 
74
- A tiny `leaderstats.server.cpp` becomes `Main` / `PlayersManager` / `CacheController`. A combat `.server.cpp` becomes `CombatController` with your `TakeDamage` logic. Filename tags: `.server.cpp`, `.client.cpp`, `.legacy.server.cpp`, `.legacy.client.cpp`, or no tag (ModuleScript). See [Architecture](docs/architecture.md) and [OOP structure](docs/oop/index.md).
77
+ Filename tags: `.server.cpp`, `.client.cpp`, `.legacy.server.cpp`, `.legacy.client.cpp`, or no tag (ModuleScript). One source file becomes one instance. Set `"architecture": true` only for the old PascalCase folder split. See [Architecture](docs/architecture.md) and [OOP structure](docs/oop/index.md).
78
+
79
+ Compiler TypeScript lives in `src/`. Sample game C++ is [`examples/game`](examples/game) (`src/server`, `src/client`, `src/shared`). `cluaupp init` still copies [`templates/game`](templates/game).
75
80
 
76
81
  ## Documentation
77
82
 
@@ -84,7 +89,7 @@ A tiny `leaderstats.server.cpp` becomes `Main` / `PlayersManager` / `CacheContro
84
89
  | [Syntax](docs/syntax.md) | C++ subset → Luau (`local`, `const`, types) |
85
90
  | [print and cout](docs/print-cout.md) | `cout <<`, `cout::warn`, `endl` |
86
91
  | [Roblox API](docs/roblox-api.md) | Vector3, CFrame, UDim2, GetService, Instance.new |
87
- | [Architecture](docs/architecture.md) | PascalCase services, Types modules, not a 200-line dump |
92
+ | [Architecture](docs/architecture.md) | One file in, one file out; opt-in ForeverHD folders |
88
93
  | [OOP structure](docs/oop/index.md) | File tags, services, modules, structs |
89
94
  | [Libraries](docs/libraries/index.md) | DataService Init, Janitor, Promise, Net |
90
95
  | [Examples](docs/examples/index.md) | Leaderstats, combat validation, shop, HUD, sword |
package/bin/cluau.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
 
4
- require("../src/cli.js");
4
+ require("../generated/cli.js");
package/bin/cluaupp.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
 
4
- require("../src/cli.js");
4
+ require("../generated/cli.js");
package/docs/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  8. [Safety](cpp-safety.md) — client trust, Janitor, Net, DataService
11
11
  9. [Organization](cpp-organization.md) — server / client / shared
12
12
  10. [Advanced](cpp-advanced.md) — `::` vs `:`, Wally, performance
13
- 11. [Architecture](architecture.md) — PascalCase services, Types modules, vs roblox-ts dumps
13
+ 11. [Architecture](architecture.md) — one file in, one file out; opt-in ForeverHD folders
14
14
  12. [OOP structure](oop/index.md) — file tags, services, modules, structs
15
15
  13. [Libraries](libraries/index.md) — DataService Init, Janitor, Promise, Net, more
16
16
  14. [Examples](examples/index.md) — leaderstats, combat validation, shop, HUD, sword
@@ -3,54 +3,77 @@ title: Architecture
3
3
  sidebar_position: 15
4
4
  ---
5
5
 
6
- # Output treated as a Roblox system
6
+ # One file in, one file out
7
7
 
8
- roblox-ts decides **what instance you get** from a filename **key** (the same idea as Rojo):
8
+ roblox-ts decides **what instance you get** from a filename **key** (the same idea as Rojo). Cluaupp does the same — and **stops there** by default. It does not invent Main / Controller / Types folders.
9
9
 
10
- | Key | Rojo instance |
10
+ | Key | Rojo instance | Default output |
11
+ | --- | --- | --- |
12
+ | `*.server.cpp` | Script | `*.server.luau` |
13
+ | `*.client.cpp` | LocalScript | `*.client.luau` |
14
+ | no suffix | ModuleScript | `Name.luau` |
15
+ | `*.legacy.server.cpp` | Legacy Script | `*.server.luau` |
16
+
17
+ `DataBoot.client.cpp` becomes `out/client/boot/DataBoot.client.luau` with your `init()` at the end. Shared `#include` modules use `require(ReplicatedStorage.Cluaupp...)`.
18
+
19
+ `--!strict` is opt-in: put `#pragma strict` in the `.cpp`, or set `"strict": true` in `cluaupp.config.json`.
20
+
21
+ The ForeverHD-style folder split (`LeaderStats/Main.luau`, …) is **opt-in**: `"architecture": true`.
22
+
23
+ ## SystemUnderstander
24
+
25
+ Like [roblox-ts](https://github.com/roblox-ts/roblox-ts) (filename **key** first) and [roblox-cs](https://github.com/roblox-csharp/roblox-cs) (scan the AST, then decide), Cluaupp does **not** call a generative model. `src/system-understander.ts` walks the Tree-sitter tree, scores token density against Roblox engine services, and returns a report the emitter may stamp as comments / extra `GetService` lines.
26
+
27
+ | Step | What happens |
11
28
  | --- | --- |
12
- | `*.server.ts` | Script |
13
- | `*.client.ts` | LocalScript |
14
- | no suffix | ModuleScript |
29
+ | `parseFileTag` | `.server.cpp` Script / Server, `.client.cpp` → LocalScript / Client, no tag → ModuleScript |
30
+ | `namesIn` | identifiers, `GetService<T>`, `new Class`, string literals |
31
+ | `scoreIntents` | evidence count × side weight (server tokens count more on `.server.cpp`) |
32
+ | `determineArchitecture` | score &lt; 2 → utility Module; otherwise Knit-style Controller / Manager / Service. `players` / `cache` stay supporting if combat, UI, or net already has ≥ 2 tokens |
33
+
34
+ The **Rojo class never changes** because of a role. A HUD LocalScript can be classified as `ViewController` and still emit `hud.client.luau`. Sample sources: [examples/game](../examples/game).
15
35
 
16
- Flamework then stamps a second key (`@Service` / `@Controller`) so the runtime knows the **role**. Cluaupp does both steps without decorators.
36
+ ## Compiler pipeline
17
37
 
18
- 1. **Tag** (filename) where the code runs and whether it is a Script, LocalScript, ModuleScript, or a 1:1 “legacy” dump.
19
- 2. **Intent** (AST) — what the code *is for*: players, cache, combat, input, UI, net, data, … scored from APIs and identifiers, the same idea as intent classification in program analysis (features from the tree, not a 200-line dump).
38
+ Cluaupp does not rewrite C++ as text. The CLI parses a Tree-sitter CST, collects symbols (`GetService<T>()`, `#include`, types, constants), then emits Luau in a fixed order:
20
39
 
21
- Leaderstats was the example. A combat `.server.cpp` is a different system and gets Combat folders, not a fake CacheController.
40
+ 1. `game:GetService(...)`
41
+ 2. `require(...)` (Rojo `default.project.json` when present)
42
+ 3. types
43
+ 4. constants
44
+ 5. functions / script body
45
+
46
+ Formatting is delegated to StyLua; type sanity to `luau-analyze`. See [CLI](cli.md).
22
47
 
23
48
  ## File tags
24
49
 
25
50
  | Source | Meaning | Output |
26
51
  | --- | --- | --- |
27
- | `combat.server.cpp` | **Script** RunContext Server | `Combat/init.luau` + `init.meta.json` |
28
- | `hud.client.cpp` | **LocalScript** | `Hud/init.client.luau` |
29
- | `tools.plugin.cpp` | **Script** RunContext Plugin | `Tools/init.luau` + `init.meta.json` |
30
- | `boot.legacy.cpp` | Legacy Script | `boot.server.luau` |
52
+ | `combat.server.cpp` | **Script** | `combat.server.luau` |
53
+ | `hud.client.cpp` | **LocalScript** | `hud.client.luau` |
54
+ | `tools.plugin.cpp` | **Script** RunContext Plugin | `tools.luau` (legacy plugin tag) |
31
55
  | `boot.legacy.server.cpp` | Legacy Script | `boot.server.luau` |
32
- | `boot.legacy.client.cpp` | Legacy LocalScript | `boot.client.luau` |
33
- | `boot.legacy.plugin.cpp` | Plugin | `boot.luau` + Plugin meta |
34
56
  | `damage.cpp` (no tag) | **ModuleScript** | `Damage.luau` |
35
57
 
36
- Trivial entry files (`init.client.cpp` that only `print`) stay a single LocalScript (`init.client.luau`). The planner does not invent Managers for a hello-world.
58
+ ## What a tagged file becomes
37
59
 
38
- ## How the planner reasons
60
+ ```
61
+ src/server/leaderstats.server.cpp → out/server/leaderstats.server.luau
62
+ src/client/boot/DataBoot.client.cpp → out/client/boot/DataBoot.client.luau
63
+ src/shared/damage.cpp → out/shared/Damage.luau
64
+ ```
65
+
66
+ Scripts and LocalScripts keep your functions and call `init()` at the end. ModuleScripts return a table. There is no invented Main, Controller, or Types file.
67
+
68
+ ## Opt-in: ForeverHD folders (`"architecture": true`)
69
+
70
+ Set `"architecture": true` in `cluaupp.config.json` to restore the old planner: PascalCase service folders, `Main` / Managers / Controllers / Types, and `require(script.Main):Start()`. Server folders emit `init.server.luau` plus a **pure JSON** `init.meta.json` with only `RunContext.Server` — never `className`, and never library `require` lines (Rojo 7.7 rejects both).
39
71
 
40
72
  ```
41
73
  filename key → server | client | module | legacy
42
74
  AST features → GetService, Instance.new, methods, identifiers
43
75
  intent scores → combat:2, character:1, …
44
76
  roles → Main + Managers + Controllers + Types
45
- user functions→ kept in the matching Controller (not discarded)
46
- ```
47
-
48
- Generated files start with that trace:
49
-
50
- ```luau
51
- -- tag server → Script (service)
52
- -- intents combat:2, character:1
53
- -- roles Main, CombatController, CombatTypes
54
77
  ```
55
78
 
56
79
  | Evidence in the C++ | Role |
@@ -64,54 +87,6 @@ Generated files start with that trace:
64
87
  | Domain shapes / stats | `{Service}Types` (`export type`, `return {}`) |
65
88
  | Wiring | `Main.Start` / `Main.Stop` |
66
89
 
67
- If the C++ creates Coins/Level, CacheController is generated (higher quality than copying `CreateLeaderstats`). Combat logic is **not** rewritten into leaderstats — `ApplyDamage` stays in `CombatController.luau`.
68
-
69
- The domain controller keeps **every** user function. CacheController is generated beside it; it must not delete `SetupPlayerManager` while `init` still calls that name. `GetChangedSignal(Paths.Currencies)` stays in `DataController`.
70
-
71
- ## What leaderstats becomes
72
-
73
- ```
74
- src/server/leaderstats.server.cpp
75
- ```
76
-
77
- ```
78
- out/server/LeaderStats/
79
- init.luau
80
- init.meta.json
81
- Main.luau
82
- PlayersManager.luau
83
- CacheController.luau
84
- LeaderStatsTypes.luau
85
- ```
86
-
87
- ## What combat becomes
88
-
89
- ```
90
- src/server/combat.server.cpp -- TakeDamage, Humanoid
91
- ```
92
-
93
- ```
94
- out/server/Combat/
95
- init.luau
96
- init.meta.json
97
- Main.luau
98
- CombatController.luau -- your ApplyDamage / OnHit
99
- CombatTypes.luau
100
- ```
101
-
102
- No PlayersManager unless you actually listen to players. No CacheController unless you actually create value Instances.
103
-
104
- ## ForeverHD-style rules
105
-
106
- - PascalCase folders and modules; camelCase locals
107
- - `--!strict` everywhere
108
- - Public API `Start` / `Stop`. `Start` is idempotent (`Stop` first). Domain `Stop` is `janitor:Cleanup()` (unbind, janitor stays reusable). `OnClose` / `Destroy` stay for `BindToClose`. `PlayersManager.Stop` disconnects and runs `onLeave`. `CacheController.ClearAll` drops the cache.
109
- - Janitor owns connections in the Manager
110
- - Module layout in generated Luau (no section banners): requires, types, constants, variables, functions, cleanup, return.
111
- - Transparent `require(script.Parent.X)`
112
-
113
- ## Config
114
-
115
- `cluaupp.config.json`: `"architecture": true` (default). `"architecture": false` forces 1:1 dumps (or use `.legacy.server.cpp` / `.legacy.client.cpp` per file).
90
+ Switching back to 1:1 deletes the stale `LeaderStats/` / `DataBoot/` folders on the next `cluaupp build`.
116
91
 
117
- How to **write** a service, tags, and module-style OOP: [OOP structure](oop/index.md). Copy-paste systems: [Examples](examples/index.md). Also [organization](cpp-organization.md) and [comparison](comparison.md).
92
+ How to **write** a system, tags, and module-style OOP: [OOP structure](oop/index.md). Copy-paste systems: [Examples](examples/index.md). Also [organization](cpp-organization.md) and [comparison](comparison.md).
package/docs/cli.md CHANGED
@@ -6,6 +6,8 @@ cluaupp <command> [folder]
6
6
 
7
7
  If `[folder]` is omitted, the current directory is used.
8
8
 
9
+ The compiler is a **collector-emitter** pipeline: Tree-sitter walks the C++ CST, Rojo maps `#include` to `require`, Luau is emitted in a fixed block order (Services → Requires → Types → Constants → Code), then StyLua / `luau-analyze` can run as post-process.
10
+
9
11
  ## `cluaupp init [folder]`
10
12
 
11
13
  Creates a game from the template:
@@ -13,8 +15,9 @@ Creates a game from the template:
13
15
  - `src/server`, `src/client`, `src/shared`
14
16
  - `cluaupp.config.json`
15
17
  - `default.project.json` (Rojo)
18
+ - `rokit.toml` (Rojo 7.7.0)
16
19
  - `include/cluaupp/roblox.hpp` (IntelliSense)
17
- - `.vscode/c_cpp_properties.json`
20
+ - `.vscode/` (clangd)
18
21
 
19
22
  ```bash
20
23
  cluaupp init .
@@ -23,13 +26,12 @@ cluaupp init my-game
23
26
 
24
27
  ## `cluaupp build [folder]`
25
28
 
26
- Transpiles `src/**/*.{cpp,h,hpp}` into `out/`. Script files become PascalCase **service folders** (`LeaderStats/Main.luau`, `PlayersManager.luau`, `CacheController.luau`, `LeaderStatsTypes.luau`) plus `init.luau` and `init.meta.json` (`RunContext.Server`) for Rojo. Shared `const` headers become `Config.luau`.
29
+ Transpiles `src/**/*.{cpp,h,hpp}` into `out/`. One tagged `.cpp` becomes one Luau instance (`leaderstats.server.luau`, `hud.client.luau`). Shared untagged files become ModuleScripts. Set `"architecture": true` for the old PascalCase service folders.
27
30
 
28
- - `--!strict` on every module
29
- - `#include "file.h"` inlines that header into the current file
31
+ - `--!strict` only with `#pragma strict`, `"strict": true`, or `--strict` on the single-file path
32
+ - `#include "file.h"` becomes `require(...)` resolved from `default.project.json` when present
30
33
  - `#include <cluaupp/roblox.hpp>` is ignored
31
- - `.h` / `.hpp` with a sibling `.cpp` are not emitted twice
32
- - `new Folder(parent)` in a stats system becomes `CacheController.Ensure`
34
+ - `.h` / `.hpp` emit a type ModuleScript (`export type` + typed table). A sibling `.cpp` becomes `*Impl.luau` (the construction); the header binds those functions.
33
35
  - A parse error exits with code 1 and `file:line:column`
34
36
  - After emit, **orphans in `out/` are removed** (source deleted → matching Luau deleted). `out/` itself is never wiped, so a running Rojo serve keeps the live tree.
35
37
  - `libs/` and `include/cluaupp` are synced by writing missing/changed files only. They are **never** deleted as a folder — Rojo 7 unwrap-crashes if `libs/ArrayIndexer` vanishes while serving.
@@ -37,12 +39,29 @@ Transpiles `src/**/*.{cpp,h,hpp}` into `out/`. Script files become PascalCase **
37
39
  ```bash
38
40
  cluaupp build
39
41
  cluaupp build ./my-game
42
+ cluaupp build --format --analyze
43
+ ```
44
+
45
+ ### Single file
46
+
47
+ ```bash
48
+ cluaupp build --input ./src/server/boot.server.cpp --output ./out/boot.server.luau --rojo ./default.project.json
40
49
  ```
41
50
 
51
+ `--format` runs StyLua; `--analyze` runs `luau-analyze`. On the single-file path both run by default (warnings if the binaries are missing). On a project build they are opt-in.
52
+
42
53
  ## `cluaupp watch [folder]`
43
54
 
44
55
  Runs a compile (without copying `libs/`) and rebuilds when anything under `src/` changes, including deletes. Parse errors are printed; the watcher stays alive and **does not write `out/`** until the project compiles cleanly (Studio keeps the last good scripts). A second watcher in the same game exits. Deleted `.cpp` files prune their `out/` artifacts on the next successful compile.
45
56
 
57
+ ## `cluaupp lsp [folder]`
58
+
59
+ Stdio JSON-RPC for **Cluaupp subset diagnostics** only. Completion, hover, and definitions are clangd.
60
+
61
+ ## `cluaupp intellisense [folder]`
62
+
63
+ Writes `compile_commands.json`, `.clangd`, and `.vscode` for clangd, and installs LLVM clangd when needed.
64
+
46
65
  ## `cluaupp --version` / `cluaupp -v`
47
66
 
48
67
  Prints the npm package version.
@@ -65,7 +84,8 @@ Shows usage.
65
84
  In the Cluaupp development repo:
66
85
 
67
86
  ```bash
68
- npm run build # cluaupp build game
69
- npm run dev # watch + Rojo
70
- npm run stop # stop Rojo
87
+ npm run build:cli # compile the TypeScript CLI
88
+ npm test
89
+ npm run dev # local gitignored playground in game/ + Rojo
90
+ npm run stop # stop Rojo
71
91
  ```
@@ -6,9 +6,9 @@
6
6
 
7
7
  Both are source-to-source. Neither goes through WASM. Generated Luau calls the Roblox API directly.
8
8
 
9
- The difference is **what Studio receives**. roblox-ts stops at the filename key (`*.server.ts` → Script). Cluaupp uses that key **and** reads the AST so a combat system is not emitted as a fake leaderstats. See [Architecture](architecture.md).
9
+ By default Cluaupp matches that filename key: `*.server.cpp` → one Script, `*.client.cpp` one LocalScript, untagged ModuleScript. The ForeverHD folder split is opt-in (`"architecture": true`). See [Architecture](architecture.md).
10
10
 
11
- Current Luau has [`local`, `const`, and `--!strict`](https://luau.org/getting-started). Cluaupp emits that on purpose: `const int` in C++ becomes `const x = ...` in Luau.
11
+ Current Luau has [`local`, `const`, and `--!strict`](https://luau.org/getting-started). Cluaupp emits `const` from C++ `const`. `--!strict` is opt-in (`#pragma strict` or `"strict": true`).
12
12
 
13
13
  ## vs C++ → WASM → Luau (RBX-CPP / Emscripten)
14
14
 
@@ -33,5 +33,5 @@ is exactly what Studio expects, not a parallel runtime.
33
33
  | Goal | Tool |
34
34
  | --- | --- |
35
35
  | Game in TypeScript | roblox-ts |
36
- | Game in C++, clear Roblox API, Luau `--!strict` | **Cluaupp** |
36
+ | Game in C++, clear Roblox API | **Cluaupp** |
37
37
  | Full native C++ (templates, STL, engines) | not Cluaupp today |
package/docs/config.md CHANGED
@@ -6,17 +6,17 @@ File: `cluaupp.config.json` at the game root (next to `src/`).
6
6
  {
7
7
  "rootDir": "src",
8
8
  "outDir": "out",
9
- "strict": true,
10
- "architecture": true
9
+ "strict": false,
10
+ "architecture": false
11
11
  }
12
12
  ```
13
13
 
14
14
  | Field | Default | Effect |
15
15
  | --- | --- | --- |
16
16
  | `rootDir` | `"src"` | Where the `.cpp` / `.h` / `.hpp` files live |
17
- | `outDir` | `"out"` | Where services and modules are written |
18
- | `strict` | `true` | Prefix `--!strict` on every generated file |
19
- | `architecture` | `true` | Emit PascalCase service folders (`LeaderStats/Main.luau`, …) instead of one dump per `.cpp` |
17
+ | `outDir` | `"out"` | Where Luau is written |
18
+ | `strict` | `false` | Prefix `--!strict` on generated files (overridden by `#pragma strict` / `#pragma nstrict`) |
19
+ | `architecture` | `false` | If `true`, emit PascalCase service folders (`LeaderStats/Main.luau`, …) instead of one Luau per `.cpp` |
20
20
 
21
21
  If the file is missing, those defaults apply.
22
22
 
@@ -28,4 +28,4 @@ The template ships `default.project.json` mapping:
28
28
  - `out/client` → `StarterPlayer.StarterPlayerScripts.Cluaupp`
29
29
  - `out/shared` → `ReplicatedStorage.Cluaupp`
30
30
 
31
- `*.server.cpp` becomes a folder with `init.luau` + `init.meta.json` (`className` Script, `RunContext` Server). `.client` stays LocalScript via `init.client.luau`. A `.legacy.server.cpp` dump is still `*.server.luau` (Legacy).
31
+ `*.server.cpp` becomes `*.server.luau` (Script). `*.client.cpp` becomes `*.client.luau` (LocalScript). Untagged files become ModuleScripts.
@@ -5,7 +5,7 @@ sidebar_position: 13
5
5
 
6
6
  # Organization
7
7
 
8
- A Cluaupp game is laid out like a roblox-ts project on disk. The **output** is not a dump: `cluaupp build` turns each system into a PascalCase service folder (Main, Manager, Controller, Types). See [Architecture](architecture.md).
8
+ A Cluaupp game is laid out like a roblox-ts project on disk. One tagged `.cpp` becomes one Luau instance (`leaderstats.server.luau`, `hud.client.luau`). See [Architecture](architecture.md).
9
9
 
10
10
  ```
11
11
  src/
@@ -47,7 +47,7 @@ const string REMOTE_COINS = "Coins";
47
47
 
48
48
  `leaderstats.server.cpp` creates leaderstats. It does not also open the shop UI. Name files after the system: `inventory.server.cpp`, `shop.client.cpp`.
49
49
 
50
- `*.server.cpp` / `*.client.cpp` are **tags** (the same keys roblox-ts uses). Untagged `.cpp` is a ModuleScript. `.legacy.server.cpp` / `.legacy.client.cpp` skip the service split. See [Architecture](architecture.md) and [OOP structure](oop/index.md).
50
+ `*.server.cpp` / `*.client.cpp` are **tags** (the same keys roblox-ts uses). Untagged `.cpp` is a ModuleScript. Set `"architecture": true` only if you want the old PascalCase folder split. See [Architecture](architecture.md) and [OOP structure](oop/index.md).
51
51
 
52
52
  ## CluauppLibs vs extra Wally
53
53
 
@@ -7,6 +7,8 @@ sidebar_position: 1
7
7
 
8
8
  High-quality Cluaupp systems you can copy. Each page is a full service: C++ that the subset actually compiles, server authority, Janitor cleanup, and the file names Studio expects.
9
9
 
10
+ In this repo the live sample is [`examples/game`](../../examples/game) (`src/server`, `src/client`, `src/shared`). Compiler TypeScript is never mixed with game C++. `cluaupp init` still copies [`templates/game`](../../templates/game).
11
+
10
12
  These are **not** dumps of `int main()`. Entry is `void init()`. There are no lambdas and no custom C++ classes — named functions + structs.
11
13
 
12
14
  ## Suggested layout
@@ -5,8 +5,8 @@ Cluaupp installs from **npm**, the same channel as roblox-ts and most Roblox too
5
5
  ## Requirements
6
6
 
7
7
  - [Node.js](https://nodejs.org/) 18 or newer
8
- - [Rojo](https://rojo.space/) to sync `out/` into Studio
9
- - An editor with C++ IntelliSense (Cursor / VS Code + the C/C++ extension)
8
+ - [Rojo](https://rojo.space/) **7.7.0** to sync `out/` into Studio (`cluaupp init` writes `rokit.toml`; run `rokit install`)
9
+ - LLVM clangd for C++ IntelliSense (Cursor / VS Code installed by `cluaupp init`)
10
10
 
11
11
  ## Install the compiler
12
12
 
@@ -43,6 +43,7 @@ npm install --save-dev cluaupp
43
43
  ```bash
44
44
  cluaupp init my-game
45
45
  cd my-game
46
+ rokit install
46
47
  cluaupp build
47
48
  rojo serve
48
49
  ```
@@ -66,7 +67,8 @@ my-game/
66
67
  shared/config.h
67
68
  shared/config.cpp
68
69
  out/ ← generated Luau (do not edit)
69
- server/LeaderStats/ Main, PlayersManager, CacheController, Types
70
+ server/leaderstats.server.luau
71
+ client/init.client.luau
70
72
  shared/Config.luau
71
73
  ```
72
74
 
@@ -122,13 +124,13 @@ If a file defines `void init()`, Cluaupp calls `init()` at the end of the `.luau
122
124
 
123
125
  ## IntelliSense
124
126
 
125
- `cluaupp init` writes the C++ IntelliSense config and installs Microsoft `ms-vscode.cpptools` (via VSIX on Cursor). Then reload the window.
127
+ `cluaupp init` writes clangd config and installs LLVM `clang++` plus the clangd editor extension when missing. Then reload the window. Completion is clangd; Cluaupp does not index C++ itself.
126
128
 
127
129
  ```bash
128
130
  cluaupp intellisense
129
131
  ```
130
132
 
131
- `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is **not** compiled to Luau.
133
+ `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is **not** compiled to Luau. clangd learns that path from `-Iinclude` in `.clangd`, `compile_flags.txt`, and `compile_commands.json` — it does not read `c_cpp_properties.json`.
132
134
 
133
135
  See [IntelliSense](intellisense.md).
134
136
 
@@ -1,31 +1,49 @@
1
- # IntelliSense
2
-
3
- `cluaupp init` and `cluaupp intellisense` install the same setup that works in Cursor:
4
-
5
- 1. Microsoft [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) (`ms-vscode.cpptools`)
6
- 2. `.vscode/c_cpp_properties.json` — LLVM `clang++`, C++20, `include/` + `src/`, `compile_commands.json`
7
- 3. Forced include of `include/cluaupp/roblox.hpp` so `GetService`, `Player`, `Janitor` complete
8
- 4. The Cluaupp completion engine (Roblox APIs + your `struct`s)
9
-
10
- Cursor’s marketplace does not list `ms-vscode.cpptools`. Cluaupp downloads the official VSIX from [vscode-cpptools releases](https://github.com/microsoft/vscode-cpptools/releases) and runs `cursor --install-extension`.
11
-
12
- ## Install
13
-
14
- ```bash
15
- cluaupp intellisense
16
- ```
17
-
18
- Reload: Command Palette **Developer: Reload Window**. Status bar `{} C++` should read **IntelliSense: Ready**.
19
-
20
- `cluaupp build` / `watch` only refresh `compile_commands.json` (no download). They never keep deleted files in the compilation database.
21
-
22
- ## Config that ships
23
-
24
- | File | Role |
25
- | --- | --- |
26
- | `.vscode/c_cpp_properties.json` | compiler path, include path, `compileCommands` |
27
- | `.vscode/settings.json` | `C_Cpp.intelliSenseEngine: default`, `clangd.enable: false` |
28
- | `.vscode/extensions.json` | recommends `ms-vscode.cpptools` |
29
- | `compile_commands.json` | one entry per `src/` file |
30
-
31
- `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is not compiled to Luau.
1
+ # IntelliSense
2
+
3
+ C++ completion, hover, and go-to-definition are **clangd**. Cluaupp does not ship a second completion engine.
4
+
5
+ `cluaupp init` / `cluaupp intellisense` install:
6
+
7
+ 1. [clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) (`llvm-vs-code-extensions.vscode-clangd`)
8
+ 2. LLVM `clang++` when missing (Windows: `winget install --id LLVM.LLVM -e`)
9
+ 3. `.clangd`, `compile_flags.txt`, and `compile_commands.json` so clangd finds `include/` (clangd does **not** read `.vscode/c_cpp_properties.json`)
10
+ 4. Forced include of `include/cluaupp/roblox.hpp` so `GetService`, `Player`, `Janitor` complete from the real C++ stubs
11
+
12
+ Tree-sitter is the **compiler** frontend (collect → emit Luau). It is not an editor language server. A homemade tokenizer in the CLI would fight clangd — that path is gone.
13
+
14
+ Microsoft `ms-vscode.cpptools` is **not** used. Two C++ engines in the same window fight; Cluaupp disables the Microsoft engine (`C_Cpp.intelliSenseEngine: Disabled`).
15
+
16
+ `cluaupp lsp` only publishes **subset parse errors** (code that clangd may accept as C++ but Cluaupp will not transpile).
17
+
18
+ ## Headers clangd must see
19
+
20
+ `#include <cluaupp/roblox.hpp>` resolves only if `-Iinclude` is on the clangd compile flags. That maps to `include/cluaupp/roblox.hpp`. Angle-bracket includes are ignored by the transpiler.
21
+
22
+ `cluaupp init` / `build` / `watch` / `intellisense` rewrite:
23
+
24
+ - `-Iinclude` and `-Isrc`
25
+ - `-include include/cluaupp/roblox.hpp`
26
+ - one `compile_commands.json` entry per file under `src/`
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ cluaupp intellisense
32
+ ```
33
+
34
+ Reload: Command Palette → **Developer: Reload Window**. clangd should attach to `.cpp` files.
35
+
36
+ `cluaupp build` / `watch` only refresh `compile_commands.json` (no download). They never keep deleted files in the compilation database.
37
+
38
+ ## Config that ships
39
+
40
+ | File | Role |
41
+ | --- | --- |
42
+ | `.vscode/c_cpp_properties.json` | compiler path (unused by clangd; kept if someone re-enables cpptools) |
43
+ | `.vscode/settings.json` | `C_Cpp.intelliSenseEngine: Disabled`, `clangd.enable: true`, `--compile-commands-dir` |
44
+ | `.vscode/extensions.json` | recommends `llvm-vs-code-extensions.vscode-clangd` |
45
+ | `.clangd` | C++20, `-Iinclude`, skip `out/` and `libs/` |
46
+ | `compile_flags.txt` | fallback flags if a file is not yet in `compile_commands.json` |
47
+ | `compile_commands.json` | one entry per `src/` file |
48
+
49
+ `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is not compiled to Luau.
package/docs/intro.md CHANGED
@@ -5,14 +5,14 @@ sidebar_position: 1
5
5
 
6
6
  # Cluaupp
7
7
 
8
- **The definitive merge of C++ and modern Luau.** You write a C++ subset. Cluaupp emits [Luau](https://luau.org/getting-started) with `--!strict`, `local`, and `const`, and calls the Roblox API the way Studio does.
8
+ **The definitive merge of C++ and modern Luau.** You write a C++ subset. Cluaupp emits [Luau](https://luau.org/getting-started) with `local` and `const` (and `--!strict` when you opt in), and calls the Roblox API the way Studio does.
9
9
 
10
10
  This site is built with [Moonwave](https://eryn.io/moonwave/) for local markdown (`npm run docs`). The **public** site is generated into `site/` and deployed to [GitHub Pages](https://kartzrbx.github.io/Cluaupp/) (Learn tabs, OOP, Examples, API). The language is in the same spirit as [roblox-ts](https://roblox-ts.com): a familiar syntax, a restricted subset, readable output.
11
11
 
12
12
  ## What you get
13
13
 
14
14
  1. A compiler (`cluaupp init` / `build` / `watch`)
15
- 2. Headers for IntelliSense (`#include <cluaupp/roblox.hpp>`)
15
+ 2. Headers for **clangd** (`#include <cluaupp/roblox.hpp>`)
16
16
  3. First-party libraries in `ReplicatedStorage.CluauppLibs`
17
17
  4. Wally wrappers for DataServiceV2, Fusion, Cmdr, EzVisualz, TopbarPlus, and the rest of your stack
18
18