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.
- package/CHANGELOG.md +8 -0
- package/README.md +29 -41
- package/api/generated/bench-latest.json +43 -21
- package/api/generated/lsp-index.json +1 -1
- package/api/manifests/roblox-target.manifest.json +5 -5
- package/api/normalized/roblox-target.profile.json +8729 -267
- package/api/roblox/luau-builtins.d.luau +185 -0
- package/api/roblox/surface.json +1 -0
- package/api/roblox-api.lock.json +11 -2
- package/bin/cluaupp.js +38 -0
- package/editors/vscode/README.md +1 -1
- package/editors/vscode/package.json +50 -15
- package/editors/vscode/snippets/flare.json +1 -1
- package/editors/vscode/snippets/hive.json +1 -1
- package/editors/vscode/syntaxes/clpp.tmLanguage.json +211 -0
- package/examples/README.md +9 -9
- package/examples/game/cluaupp.config.json +2 -2
- package/examples/game/default.project.json +4 -15
- package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau +8 -0
- package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau.map.json +13 -0
- package/examples/game/out/ServerScriptService/Leaderstats.server.luau +26 -0
- package/examples/game/out/ServerScriptService/Leaderstats.server.luau.map.json +13 -0
- package/examples/game/out/ServerScriptService/Main.server.luau +15 -0
- package/examples/game/out/ServerScriptService/Main.server.luau.map.json +13 -0
- package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau +10 -0
- package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau.map.json +13 -0
- package/examples/game/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
- package/examples/game/src/ServerScriptService/Leaderstats.server.clp +18 -0
- package/examples/game/src/ServerScriptService/Main.server.clp +9 -0
- package/examples/game/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
- package/generated/api/build-profile.js +1 -1
- package/generated/api/loader.js +2 -2
- package/generated/api/surface/build.js +328 -0
- package/generated/api/surface/luau-defs.js +595 -0
- package/generated/api/surface/model.js +8 -0
- package/generated/api-cli.js +2 -2
- package/generated/cli.js +18 -17
- package/generated/clpp/contract.js +6 -3
- package/generated/clpp/handshake.js +36 -0
- package/generated/clpp/modules.js +20 -9
- package/generated/clpp/runner.js +62 -31
- package/generated/compile.js +18 -1
- package/generated/compiler/ast.js +3 -0
- package/generated/compiler/checker/calls.js +999 -0
- package/generated/compiler/checker/checker.js +1215 -0
- package/generated/compiler/checker/exprs.js +791 -0
- package/generated/compiler/checker/flow.js +168 -0
- package/generated/compiler/checker/members.js +763 -0
- package/generated/compiler/checker/statements.js +792 -0
- package/generated/compiler/checker/symbols.js +90 -0
- package/generated/compiler/checker/typeops.js +348 -0
- package/generated/compiler/checker/yields.js +115 -0
- package/generated/compiler/diagnostics.js +138 -0
- package/generated/compiler/emit/emitter.js +2356 -0
- package/generated/compiler/emit/luau-types.js +137 -0
- package/generated/compiler/emit/names.js +130 -0
- package/generated/compiler/emit/runtime.js +432 -0
- package/generated/compiler/lexer.js +403 -0
- package/generated/compiler/parser.js +1881 -0
- package/generated/compiler/project.js +332 -0
- package/generated/compiler/roblox/api.js +388 -0
- package/generated/compiler/roblox/context.js +100 -0
- package/generated/compiler/source.js +59 -0
- package/generated/compiler/stdlib.js +232 -0
- package/generated/compiler/types.js +250 -0
- package/generated/intellisense.js +1 -15
- package/generated/lsp.js +1 -1
- package/generated/target/build-cache.js +4 -4
- package/generated/target/datamodel-generate.js +12 -0
- package/generated/target/gen-rojo-tree.js +15 -0
- package/generated/target/source-map.js +61 -8
- package/generated/target/studio-bridge.js +1 -0
- package/generated/utils/project.js +104 -31
- package/include/README.md +5 -0
- package/native/bin/.gitkeep +1 -0
- package/package.json +17 -6
- package/plugins/CluauppNav/Plugin.luau +28 -4
- package/rust/cluaupp/Cargo.lock +795 -0
- package/rust/cluaupp/Cargo.toml +17 -0
- package/rust/cluaupp/src/main.rs +717 -0
- package/scripts/postinstall-native.js +56 -0
- package/skills/README.md +3 -3
- package/skills/clpp-hive-flare/SKILL.md +30 -26
- package/skills/clpp-language/SKILL.md +67 -74
- package/skills/clpp-language/compiler.md +24 -36
- package/skills/clpp-style/SKILL.md +31 -44
- package/src/api/build-profile.ts +1 -1
- package/src/api/loader.ts +2 -2
- package/src/api/surface/build.ts +374 -0
- package/src/api/surface/luau-defs.ts +635 -0
- package/src/api/surface/model.ts +96 -0
- package/src/api-cli.ts +2 -2
- package/src/cli.ts +19 -18
- package/src/clpp/contract.ts +20 -3
- package/src/clpp/handshake.ts +25 -0
- package/src/clpp/modules.ts +17 -10
- package/src/clpp/runner.ts +52 -34
- package/src/compile.ts +20 -2
- package/src/compiler/ast.ts +336 -0
- package/src/compiler/checker/calls.ts +1025 -0
- package/src/compiler/checker/checker.ts +1352 -0
- package/src/compiler/checker/exprs.ts +805 -0
- package/src/compiler/checker/flow.ts +174 -0
- package/src/compiler/checker/members.ts +793 -0
- package/src/compiler/checker/statements.ts +802 -0
- package/src/compiler/checker/symbols.ts +219 -0
- package/src/compiler/checker/typeops.ts +355 -0
- package/src/compiler/checker/yields.ts +120 -0
- package/src/compiler/diagnostics.ts +163 -0
- package/src/compiler/emit/emitter.ts +2486 -0
- package/src/compiler/emit/luau-types.ts +143 -0
- package/src/compiler/emit/names.ts +130 -0
- package/src/compiler/emit/runtime.ts +438 -0
- package/src/compiler/lexer.ts +444 -0
- package/src/compiler/parser.ts +1943 -0
- package/src/compiler/project.ts +354 -0
- package/src/compiler/roblox/api.ts +408 -0
- package/src/compiler/roblox/context.ts +108 -0
- package/src/compiler/source.ts +67 -0
- package/src/compiler/stdlib.ts +256 -0
- package/src/compiler/types.ts +313 -0
- package/src/intellisense.ts +1 -13
- package/src/lsp.ts +1 -1
- package/src/target/build-cache.ts +5 -8
- package/src/target/datamodel-generate.ts +12 -1
- package/src/target/gen-rojo-tree.ts +15 -0
- package/src/target/source-map.ts +65 -27
- package/src/target/studio-bridge.ts +3 -0
- package/src/types.ts +3 -0
- package/src/utils/project.ts +99 -37
- package/templates/README.md +7 -0
- package/templates/{game → game-modern}/cluaupp.config.json +2 -2
- package/templates/{game → game-modern}/package.json +1 -2
- package/templates/game-modern/rokit.toml +2 -0
- package/templates/game-modern/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
- package/templates/game-modern/src/ServerScriptService/Handlers/Guard.server.clp +4 -0
- package/templates/game-modern/src/ServerScriptService/Main.server.clp +8 -0
- package/templates/game-modern/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
- package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +0 -29
- package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +0 -13
- package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +0 -83
- package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +0 -13
- package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +0 -18
- package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +0 -13
- package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +0 -14
- package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +0 -13
- package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +0 -15
- package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +0 -13
- package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +0 -50
- package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +0 -13
- package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +0 -12
- package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +0 -13
- package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +0 -16
- package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +0 -13
- package/examples/game/src/Client/Controllers/DataController.client.clpp +0 -7
- package/examples/game/src/Client/Main.client.clpp +0 -4
- package/examples/game/src/Declarations/Net.flare +0 -5
- package/examples/game/src/Include/GameTypes.clh +0 -40
- package/examples/game/src/Modules/Core/Guard.server.clpp +0 -7
- package/examples/game/src/Modules/Core/PlayerHandler.server.clpp +0 -23
- package/examples/game/src/Server/Boot/DataBoot.server.clpp +0 -13
- package/examples/game/src/Server/Main.server.clpp +0 -4
- package/templates/game/.clangd +0 -25
- package/templates/game/.vscode/extensions.json +0 -8
- package/templates/game/.vscode/settings.json +0 -17
- package/templates/game/Packages/.gitkeep +0 -0
- package/templates/game/compile_flags.txt +0 -6
- package/templates/game/default.project.json +0 -41
- package/templates/game/include/clpp/datatypes.clh +0 -575
- package/templates/game/include/clpp/generated/enums.clh +0 -4920
- package/templates/game/include/clpp/generated/instances.clh +0 -87182
- package/templates/game/include/clpp/libs/arrayindexer.clh +0 -12
- package/templates/game/include/clpp/libs/axiom.clh +0 -154
- package/templates/game/include/clpp/libs/bloom.clh +0 -58
- package/templates/game/include/clpp/libs/coil.clh +0 -37
- package/templates/game/include/clpp/libs/crest.clh +0 -22
- package/templates/game/include/clpp/libs/echo.clh +0 -52
- package/templates/game/include/clpp/libs/ember.clh +0 -17
- package/templates/game/include/clpp/libs/flare.clh +0 -65
- package/templates/game/include/clpp/libs/gleam.clh +0 -111
- package/templates/game/include/clpp/libs/guide.clh +0 -42
- package/templates/game/include/clpp/libs/helm.clh +0 -31
- package/templates/game/include/clpp/libs/hive.clh +0 -20
- package/templates/game/include/clpp/libs/keep.clh +0 -158
- package/templates/game/include/clpp/libs/lens.clh +0 -24
- package/templates/game/include/clpp/libs/mint.clh +0 -28
- package/templates/game/include/clpp/libs/net.clh +0 -31
- package/templates/game/include/clpp/libs/occlude.clh +0 -15
- package/templates/game/include/clpp/libs/pin.clh +0 -28
- package/templates/game/include/clpp/libs/promise.clh +0 -24
- package/templates/game/include/clpp/libs/roster.clh +0 -123
- package/templates/game/include/clpp/libs/shift.clh +0 -22
- package/templates/game/include/clpp/libs/spark.clh +0 -28
- package/templates/game/include/clpp/libs/stage.clh +0 -23
- package/templates/game/include/clpp/libs/sweep.clh +0 -23
- package/templates/game/include/clpp/libs/trace.clh +0 -18
- package/templates/game/include/clpp/libs/ward.clh +0 -19
- package/templates/game/include/clpp/libs.clh +0 -31
- package/templates/game/include/clpp/roblox.clh +0 -41
- package/templates/game/rokit.toml +0 -5
- package/templates/game/src/Client/Controllers/DataController.client.clpp +0 -7
- package/templates/game/src/Client/Main.client.clpp +0 -4
- package/templates/game/src/Declarations/Net.flare +0 -5
- package/templates/game/src/Include/GameTypes.clh +0 -40
- package/templates/game/src/Modules/Core/Guard.server.clpp +0 -7
- package/templates/game/src/Modules/Core/PlayerHandler.server.clpp +0 -24
- package/templates/game/src/Server/Boot/DataBoot.server.clpp +0 -13
- package/templates/game/src/Server/Main.server.clpp +0 -4
- package/templates/game/stylua.toml +0 -9
- package/templates/game/wally.toml +0 -12
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CL++ standard library modules (`@clpp.axiom`, `@clpp.text`, `@clpp.math`, `@clpp.http`) on the
|
|
4
|
+
* Roblox target. Each function has a CL++ signature and a lowering: an inline Luau template using
|
|
5
|
+
* fast built-ins, or a call into the CluauppLibs runtime (`Axiom`) / a file-local helper.
|
|
6
|
+
*
|
|
7
|
+
* Templates use `$1…$n` for arguments; `@n` marks arguments that are evaluated more than once,
|
|
8
|
+
* so the emitter only inlines when those arguments are side-effect free.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.STD_PATHS = exports.DESKTOP_ONLY = void 0;
|
|
12
|
+
exports.stdModule = stdModule;
|
|
13
|
+
exports.stdFunctionType = stdFunctionType;
|
|
14
|
+
const types_js_1 = require("./types.js");
|
|
15
|
+
const typeOf = {
|
|
16
|
+
float: types_js_1.T.float,
|
|
17
|
+
int: types_js_1.T.int,
|
|
18
|
+
bool: types_js_1.T.bool,
|
|
19
|
+
string: types_js_1.T.string,
|
|
20
|
+
Vector2: types_js_1.T.datatype("Vector2"),
|
|
21
|
+
Vector3: types_js_1.T.datatype("Vector3"),
|
|
22
|
+
Color3: types_js_1.T.datatype("Color3"),
|
|
23
|
+
CFrame: types_js_1.T.datatype("CFrame"),
|
|
24
|
+
UDim2: types_js_1.T.datatype("UDim2"),
|
|
25
|
+
floats: types_js_1.T.list(types_js_1.T.float),
|
|
26
|
+
strings: types_js_1.T.list(types_js_1.T.string),
|
|
27
|
+
list: types_js_1.T.list(types_js_1.T.any, false),
|
|
28
|
+
any: types_js_1.T.any,
|
|
29
|
+
strings2: types_js_1.T.list(types_js_1.T.string),
|
|
30
|
+
};
|
|
31
|
+
function sig(spec, inline, extra = {}) {
|
|
32
|
+
const m = /^(\w+)\(([^)]*)\)\s*->\s*(\w+)$/.exec(spec);
|
|
33
|
+
if (!m) {
|
|
34
|
+
throw new Error(`bad std signature ${spec}`);
|
|
35
|
+
}
|
|
36
|
+
const params = m[2]
|
|
37
|
+
.split(",")
|
|
38
|
+
.map((p) => p.trim())
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.map((p, i) => {
|
|
41
|
+
const optional = p.endsWith("?");
|
|
42
|
+
const [tname, pname] = p.replace("?", "").split(/\s+/);
|
|
43
|
+
return { name: pname || `p${i}`, type: typeOf[tname] ?? types_js_1.T.any, optional };
|
|
44
|
+
});
|
|
45
|
+
return { name: m[1], params, ret: typeOf[m[3]] ?? types_js_1.T.void, inline, ...extra };
|
|
46
|
+
}
|
|
47
|
+
const AXIOM = [
|
|
48
|
+
sig("Clamp(float value, float min, float max) -> float", "math.min(math.max($1, $2), $3)"),
|
|
49
|
+
sig("Map(float value, float inMin, float inMax, float outMin, float outMax) -> float", null),
|
|
50
|
+
sig("Wrap(float value, float min, float max) -> float", null),
|
|
51
|
+
sig("Sign(float value) -> float", "math.sign($1)"),
|
|
52
|
+
sig("Round(float value, float places?) -> float", null),
|
|
53
|
+
sig("Snap(float value, float step) -> float", null),
|
|
54
|
+
sig("PingPong(float t, float length) -> float", null),
|
|
55
|
+
sig("Saturate(float value) -> float", "math.min(math.max($1, 0), 1)"),
|
|
56
|
+
sig("Fract(float value) -> float", "@1 - math.floor(@1)"),
|
|
57
|
+
sig("InvLerp(float from, float to, float value) -> float", null),
|
|
58
|
+
sig("Approach(float current, float target, float maxDelta) -> float", null),
|
|
59
|
+
sig("IsFinite(float value) -> bool", "@1 == @1 and @1 ~= math.huge and @1 ~= -math.huge"),
|
|
60
|
+
sig("Abs(float value) -> float", "math.abs($1)"),
|
|
61
|
+
sig("Min(float a, float b) -> float", "math.min($1, $2)"),
|
|
62
|
+
sig("Max(float a, float b) -> float", "math.max($1, $2)"),
|
|
63
|
+
sig("Pow(float base, float exp) -> float", "$1 ^ $2"),
|
|
64
|
+
sig("Sqrt(float value) -> float", "math.sqrt($1)"),
|
|
65
|
+
sig("Cbrt(float value) -> float", null),
|
|
66
|
+
sig("Hypot(float a, float b) -> float", "math.sqrt(@1 * @1 + @2 * @2)"),
|
|
67
|
+
sig("Log(float value) -> float", "math.log($1)"),
|
|
68
|
+
sig("Log2(float value) -> float", "math.log($1, 2)"),
|
|
69
|
+
sig("Log10(float value) -> float", "math.log10($1)"),
|
|
70
|
+
sig("Exp(float value) -> float", "math.exp($1)"),
|
|
71
|
+
sig("Smoothstep(float edge0, float edge1, float x) -> float", null),
|
|
72
|
+
sig("Smootherstep(float edge0, float edge1, float x) -> float", null),
|
|
73
|
+
sig("Gcd(float a, float b) -> float", null),
|
|
74
|
+
sig("Lcm(float a, float b) -> float", null),
|
|
75
|
+
sig("IsEven(float value) -> bool", "$1 % 2 == 0"),
|
|
76
|
+
sig("IsOdd(float value) -> bool", "$1 % 2 == 1"),
|
|
77
|
+
sig("IsNaN(float value) -> bool", "@1 ~= @1"),
|
|
78
|
+
sig("Factorial(float n) -> float", null),
|
|
79
|
+
sig("Scale(float value, float index) -> float", null),
|
|
80
|
+
sig("Lerp(float from, float to, float alpha) -> float", "@1 + (@2 - @1) * $3"),
|
|
81
|
+
sig("LerpClamped(float from, float to, float alpha) -> float", "@1 + (@2 - @1) * math.min(math.max($3, 0), 1)"),
|
|
82
|
+
sig("LerpVector2(Vector2 from, Vector2 to, float alpha) -> Vector2", "$1:Lerp($2, $3)"),
|
|
83
|
+
sig("LerpVector3(Vector3 from, Vector3 to, float alpha) -> Vector3", "$1:Lerp($2, $3)"),
|
|
84
|
+
sig("LerpVector(Vector3 from, Vector3 to, float alpha) -> Vector3", "$1:Lerp($2, $3)"),
|
|
85
|
+
sig("LerpColor3(Color3 from, Color3 to, float alpha) -> Color3", "$1:Lerp($2, $3)"),
|
|
86
|
+
sig("LerpCFrame(CFrame from, CFrame to, float alpha) -> CFrame", "$1:Lerp($2, $3)"),
|
|
87
|
+
sig("SlerpCFrame(CFrame from, CFrame to, float alpha) -> CFrame", "$1:Lerp($2, $3)"),
|
|
88
|
+
sig("LerpUDim2(UDim2 from, UDim2 to, float alpha) -> UDim2", "$1:Lerp($2, $3)"),
|
|
89
|
+
sig("LerpAngle(float from, float to, float alpha) -> float", null),
|
|
90
|
+
sig("Inverse(float from, float to, float value) -> float", null),
|
|
91
|
+
sig("Project(Vector3 a, Vector3 b) -> Vector3", null),
|
|
92
|
+
sig("Reject(Vector3 a, Vector3 b) -> Vector3", null),
|
|
93
|
+
sig("Reflect(Vector3 incident, Vector3 normal) -> Vector3", null),
|
|
94
|
+
sig("Angle(Vector3 a, Vector3 b) -> float", "$1:Angle($2)"),
|
|
95
|
+
sig("Distance(Vector3 a, Vector3 b) -> float", "($2 - $1).Magnitude"),
|
|
96
|
+
sig("Distance2(Vector2 a, Vector2 b) -> float", "($2 - $1).Magnitude"),
|
|
97
|
+
sig("Orthonormal(Vector3 forward, Vector3 up?) -> Vector3", null),
|
|
98
|
+
sig("Slerp(Vector3 a, Vector3 b, float t) -> Vector3", null),
|
|
99
|
+
sig("LookAt(Vector3 from, Vector3 target) -> Vector3", null),
|
|
100
|
+
sig("Flat(Vector3 value) -> Vector3", null),
|
|
101
|
+
sig("Dot(Vector3 a, Vector3 b) -> float", "$1:Dot($2)"),
|
|
102
|
+
sig("Cross(Vector3 a, Vector3 b) -> Vector3", "$1:Cross($2)"),
|
|
103
|
+
sig("Length(Vector3 v) -> float", "$1.Magnitude"),
|
|
104
|
+
sig("Normalize(Vector3 v) -> Vector3", null),
|
|
105
|
+
sig("CubicBezier(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) -> Vector3", null),
|
|
106
|
+
sig("QuadraticBezier(float t, Vector3 p0, Vector3 p1, Vector3 p2) -> Vector3", null),
|
|
107
|
+
sig("Hover(float t, Vector3 base, Vector3 amplitude) -> Vector3", null),
|
|
108
|
+
sig("Float(float t, Vector3 base, Vector3 amplitude) -> Vector3", null),
|
|
109
|
+
sig("FloatSpin(float t, Vector3 base) -> Vector3", null),
|
|
110
|
+
sig("AabbContains(Vector3 point, Vector3 min, Vector3 max) -> bool", null),
|
|
111
|
+
sig("SphereContains(Vector3 point, Vector3 center, float radius) -> bool", "($1 - $2).Magnitude <= $3"),
|
|
112
|
+
sig("RayPlane(Vector3 origin, Vector3 dir, Vector3 point, Vector3 normal) -> Vector3", null),
|
|
113
|
+
sig("Barycentric(Vector3 p, Vector3 a, Vector3 b, Vector3 c) -> Vector3", null),
|
|
114
|
+
sig("ClosestPointOnSegment(Vector3 p, Vector3 a, Vector3 b) -> Vector3", null),
|
|
115
|
+
sig("Deg(float rad) -> float", "math.deg($1)"),
|
|
116
|
+
sig("Rad(float deg) -> float", "math.rad($1)"),
|
|
117
|
+
sig("DeltaAngle(float from, float to) -> float", null),
|
|
118
|
+
sig("AngleDiff(float from, float to) -> float", null),
|
|
119
|
+
sig("DeltaAngleDegrees(float from, float to) -> float", null),
|
|
120
|
+
sig("NormalizeAngle(float angle) -> float", null),
|
|
121
|
+
sig("Sin(float x) -> float", "math.sin($1)"),
|
|
122
|
+
sig("Cos(float x) -> float", "math.cos($1)"),
|
|
123
|
+
sig("Tan(float x) -> float", "math.tan($1)"),
|
|
124
|
+
sig("Asin(float x) -> float", "math.asin($1)"),
|
|
125
|
+
sig("Acos(float x) -> float", "math.acos($1)"),
|
|
126
|
+
sig("Atan2(float y, float x) -> float", "math.atan2($1, $2)"),
|
|
127
|
+
sig("RandomRange(float min, float max) -> float", null),
|
|
128
|
+
sig("Random(float min, float max) -> float", null),
|
|
129
|
+
sig("Weighted(floats weights) -> int", null),
|
|
130
|
+
sig("Gaussian(float mean?, float std?) -> float", null),
|
|
131
|
+
sig("Average(floats values) -> float", null),
|
|
132
|
+
sig("Sum(floats values) -> float", null),
|
|
133
|
+
sig("HashU32(float n) -> int", null),
|
|
134
|
+
sig("Value1(float x) -> float", null),
|
|
135
|
+
sig("Value2(float x, float y) -> float", null),
|
|
136
|
+
sig("Value3(float x, float y, float z) -> float", null),
|
|
137
|
+
sig("FromHSV(float h, float s, float v) -> Color3", "Color3.fromHSV($1, $2, $3)"),
|
|
138
|
+
sig("Contrast(Color3 color, float amount) -> Color3", null),
|
|
139
|
+
sig("LerpHSV(Color3 a, Color3 b, float t) -> Color3", null),
|
|
140
|
+
sig("Floor(float value) -> float", "math.floor($1)"),
|
|
141
|
+
sig("Ceil(float value) -> float", "math.ceil($1)"),
|
|
142
|
+
sig("Trunc(float value) -> float", null),
|
|
143
|
+
sig("Pi() -> float", "math.pi"),
|
|
144
|
+
];
|
|
145
|
+
const TEXT = [
|
|
146
|
+
sig("trim(string text) -> string", null, { helper: "trim" }),
|
|
147
|
+
sig("lower(string text) -> string", "string.lower($1)"),
|
|
148
|
+
sig("upper(string text) -> string", "string.upper($1)"),
|
|
149
|
+
sig("contains(string text, string part) -> bool", "string.find($1, $2, 1, true) ~= nil"),
|
|
150
|
+
sig("split(string text, string separator) -> strings", "string.split($1, $2)"),
|
|
151
|
+
sig("replace(string text, string target, string replacement) -> string", null, { helper: "replace" }),
|
|
152
|
+
sig("startsWith(string text, string part) -> bool", "string.sub($1, 1, #@2) == @2"),
|
|
153
|
+
sig("endsWith(string text, string part) -> bool", null, { helper: "endsWith" }),
|
|
154
|
+
sig("repeat(string text, int count) -> string", "string.rep($1, $2)"),
|
|
155
|
+
sig("toNumber(string text) -> float", null, { helper: "toNumber" }),
|
|
156
|
+
sig("indexOf(string text, string part) -> int", null, { helper: "indexOf" }),
|
|
157
|
+
sig("joinAll(list parts, string separator) -> string", null, { helper: "joinAll" }),
|
|
158
|
+
];
|
|
159
|
+
const MATH = [sig("abs(float n) -> float", "math.abs($1)")];
|
|
160
|
+
const HTTP = [sig("host(string url) -> string", null, { helper: "urlHost" })];
|
|
161
|
+
/** @clpp.json on Roblox: HttpService JSONEncode/JSONDecode plus dotted-path helpers. */
|
|
162
|
+
const JSON_FNS = [
|
|
163
|
+
sig("Parse(string text) -> any", null, { helper: "jsonParse" }),
|
|
164
|
+
sig("Valid(string text) -> bool", null, { helper: "jsonValid" }),
|
|
165
|
+
sig("Stringify(any value) -> string", null, { helper: "jsonStringify" }),
|
|
166
|
+
sig("Pretty(any value) -> string", null, { helper: "jsonPretty" }),
|
|
167
|
+
sig("Get(any value, string path) -> any", null, { helper: "jsonGet" }),
|
|
168
|
+
sig("Has(any value, string path) -> bool", null, { helper: "jsonHas" }),
|
|
169
|
+
sig("Set(any target, string key, any value) -> any", null, { helper: "jsonSet" }),
|
|
170
|
+
sig("Object() -> any", "{}"),
|
|
171
|
+
sig("Keys(any object) -> strings", null, { helper: "jsonKeys" }),
|
|
172
|
+
];
|
|
173
|
+
/** @clpp.time on Roblox: os.clock / DateTime / os.date / task.wait. */
|
|
174
|
+
const TIME = [
|
|
175
|
+
sig("Now() -> float", "DateTime.now().UnixTimestampMillis / 1000"),
|
|
176
|
+
sig("Clock() -> float", "os.clock()"),
|
|
177
|
+
sig("Sleep(float ms) -> void", "task.wait($1 / 1000)"),
|
|
178
|
+
sig("Date() -> string", 'os.date("%Y-%m-%d")'),
|
|
179
|
+
sig("TimeOfDay() -> string", 'os.date("%H:%M:%S")'),
|
|
180
|
+
sig("Format(string pattern) -> string", "os.date($1)"),
|
|
181
|
+
sig("Year() -> int", 'os.date("*t").year'),
|
|
182
|
+
sig("Month() -> int", 'os.date("*t").month'),
|
|
183
|
+
sig("Day() -> int", 'os.date("*t").day'),
|
|
184
|
+
sig("Hour() -> int", 'os.date("*t").hour'),
|
|
185
|
+
sig("Minute() -> int", 'os.date("*t").min'),
|
|
186
|
+
sig("Second() -> int", 'os.date("*t").sec'),
|
|
187
|
+
sig("Weekday() -> int", 'os.date("*t").wday - 1'),
|
|
188
|
+
sig("DayOfYear() -> int", 'os.date("*t").yday'),
|
|
189
|
+
];
|
|
190
|
+
const MODULES = {
|
|
191
|
+
axiom: new Map(AXIOM.map((f) => [f.name, f])),
|
|
192
|
+
text: new Map(TEXT.map((f) => [f.name, f])),
|
|
193
|
+
math: new Map(MATH.map((f) => [f.name, f])),
|
|
194
|
+
http: new Map(HTTP.map((f) => [f.name, f])),
|
|
195
|
+
json: new Map(JSON_FNS.map((f) => [f.name, f])),
|
|
196
|
+
time: new Map(TIME.map((f) => [f.name, f])),
|
|
197
|
+
};
|
|
198
|
+
for (const f of AXIOM) {
|
|
199
|
+
if (!f.inline) {
|
|
200
|
+
f.runtime = f.name;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/** Desktop-only CL++ modules and what to use on Roblox instead. */
|
|
204
|
+
exports.DESKTOP_ONLY = {
|
|
205
|
+
"@clpp.fs": "Roblox games have no file system; persist data with DataStoreService (or CluauppLibs Keep)",
|
|
206
|
+
"@clpp.os": "Roblox games have no process environment; use attributes or a config module",
|
|
207
|
+
"@clpp.window": "the Roblox client owns the window; use RunService.RenderStepped and UserInputService",
|
|
208
|
+
"@clpp.gfx": "draw with GUI objects (Frame, ImageLabel) or EditableImage",
|
|
209
|
+
"@clpp.ui": "build UI with ScreenGui/Frame/TextButton, or CluauppLibs Gleam",
|
|
210
|
+
"@clpp.gui": "build UI with ScreenGui instances, or the declarative CluauppLibs Gleam",
|
|
211
|
+
"@clpp.audio": "play Sound instances (SoundService) instead",
|
|
212
|
+
"@clpp.input": "read input with UserInputService/ContextActionService (scripts cannot drive the mouse)",
|
|
213
|
+
"@clpp.io": "there is no console input on Roblox; use print/warn",
|
|
214
|
+
};
|
|
215
|
+
exports.STD_PATHS = {
|
|
216
|
+
"@clpp.axiom": "axiom",
|
|
217
|
+
"@clpp.Axion": "axiom",
|
|
218
|
+
"@clpp.mathutils": "axiom",
|
|
219
|
+
"@clpp.text": "text",
|
|
220
|
+
"@clpp.math": "math",
|
|
221
|
+
"@clpp.http": "http",
|
|
222
|
+
"@clpp.json": "json",
|
|
223
|
+
"@clpp.time": "time",
|
|
224
|
+
"@clpp.fs": "unsupported",
|
|
225
|
+
"@clpp.os": "unsupported",
|
|
226
|
+
};
|
|
227
|
+
function stdModule(name) {
|
|
228
|
+
return MODULES[name];
|
|
229
|
+
}
|
|
230
|
+
function stdFunctionType(f) {
|
|
231
|
+
return types_js_1.T.func(f.params, f.ret);
|
|
232
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CL++ type model for the Roblox host: the CL++ core types plus Roblox classes, datatypes,
|
|
4
|
+
* enums and signals. Types are plain immutable objects; struct/enum details live in registries
|
|
5
|
+
* keyed by `id` (`<moduleId>::<Name>`).
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.T = void 0;
|
|
9
|
+
exports.prune = prune;
|
|
10
|
+
exports.isNumeric = isNumeric;
|
|
11
|
+
exports.isIntLike = isIntLike;
|
|
12
|
+
exports.isDynamic = isDynamic;
|
|
13
|
+
exports.isStringLike = isStringLike;
|
|
14
|
+
exports.isBoolLike = isBoolLike;
|
|
15
|
+
exports.widen = widen;
|
|
16
|
+
exports.nonNull = nonNull;
|
|
17
|
+
exports.isNullable = isNullable;
|
|
18
|
+
exports.isValueTable = isValueTable;
|
|
19
|
+
exports.sameType = sameType;
|
|
20
|
+
exports.typeToString = typeToString;
|
|
21
|
+
exports.T = {
|
|
22
|
+
any: { k: "any" },
|
|
23
|
+
unknown: { k: "unknown" },
|
|
24
|
+
never: { k: "never" },
|
|
25
|
+
void: { k: "void" },
|
|
26
|
+
null: { k: "null" },
|
|
27
|
+
int: { k: "int" },
|
|
28
|
+
float: { k: "float" },
|
|
29
|
+
bool: { k: "bool" },
|
|
30
|
+
string: { k: "string" },
|
|
31
|
+
buffer: { k: "buffer" },
|
|
32
|
+
thread: { k: "thread" },
|
|
33
|
+
instance: (cls) => ({ k: "instance", cls }),
|
|
34
|
+
datatype: (name) => ({ k: "datatype", name }),
|
|
35
|
+
list: (elem, typed = true) => ({ k: "list", elem, typed }),
|
|
36
|
+
dict: (key, value) => ({ k: "dict", key, value }),
|
|
37
|
+
option: (inner) => (inner.k === "option" || inner.k === "any" || inner.k === "unknown" || inner.k === "null" ? inner : { k: "option", inner }),
|
|
38
|
+
func: (params, ret, variadic = null) => ({ k: "func", params, ret, variadic }),
|
|
39
|
+
};
|
|
40
|
+
/** Follow solved inference slots. */
|
|
41
|
+
function prune(t) {
|
|
42
|
+
let cur = t;
|
|
43
|
+
while (cur.k === "infer" && cur.resolved) {
|
|
44
|
+
cur = cur.resolved;
|
|
45
|
+
}
|
|
46
|
+
return cur;
|
|
47
|
+
}
|
|
48
|
+
function isNumeric(t) {
|
|
49
|
+
const p = prune(t);
|
|
50
|
+
return p.k === "int" || p.k === "float" || (p.k === "lit" && typeof p.value === "number");
|
|
51
|
+
}
|
|
52
|
+
function isIntLike(t) {
|
|
53
|
+
const p = prune(t);
|
|
54
|
+
return p.k === "int" || (p.k === "lit" && typeof p.value === "number" && Number.isInteger(p.value)) || p.k === "enum";
|
|
55
|
+
}
|
|
56
|
+
function isDynamic(t) {
|
|
57
|
+
const p = prune(t);
|
|
58
|
+
return p.k === "any" || p.k === "unknown" || (p.k === "infer" && !p.resolved);
|
|
59
|
+
}
|
|
60
|
+
function isStringLike(t) {
|
|
61
|
+
const p = prune(t);
|
|
62
|
+
return p.k === "string" || (p.k === "lit" && typeof p.value === "string");
|
|
63
|
+
}
|
|
64
|
+
function isBoolLike(t) {
|
|
65
|
+
const p = prune(t);
|
|
66
|
+
return p.k === "bool" || (p.k === "lit" && typeof p.value === "boolean");
|
|
67
|
+
}
|
|
68
|
+
/** Widen literal types: `"Idle"` → string, `3` → int. */
|
|
69
|
+
function widen(t) {
|
|
70
|
+
const p = prune(t);
|
|
71
|
+
if (p.k === "lit") {
|
|
72
|
+
if (typeof p.value === "string") {
|
|
73
|
+
return exports.T.string;
|
|
74
|
+
}
|
|
75
|
+
if (typeof p.value === "boolean") {
|
|
76
|
+
return exports.T.bool;
|
|
77
|
+
}
|
|
78
|
+
return Number.isInteger(p.value) ? exports.T.int : exports.T.float;
|
|
79
|
+
}
|
|
80
|
+
return p;
|
|
81
|
+
}
|
|
82
|
+
/** Remove `null`/option wrappers. */
|
|
83
|
+
function nonNull(t) {
|
|
84
|
+
const p = prune(t);
|
|
85
|
+
if (p.k === "option") {
|
|
86
|
+
return p.inner;
|
|
87
|
+
}
|
|
88
|
+
if (p.k === "union") {
|
|
89
|
+
const members = p.members.filter((m) => prune(m).k !== "null");
|
|
90
|
+
return members.length === 1 ? members[0] : { k: "union", members };
|
|
91
|
+
}
|
|
92
|
+
return p;
|
|
93
|
+
}
|
|
94
|
+
function isNullable(t) {
|
|
95
|
+
const p = prune(t);
|
|
96
|
+
return p.k === "option" || p.k === "null" || (p.k === "union" && p.members.some((m) => prune(m).k === "null"));
|
|
97
|
+
}
|
|
98
|
+
/** Tables that CL++ treats as values (copied on assignment). */
|
|
99
|
+
function isValueTable(t) {
|
|
100
|
+
const p = prune(t);
|
|
101
|
+
return p.k === "struct" || p.k === "list" || p.k === "dict" || p.k === "result";
|
|
102
|
+
}
|
|
103
|
+
function sameType(a, b) {
|
|
104
|
+
const x = prune(a);
|
|
105
|
+
const y = prune(b);
|
|
106
|
+
if (x === y) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
if (x.k !== y.k) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
switch (x.k) {
|
|
113
|
+
case "lit":
|
|
114
|
+
return x.value === y.value;
|
|
115
|
+
case "list":
|
|
116
|
+
return sameType(x.elem, y.elem);
|
|
117
|
+
case "dict":
|
|
118
|
+
return sameType(x.key, y.key) && sameType(x.value, y.value);
|
|
119
|
+
case "struct":
|
|
120
|
+
return x.id === y.id && x.args.length === y.args.length && x.args.every((a2, i) => sameType(a2, y.args[i]));
|
|
121
|
+
case "enum":
|
|
122
|
+
case "variant":
|
|
123
|
+
return x.id === y.id;
|
|
124
|
+
case "option":
|
|
125
|
+
return sameType(x.inner, y.inner);
|
|
126
|
+
case "result":
|
|
127
|
+
return sameType(x.ok, y.ok) && sameType(x.err, y.err);
|
|
128
|
+
case "task":
|
|
129
|
+
return sameType(x.result, y.result);
|
|
130
|
+
case "instance":
|
|
131
|
+
return x.cls === y.cls;
|
|
132
|
+
case "datatype":
|
|
133
|
+
return x.name === y.name;
|
|
134
|
+
case "rbxEnumItem":
|
|
135
|
+
case "rbxEnum":
|
|
136
|
+
return x.enumName === y.enumName;
|
|
137
|
+
case "param":
|
|
138
|
+
return x.name === y.name;
|
|
139
|
+
case "tuple":
|
|
140
|
+
return x.elems.length === y.elems.length && x.elems.every((e, i) => sameType(e, y.elems[i]));
|
|
141
|
+
case "union":
|
|
142
|
+
return x.members.length === y.members.length && x.members.every((m) => y.members.some((n) => sameType(m, n)));
|
|
143
|
+
default:
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/** CL++ notation, for diagnostics and hover. */
|
|
148
|
+
function typeToString(t, depth = 0) {
|
|
149
|
+
const p = prune(t);
|
|
150
|
+
if (depth > 6) {
|
|
151
|
+
return "…";
|
|
152
|
+
}
|
|
153
|
+
const s = (x) => typeToString(x, depth + 1);
|
|
154
|
+
switch (p.k) {
|
|
155
|
+
case "any":
|
|
156
|
+
return "any";
|
|
157
|
+
case "unknown":
|
|
158
|
+
return "unknown";
|
|
159
|
+
case "never":
|
|
160
|
+
return "never";
|
|
161
|
+
case "void":
|
|
162
|
+
return "void";
|
|
163
|
+
case "null":
|
|
164
|
+
return "null";
|
|
165
|
+
case "int":
|
|
166
|
+
case "float":
|
|
167
|
+
case "bool":
|
|
168
|
+
case "string":
|
|
169
|
+
case "buffer":
|
|
170
|
+
case "thread":
|
|
171
|
+
return p.k;
|
|
172
|
+
case "lit":
|
|
173
|
+
return typeof p.value === "string" ? JSON.stringify(p.value) : String(p.value);
|
|
174
|
+
case "list":
|
|
175
|
+
return p.typed ? `array<${s(p.elem)}>` : "list";
|
|
176
|
+
case "dict":
|
|
177
|
+
return `dictionary<${s(p.key)}, ${s(p.value)}>`;
|
|
178
|
+
case "tuple":
|
|
179
|
+
return `(${p.elems.map(s).join(", ")})`;
|
|
180
|
+
case "table":
|
|
181
|
+
return `{ ${Object.entries(p.fields).slice(0, 6).map(([k, v]) => `${k}: ${s(v)}`).join(", ")} }`;
|
|
182
|
+
case "struct":
|
|
183
|
+
return p.args.length ? `${p.name}<${p.args.map(s).join(", ")}>` : p.name;
|
|
184
|
+
case "enum":
|
|
185
|
+
case "variant":
|
|
186
|
+
return p.name;
|
|
187
|
+
case "option":
|
|
188
|
+
return `${s(p.inner)}?`;
|
|
189
|
+
case "result":
|
|
190
|
+
return `Result<${s(p.ok)}, ${s(p.err)}>`;
|
|
191
|
+
case "task":
|
|
192
|
+
return isDynamic(p.result) || p.result.k === "void" ? "task" : `task<${s(p.result)}>`;
|
|
193
|
+
case "func": {
|
|
194
|
+
const params = p.params.map((x) => `${s(x.type)}${x.optional ? "?" : ""}`);
|
|
195
|
+
if (p.variadic) {
|
|
196
|
+
params.push(`...${s(p.variadic)}`);
|
|
197
|
+
}
|
|
198
|
+
return `func(${params.join(", ")}) -> ${s(p.ret)}`;
|
|
199
|
+
}
|
|
200
|
+
case "union":
|
|
201
|
+
return p.members.map(s).join(" | ");
|
|
202
|
+
case "param":
|
|
203
|
+
return p.name;
|
|
204
|
+
case "instance":
|
|
205
|
+
return p.cls;
|
|
206
|
+
case "datatype":
|
|
207
|
+
return p.name;
|
|
208
|
+
case "rbxEnumItem":
|
|
209
|
+
return `Enum.${p.enumName}`;
|
|
210
|
+
case "rbxEnum":
|
|
211
|
+
return `Enum.${p.enumName} (enum)`;
|
|
212
|
+
case "rbxEnums":
|
|
213
|
+
return "Enum";
|
|
214
|
+
case "rbxSignal":
|
|
215
|
+
return `RBXScriptSignal<${p.args.map(s).join(", ")}>`;
|
|
216
|
+
case "clSignal":
|
|
217
|
+
return p.params ? `signal(${p.params.map(s).join(", ")})` : "signal";
|
|
218
|
+
case "namespace":
|
|
219
|
+
return nsToString(p.ns);
|
|
220
|
+
case "infer":
|
|
221
|
+
return "unknown";
|
|
222
|
+
default:
|
|
223
|
+
return "unknown";
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function nsToString(ns) {
|
|
227
|
+
switch (ns.kind) {
|
|
228
|
+
case "module":
|
|
229
|
+
case "luauModule":
|
|
230
|
+
return `module ${ns.alias}`;
|
|
231
|
+
case "library":
|
|
232
|
+
return `library ${ns.name}`;
|
|
233
|
+
case "datatype":
|
|
234
|
+
return `${ns.name} (datatype)`;
|
|
235
|
+
case "instanceStatic":
|
|
236
|
+
return "Instance";
|
|
237
|
+
case "struct":
|
|
238
|
+
return `struct ${ns.name}`;
|
|
239
|
+
case "enum":
|
|
240
|
+
return `enum ${ns.name}`;
|
|
241
|
+
case "clNamespace":
|
|
242
|
+
return `namespace ${ns.name}`;
|
|
243
|
+
case "stdlib":
|
|
244
|
+
return `module ${ns.alias}`;
|
|
245
|
+
case "result":
|
|
246
|
+
return "Result";
|
|
247
|
+
default:
|
|
248
|
+
return "namespace";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -13,8 +13,6 @@ const node_os_1 = __importDefault(require("node:os"));
|
|
|
13
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
14
|
const node_child_process_1 = require("node:child_process");
|
|
15
15
|
const package_info_js_1 = require("./package-info.js");
|
|
16
|
-
const contract_js_1 = require("./clpp/contract.js");
|
|
17
|
-
const runner_js_1 = require("./clpp/runner.js");
|
|
18
16
|
const paths_js_1 = require("./clpp/paths.js");
|
|
19
17
|
const editor_install_js_1 = require("./editor-install.js");
|
|
20
18
|
function copyDir(from, to) {
|
|
@@ -111,7 +109,7 @@ function writeVscode(root) {
|
|
|
111
109
|
});
|
|
112
110
|
}
|
|
113
111
|
function diagnosticsFor(_source, _fileName) {
|
|
114
|
-
//
|
|
112
|
+
// CL++ diagnostics are reported by the compiler during build. Do not spawn a compiler
|
|
115
113
|
// from the editor — that duplicates source=clpp and freezes on every keystroke.
|
|
116
114
|
return [];
|
|
117
115
|
}
|
|
@@ -198,18 +196,6 @@ async function installEditorSupport() {
|
|
|
198
196
|
console.log(" ", dest);
|
|
199
197
|
}
|
|
200
198
|
}
|
|
201
|
-
if ((0, runner_js_1.hasClpp)()) {
|
|
202
|
-
const result = (0, node_child_process_1.spawnSync)("clpp", ["install"], { encoding: "utf8", windowsHide: true });
|
|
203
|
-
if (result.status === 0) {
|
|
204
|
-
console.log(String(result.stderr || result.stdout || "clpp install ok").trim());
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
console.log("cluaupp:", contract_js_1.CLPP_INSTALL_HINT);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
console.log("cluaupp:", contract_js_1.CLPP_INSTALL_HINT);
|
|
212
|
-
}
|
|
213
199
|
return { local };
|
|
214
200
|
}
|
|
215
201
|
exports.isClppSource = paths_js_1.isSourceFile;
|
package/generated/lsp.js
CHANGED
|
@@ -34,7 +34,7 @@ function flareDiagnostics(document) {
|
|
|
34
34
|
}));
|
|
35
35
|
}
|
|
36
36
|
function start(_options = {}) {
|
|
37
|
-
const connection = (0, node_1.createConnection)(node_1.ProposedFeatures.all);
|
|
37
|
+
const connection = (0, node_1.createConnection)(node_1.ProposedFeatures.all, process.stdin, process.stdout);
|
|
38
38
|
const documents = new node_1.TextDocuments(vscode_languageserver_textdocument_1.TextDocument);
|
|
39
39
|
connection.onInitialize(() => ({
|
|
40
40
|
capabilities: {
|
|
@@ -21,7 +21,7 @@ const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
|
21
21
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
22
22
|
const node_os_1 = __importDefault(require("node:os"));
|
|
23
23
|
const node_path_1 = __importDefault(require("node:path"));
|
|
24
|
-
exports.COMPILE_CACHE_SCHEMA =
|
|
24
|
+
exports.COMPILE_CACHE_SCHEMA = 2;
|
|
25
25
|
function compileCacheDir(projectRoot) {
|
|
26
26
|
return node_path_1.default.join(projectRoot, ".cluaupp", "compile-cache");
|
|
27
27
|
}
|
|
@@ -35,7 +35,7 @@ function indexPath(projectRoot) {
|
|
|
35
35
|
return node_path_1.default.join(compileCacheDir(projectRoot), "index.json");
|
|
36
36
|
}
|
|
37
37
|
function jobPath(projectRoot, rel) {
|
|
38
|
-
const safe = rel
|
|
38
|
+
const safe = hashText(rel);
|
|
39
39
|
return node_path_1.default.join(compileCacheDir(projectRoot), `${safe}.json`);
|
|
40
40
|
}
|
|
41
41
|
function loadCompileCacheIndex(projectRoot) {
|
|
@@ -45,7 +45,7 @@ function loadCompileCacheIndex(projectRoot) {
|
|
|
45
45
|
}
|
|
46
46
|
try {
|
|
47
47
|
const raw = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
|
|
48
|
-
if (!raw || typeof raw.entries !== "object") {
|
|
48
|
+
if (!raw || raw.schemaVersion !== exports.COMPILE_CACHE_SCHEMA || !raw.entries || typeof raw.entries !== "object" || Array.isArray(raw.entries)) {
|
|
49
49
|
return { schemaVersion: exports.COMPILE_CACHE_SCHEMA, entries: {} };
|
|
50
50
|
}
|
|
51
51
|
return { schemaVersion: exports.COMPILE_CACHE_SCHEMA, entries: raw.entries };
|
|
@@ -70,7 +70,7 @@ function readCachedJob(projectRoot, rel, sourceHash) {
|
|
|
70
70
|
}
|
|
71
71
|
try {
|
|
72
72
|
const job = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
|
|
73
|
-
if (!job || job.sourceHash !== sourceHash || !Array.isArray(job.files)) {
|
|
73
|
+
if (!job || job.rel !== rel || job.sourceHash !== sourceHash || !Array.isArray(job.files) || !job.files.every(f => typeof f.name === "string" && typeof f.contents === "string")) {
|
|
74
74
|
return null;
|
|
75
75
|
}
|
|
76
76
|
return job;
|
|
@@ -12,6 +12,7 @@ exports.writeDatamodelArtifacts = writeDatamodelArtifacts;
|
|
|
12
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
14
|
const datamodel_js_1 = require("./datamodel.js");
|
|
15
|
+
const paths_js_1 = require("../clpp/paths.js");
|
|
15
16
|
function safeIdent(name) {
|
|
16
17
|
const cleaned = name.replace(/[^A-Za-z0-9_]/g, "_");
|
|
17
18
|
return /^[A-Za-z_]/.test(cleaned) ? cleaned : `_${cleaned}`;
|
|
@@ -66,6 +67,17 @@ function writeDatamodelArtifacts(projectRoot, opts) {
|
|
|
66
67
|
node_fs_1.default.mkdirSync(outDir, { recursive: true });
|
|
67
68
|
const profilePath = node_path_1.default.join(outDir, "datamodel-profile.json");
|
|
68
69
|
node_fs_1.default.writeFileSync(profilePath, JSON.stringify(profileWithoutIndex(profile), null, "\t") + "\n", "utf8");
|
|
70
|
+
let sourceRoot = "src";
|
|
71
|
+
const configPath = node_path_1.default.join(projectRoot, "cluaupp.config.json");
|
|
72
|
+
if (node_fs_1.default.existsSync(configPath)) {
|
|
73
|
+
const config = JSON.parse(node_fs_1.default.readFileSync(configPath, "utf8"));
|
|
74
|
+
if (typeof config.rootDir === "string")
|
|
75
|
+
sourceRoot = config.rootDir;
|
|
76
|
+
}
|
|
77
|
+
const sources = (0, paths_js_1.collectSources)(node_path_1.default.resolve(projectRoot, sourceRoot));
|
|
78
|
+
const modern = sources.some(file => /\.clp$/i.test(file)) && !sources.some(file => /\.clpp$/i.test(file));
|
|
79
|
+
if (modern && !opts?.headerPath)
|
|
80
|
+
return { profile, profilePath, headerPath: null };
|
|
69
81
|
const headerPath = opts?.headerPath ||
|
|
70
82
|
node_path_1.default.join(projectRoot, "include", "clpp", "generated", "datamodel.clh");
|
|
71
83
|
node_fs_1.default.mkdirSync(node_path_1.default.dirname(headerPath), { recursive: true });
|
|
@@ -99,6 +99,21 @@ function buildRojoTree(root, rootDir, outDir) {
|
|
|
99
99
|
const sourceRoot = node_fs_1.default.existsSync(outRoot) ? outRoot : srcRoot;
|
|
100
100
|
const tree = baseTree();
|
|
101
101
|
const relRoot = node_path_1.default.relative(root, sourceRoot).replace(/\\/g, "/");
|
|
102
|
+
const projectSources = walkFiles(srcRoot);
|
|
103
|
+
const modernOnly = projectSources.some((file) => /\.clp$/i.test(file)) && !projectSources.some((file) => /\.(clpp|clh)$/i.test(file));
|
|
104
|
+
if (modernOnly) {
|
|
105
|
+
for (const service of ["ServerScriptService", "ServerStorage", "ReplicatedStorage", "ReplicatedFirst", "Workspace", "StarterGui", "StarterPack", "Lighting", "SoundService", "Teams"]) {
|
|
106
|
+
if (projectSources.some((file) => node_path_1.default.relative(srcRoot, file).replace(/\\/g, "/").startsWith(`${service}/`))) {
|
|
107
|
+
withPath(ensureNode(tree, [service]), `${outDir}/${service}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (const nested of ["StarterPlayerScripts", "StarterCharacterScripts"]) {
|
|
111
|
+
if (projectSources.some((file) => node_path_1.default.relative(srcRoot, file).replace(/\\/g, "/").startsWith(`StarterPlayer/${nested}/`))) {
|
|
112
|
+
withPath(ensureNode(tree, ["StarterPlayer", nested]), `${outDir}/StarterPlayer/${nested}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return tree;
|
|
116
|
+
}
|
|
102
117
|
withPath(ensureNode(tree, ["ServerScriptService"]), `${relRoot}/Server`);
|
|
103
118
|
withPath(ensureNode(tree, ["ServerScriptService", "Parallel"]), `${relRoot}/Parallel`);
|
|
104
119
|
withPath(ensureNode(tree, ["StarterPlayer", "StarterPlayerScripts"]), `${relRoot}/Client`);
|