cluaupp 0.2.3 → 1.0.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 (114) hide show
  1. package/CHANGELOG.md +10 -79
  2. package/README.md +42 -88
  3. package/docs/README.md +13 -21
  4. package/docs/architecture.md +13 -76
  5. package/docs/cli.md +12 -64
  6. package/docs/comparison.md +6 -24
  7. package/docs/config.md +6 -7
  8. package/docs/examples/combat.md +19 -227
  9. package/docs/examples/hud.md +13 -81
  10. package/docs/examples/index.md +9 -16
  11. package/docs/getting-started.md +20 -137
  12. package/docs/intellisense.md +5 -41
  13. package/docs/intro.md +16 -15
  14. package/docs/migration.md +38 -0
  15. package/docs/oop/file-tags.md +12 -36
  16. package/docs/oop/index.md +8 -14
  17. package/docs/syntax.md +54 -236
  18. package/editors/vscode/extension.js +1 -1
  19. package/editors/vscode/package.json +4 -4
  20. package/examples/README.md +5 -7
  21. package/examples/game/.vscode/extensions.json +0 -3
  22. package/examples/game/.vscode/settings.json +6 -14
  23. package/examples/game/src/client/hud.client.clpp +54 -0
  24. package/examples/game/src/client/init.client.clpp +6 -0
  25. package/examples/game/src/server/combat.server.clpp +85 -0
  26. package/examples/game/src/server/leaderstats.server.clpp +28 -0
  27. package/examples/game/src/shared/PlayerData.clh +20 -0
  28. package/examples/game/src/shared/config.clp +6 -0
  29. package/examples/game/src/shared/features.clp +88 -0
  30. package/generated/cli.js +40 -24
  31. package/generated/clpp/contract.js +5 -0
  32. package/generated/clpp/index.js +27 -0
  33. package/generated/clpp/paths.js +121 -0
  34. package/generated/clpp/postprocess.js +78 -0
  35. package/generated/clpp/runner.js +102 -0
  36. package/generated/compile.js +26 -138
  37. package/generated/intellisense.js +38 -157
  38. package/generated/libs.js +1 -1
  39. package/generated/lsp.js +1 -8
  40. package/generated/preprocess.js +8 -179
  41. package/generated/system-understander.js +1 -1
  42. package/generated/transpile.js +3 -50
  43. package/generated/utils/project.js +13 -28
  44. package/include/{cluaupp/datatypes.hpp → clpp/datatypes.clh} +1 -1
  45. package/include/{cluaupp/generated/instances.hpp → clpp/generated/instances.clh} +1 -1
  46. package/include/{cluaupp/libs/chrono.hpp → clpp/libs/chrono.clh} +9 -9
  47. package/include/{cluaupp/libs/cmdr.hpp → clpp/libs/cmdr.clh} +4 -4
  48. package/include/{cluaupp/libs/dataservice.hpp → clpp/libs/dataservice.clh} +8 -15
  49. package/include/{cluaupp/libs/display.hpp → clpp/libs/display.clh} +1 -2
  50. package/include/{cluaupp/libs/ezvisual.hpp → clpp/libs/ezvisual.clh} +1 -3
  51. package/include/{cluaupp/libs/formatnumber.hpp → clpp/libs/formatnumber.clh} +2 -3
  52. package/include/{cluaupp/libs/fusion.hpp → clpp/libs/fusion.clh} +5 -5
  53. package/include/{cluaupp/libs/iris.hpp → clpp/libs/iris.clh} +2 -2
  54. package/include/{cluaupp/libs/janitor.hpp → clpp/libs/janitor.clh} +1 -2
  55. package/include/{cluaupp/libs/module3d.hpp → clpp/libs/module3d.clh} +2 -4
  56. package/include/{cluaupp/libs/net.hpp → clpp/libs/net.clh} +2 -4
  57. package/include/{cluaupp/libs/promise.hpp → clpp/libs/promise.clh} +1 -4
  58. package/include/{cluaupp/libs/spring.hpp → clpp/libs/spring.clh} +1 -2
  59. package/include/{cluaupp/libs/statemachine.hpp → clpp/libs/statemachine.clh} +2 -3
  60. package/include/{cluaupp/libs/stickybillboard.hpp → clpp/libs/stickybillboard.clh} +1 -2
  61. package/include/{cluaupp/libs/topbarplus.hpp → clpp/libs/topbarplus.clh} +3 -4
  62. package/include/clpp/libs.clh +24 -0
  63. package/include/clpp/roblox.clh +31 -0
  64. package/package.json +7 -14
  65. package/src/cli.ts +39 -25
  66. package/src/clpp/contract.ts +39 -0
  67. package/src/clpp/index.ts +18 -0
  68. package/src/clpp/paths.ts +117 -0
  69. package/src/clpp/postprocess.ts +93 -0
  70. package/src/clpp/runner.ts +102 -0
  71. package/src/compile.ts +26 -149
  72. package/src/intellisense.ts +36 -165
  73. package/src/libs.ts +1 -1
  74. package/src/lsp.ts +1 -5
  75. package/src/preprocess.ts +8 -180
  76. package/src/system-understander.ts +1 -1
  77. package/src/transpile.ts +9 -52
  78. package/src/utils/project.ts +12 -28
  79. package/templates/game/.vscode/extensions.json +0 -3
  80. package/templates/game/.vscode/settings.json +6 -14
  81. package/templates/game/src/client/init.client.clpp +6 -0
  82. package/templates/game/src/server/leaderstats.server.clpp +29 -0
  83. package/templates/game/src/shared/config.clp +6 -0
  84. package/examples/game/.clangd +0 -25
  85. package/examples/game/compile_flags.txt +0 -6
  86. package/examples/game/src/client/hud.client.cpp +0 -12
  87. package/examples/game/src/client/init.client.cpp +0 -6
  88. package/examples/game/src/server/combat.server.cpp +0 -23
  89. package/examples/game/src/server/leaderstats.server.cpp +0 -29
  90. package/examples/game/src/shared/config.cpp +0 -5
  91. package/examples/game/src/shared/config.h +0 -5
  92. package/include/cluaupp/libs.hpp +0 -25
  93. package/include/cluaupp/roblox.hpp +0 -47
  94. package/src/architecture.ts +0 -500
  95. package/src/ast.ts +0 -37
  96. package/src/emit.ts +0 -609
  97. package/src/emitter/luau-codegen.ts +0 -187
  98. package/src/emitter/translators.ts +0 -168
  99. package/src/headers.ts +0 -233
  100. package/src/layout.ts +0 -114
  101. package/src/lex.ts +0 -158
  102. package/src/parse.ts +0 -729
  103. package/src/parser/collector.ts +0 -148
  104. package/src/parser/index.ts +0 -27
  105. package/src/tree-sitter-cpp.d.ts +0 -4
  106. package/src/understand.ts +0 -322
  107. package/templates/game/src/client/init.client.cpp +0 -6
  108. package/templates/game/src/server/leaderstats.server.cpp +0 -29
  109. package/templates/game/src/shared/config.cpp +0 -5
  110. package/templates/game/src/shared/config.h +0 -5
  111. /package/include/{cluaupp/generated/enums.hpp → clpp/generated/enums.clh} +0 -0
  112. /package/include/{cluaupp/libs/math.hpp → clpp/libs/math.clh} +0 -0
  113. /package/include/{cluaupp/libs/twinkle.hpp → clpp/libs/twinkle.clh} +0 -0
  114. /package/include/{cluaupp/libs/vfx.hpp → clpp/libs/vfx.clh} +0 -0
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasClpp = hasClpp;
4
+ exports.resolveClppBinary = resolveClppBinary;
5
+ exports.compileViaClpp = compileViaClpp;
6
+ exports.clppManifest = clppManifest;
7
+ exports.clppVersion = clppVersion;
8
+ const node_child_process_1 = require("node:child_process");
9
+ const contract_js_1 = require("./contract.js");
10
+ const MISSING_CLPP = `cluaupp: clpp not found. ${contract_js_1.CLPP_INSTALL_HINT}`;
11
+ function whichClpp() {
12
+ if (process.env.CLPP_PATH) {
13
+ return process.env.CLPP_PATH;
14
+ }
15
+ const finder = process.platform === "win32" ? "where" : "which";
16
+ const found = (0, node_child_process_1.spawnSync)(finder, ["clpp"], { encoding: "utf8", windowsHide: true });
17
+ if (found.status !== 0) {
18
+ return null;
19
+ }
20
+ const line = String(found.stdout || "")
21
+ .split(/\r?\n/)
22
+ .map((item) => item.trim())
23
+ .find((item) => item.length > 0);
24
+ return line || "clpp";
25
+ }
26
+ function hasClpp() {
27
+ return Boolean(whichClpp());
28
+ }
29
+ function resolveClppBinary() {
30
+ const bin = whichClpp();
31
+ if (!bin) {
32
+ throw new Error(MISSING_CLPP);
33
+ }
34
+ return bin;
35
+ }
36
+ function parseArtifact(stdout, fileName, fallbackError) {
37
+ const text = String(stdout || "").trim();
38
+ try {
39
+ const parsed = JSON.parse(text);
40
+ if (parsed && typeof parsed === "object") {
41
+ return parsed;
42
+ }
43
+ }
44
+ catch {
45
+ // fall through
46
+ }
47
+ return {
48
+ ok: false,
49
+ luau: "",
50
+ fileName,
51
+ outputHint: "",
52
+ scriptKind: null,
53
+ isScript: false,
54
+ isHeader: false,
55
+ rojoClass: "ModuleScript",
56
+ libraries: [],
57
+ error: fallbackError || "clpp returned invalid JSON",
58
+ };
59
+ }
60
+ function compileViaClpp(request) {
61
+ const bin = resolveClppBinary();
62
+ const payload = JSON.stringify({
63
+ source: request.source,
64
+ fileName: request.fileName,
65
+ strict: request.strict,
66
+ });
67
+ const result = (0, node_child_process_1.spawnSync)(bin, ["api", "compile"], {
68
+ input: payload,
69
+ encoding: "utf8",
70
+ cwd: request.cwd,
71
+ maxBuffer: 16 * 1024 * 1024,
72
+ windowsHide: true,
73
+ });
74
+ const stderr = String(result.stderr || "").trim();
75
+ const artifact = parseArtifact(result.stdout, request.fileName, stderr || result.error?.message || "clpp api compile failed");
76
+ if (!artifact.ok) {
77
+ throw new Error(artifact.error || stderr || `clpp failed (${result.status})`);
78
+ }
79
+ return artifact;
80
+ }
81
+ function clppManifest() {
82
+ const bin = resolveClppBinary();
83
+ const result = (0, node_child_process_1.spawnSync)(bin, ["api", "manifest"], {
84
+ encoding: "utf8",
85
+ windowsHide: true,
86
+ });
87
+ if (result.status !== 0) {
88
+ throw new Error(String(result.stderr || result.error?.message || "clpp api manifest failed"));
89
+ }
90
+ return JSON.parse(result.stdout);
91
+ }
92
+ function clppVersion() {
93
+ const bin = whichClpp();
94
+ if (!bin) {
95
+ return null;
96
+ }
97
+ const result = (0, node_child_process_1.spawnSync)(bin, ["--version"], { encoding: "utf8", windowsHide: true });
98
+ if (result.status !== 0) {
99
+ return null;
100
+ }
101
+ return String(result.stdout || "").trim() || null;
102
+ }
@@ -5,149 +5,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.compileSource = compileSource;
7
7
  exports.compileService = compileService;
8
- const node_fs_1 = __importDefault(require("node:fs"));
9
8
  const node_path_1 = __importDefault(require("node:path"));
10
- const parse_js_1 = require("./parse.js");
11
- const emit_js_1 = require("./emit.js");
12
- const preprocess_js_1 = require("./preprocess.js");
13
- const libs_js_1 = require("./libs.js");
14
- const architecture_js_1 = require("./architecture.js");
15
- const headers_js_1 = require("./headers.js");
16
- function shouldAttachRequires(name, contents) {
17
- const file = String(name || "").replace(/\\/g, "/");
18
- if (/\.json$/i.test(file) || /\.meta\.json$/i.test(file)) {
19
- return false;
20
- }
21
- const trimmed = String(contents || "").trim();
22
- if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
23
- return false;
24
- }
25
- return true;
26
- }
27
- function attachRequires(contents, source, ast, options, outName) {
28
- if (!shouldAttachRequires(outName, contents)) {
29
- return contents;
30
- }
31
- const libraries = String(contents).includes("CluauppLibs") ? [] : (0, libs_js_1.collectLibraries)(source, ast);
32
- return (0, libs_js_1.insertPreamble)(contents, options.moduleIncludes || [], libraries, outName);
33
- }
34
- function posixRel(from, file) {
35
- return node_path_1.default.relative(from, file).replace(/\\/g, "/");
36
- }
37
- function declKey(decl) {
38
- return `${decl.owner || ""}::${decl.name}`;
39
- }
40
- function mergeSiblingImpl(ast, implPath, options) {
41
- const implOptions = {
42
- ...options,
43
- moduleIncludes: [],
44
- seen: new Set(),
45
- pragmaResolved: false,
46
- };
47
- const prepared = (0, preprocess_js_1.preprocess)(node_fs_1.default.readFileSync(implPath, "utf8"), implPath, implOptions);
48
- const implAst = (0, parse_js_1.parse)(prepared, node_path_1.default.basename(implPath));
49
- if (!Array.isArray(ast.body)) {
50
- ast.body = [];
51
- }
52
- const existing = new Set((ast.body || [])
53
- .filter((decl) => decl && (decl.type === "function" || decl.type === "proto") && decl.name)
54
- .map(declKey));
55
- for (const decl of implAst.body || []) {
56
- if ((decl.type !== "function" && decl.type !== "proto") || !decl.name) {
57
- continue;
58
- }
59
- const key = declKey(decl);
60
- if (existing.has(key)) {
61
- continue;
62
- }
63
- existing.add(key);
64
- ast.body.push({
65
- type: "proto",
66
- name: decl.name,
67
- owner: decl.owner,
68
- returnType: decl.returnType,
69
- params: decl.params,
70
- });
71
- }
72
- }
73
- function wireHeaderImpl(ast, fileName, options) {
74
- const headerPath = options.filePath || null;
75
- const impl = headerPath ? (0, preprocess_js_1.siblingImplementation)(headerPath) : null;
76
- if (!impl) {
77
- return;
78
- }
79
- mergeSiblingImpl(ast, impl, options);
80
- const typeName = (0, headers_js_1.primaryHeaderName)(ast, options.relativeName || fileName);
81
- const implRel = options.srcDir ? posixRel(options.srcDir, impl) : node_path_1.default.basename(impl).replace(/\\/g, "/");
82
- const implOut = (0, preprocess_js_1.implOutName)(implRel);
83
- options.headerImplName = `${typeName}Module`;
84
- options.moduleIncludes = options.moduleIncludes || [];
85
- if (!options.moduleIncludes.some((spec) => spec.name === options.headerImplName)) {
86
- options.moduleIncludes.push({
87
- name: options.headerImplName,
88
- outRel: implOut,
89
- exports: { consts: [], structs: [] },
90
- });
91
- }
92
- }
93
- function compileHeader(source, fileName, options, ast) {
94
- wireHeaderImpl(ast, fileName, options);
95
- const rel = (options.relativeName || fileName || "header.h").replace(/\\/g, "/");
96
- const outName = (0, preprocess_js_1.toLuauPath)(rel);
97
- const luau = attachRequires((0, headers_js_1.emitHeaderModule)(ast, options), source, ast, options, outName);
98
- return {
99
- kind: "module",
100
- plan: { kind: "module", strict: options.strict === true },
101
- files: [{ name: outName, contents: luau }],
102
- stale: [],
103
- };
104
- }
9
+ const runner_js_1 = require("./clpp/runner.js");
10
+ const postprocess_js_1 = require("./clpp/postprocess.js");
11
+ const paths_js_1 = require("./clpp/paths.js");
105
12
  function compileSource(source, fileName, options = {}) {
106
- const opts = options;
107
- opts.moduleIncludes = opts.moduleIncludes || [];
108
- const prepared = (0, preprocess_js_1.preprocess)(source, opts.filePath || null, opts);
109
- const ast = (0, parse_js_1.parse)(prepared, fileName || "input.cpp");
110
- if ((0, preprocess_js_1.isHeaderFile)(fileName || "") || (0, preprocess_js_1.isHeaderFile)(opts.filePath || "")) {
111
- return compileHeader(source, fileName || "header.h", opts, ast).files[0].contents;
112
- }
113
- const luau = (0, emit_js_1.emit)(ast, opts);
114
- return attachRequires(luau, source, ast, opts, opts.outName || fileName || "input.cpp");
13
+ return compileService(source, fileName, options).files[0]?.contents ?? "";
115
14
  }
116
15
  function compileService(source, fileName, options = {}) {
117
- const opts = options;
118
- opts.moduleIncludes = opts.moduleIncludes || [];
119
- const prepared = (0, preprocess_js_1.preprocess)(source, opts.filePath || null, opts);
120
- const ast = (0, parse_js_1.parse)(prepared, fileName || "input.cpp");
121
- if ((0, preprocess_js_1.isHeaderFile)(fileName || "") || (0, preprocess_js_1.isHeaderFile)(opts.filePath || "") || (0, preprocess_js_1.isHeaderFile)(opts.relativeName || "")) {
122
- return compileHeader(source, fileName || "header.h", opts, ast);
123
- }
124
- const implHeader = opts.filePath ? (0, preprocess_js_1.siblingHeader)(opts.filePath) : null;
125
- if (implHeader) {
126
- opts.skipInit = true;
127
- }
128
- const planned = (0, architecture_js_1.planOutput)(ast, fileName || "input.cpp", {
129
- ...opts,
130
- relativeName: opts.relativeName || fileName,
131
- source: prepared,
132
- siblingHeader: implHeader,
16
+ const relative = (options.relativeName || fileName || "input.clpp").replace(/\\/g, "/");
17
+ const outName = options.outName || (0, paths_js_1.toLuauPath)(relative);
18
+ const header = options.filePath ? (0, paths_js_1.siblingHeader)(options.filePath) : null;
19
+ const skipInit = options.skipInit === true || (0, postprocess_js_1.shouldSkipInit)(relative, Boolean(header));
20
+ const diskPath = options.filePath ? node_path_1.default.resolve(options.filePath) : null;
21
+ const artifact = (0, runner_js_1.compileViaClpp)({
22
+ source,
23
+ fileName: diskPath ? diskPath.replace(/\\/g, "/") : relative,
24
+ strict: options.strict,
25
+ cwd: diskPath ? node_path_1.default.dirname(diskPath) : options.srcDir,
26
+ });
27
+ const luau = (0, postprocess_js_1.clppLuauToGame)(artifact, {
28
+ relativeName: relative,
29
+ outName,
30
+ srcDir: options.srcDir,
31
+ rootDir: options.rootDir,
32
+ strict: options.strict,
33
+ skipInit,
133
34
  });
134
- if (planned.files) {
135
- return {
136
- ...planned,
137
- files: planned.files.map((file) => ({
138
- ...file,
139
- contents: attachRequires(file.contents, source, ast, opts, file.name),
140
- })),
141
- };
142
- }
143
- const luau = attachRequires((0, emit_js_1.emit)(ast, opts), source, ast, opts, planned.outName || opts.outName || fileName || "input.cpp");
144
- const name = planned.outName ||
145
- opts.outName ||
146
- String(fileName || "input.cpp").replace(/\.(cpp|cc|cxx|c|h|hpp|hh)$/i, ".luau");
147
35
  return {
148
- kind: planned.kind || "flat",
149
- plan: planned.plan,
150
- files: [{ name, contents: luau }],
151
- stale: planned.stale || [],
36
+ kind: (0, paths_js_1.emitKind)(relative),
37
+ plan: { kind: (0, paths_js_1.emitKind)(relative), strict: options.strict === true },
38
+ files: [{ name: outName, contents: luau }],
39
+ stale: [],
152
40
  };
153
41
  }
@@ -3,9 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.clangPath = clangPath;
7
- exports.writeCompileCommands = writeCompileCommands;
8
- exports.writeClangd = writeClangd;
6
+ exports.isClppSource = void 0;
9
7
  exports.diagnosticsFor = diagnosticsFor;
10
8
  exports.syncEditorSupport = syncEditorSupport;
11
9
  exports.installEditorExtension = installEditorExtension;
@@ -13,57 +11,11 @@ exports.installEditorSupport = installEditorSupport;
13
11
  const node_fs_1 = __importDefault(require("node:fs"));
14
12
  const node_os_1 = __importDefault(require("node:os"));
15
13
  const node_path_1 = __importDefault(require("node:path"));
16
- const parse_js_1 = require("./parse.js");
17
- const preprocess_js_1 = require("./preprocess.js");
18
- const editor_install_js_1 = require("./editor-install.js");
14
+ const node_child_process_1 = require("node:child_process");
19
15
  const package_info_js_1 = require("./package-info.js");
20
- function posix(file) {
21
- return String(file).replace(/\\/g, "/");
22
- }
23
- function collectFiles(dir, files = []) {
24
- if (!node_fs_1.default.existsSync(dir)) {
25
- return files;
26
- }
27
- for (const entry of node_fs_1.default.readdirSync(dir, { withFileTypes: true })) {
28
- const full = node_path_1.default.join(dir, entry.name);
29
- if (entry.isDirectory()) {
30
- collectFiles(full, files);
31
- }
32
- else {
33
- files.push(full);
34
- }
35
- }
36
- return files;
37
- }
38
- function isCppFile(file) {
39
- return /\.(cpp|cc|cxx|c|h|hpp|hh)$/i.test(file);
40
- }
41
- function clangCompileArgs(root) {
42
- const absRoot = posix(node_path_1.default.resolve(root));
43
- const absInclude = posix(node_path_1.default.join(absRoot, "include"));
44
- const absSrc = posix(node_path_1.default.join(absRoot, "src"));
45
- const roblox = posix(node_path_1.default.join(absInclude, "cluaupp", "roblox.hpp"));
46
- return [
47
- "-xc++",
48
- "-std=c++20",
49
- "-ferror-limit=0",
50
- "-I" + absInclude,
51
- "-I" + absSrc,
52
- "-Iinclude",
53
- "-Isrc",
54
- "-include",
55
- roblox,
56
- ];
57
- }
58
- function compileCommandEntry(root, file) {
59
- const absRoot = posix(node_path_1.default.resolve(root));
60
- const absFile = posix(node_path_1.default.resolve(file));
61
- return {
62
- directory: absRoot,
63
- file: absFile,
64
- arguments: [clangPath(), ...clangCompileArgs(root), "-c", absFile],
65
- };
66
- }
16
+ const contract_js_1 = require("./clpp/contract.js");
17
+ const runner_js_1 = require("./clpp/runner.js");
18
+ const paths_js_1 = require("./clpp/paths.js");
67
19
  function copyDir(from, to) {
68
20
  node_fs_1.default.mkdirSync(to, { recursive: true });
69
21
  for (const entry of node_fs_1.default.readdirSync(from, { withFileTypes: true })) {
@@ -93,16 +45,6 @@ function uniqueStrings(...lists) {
93
45
  }
94
46
  return out;
95
47
  }
96
- function stripCppToolsSettings(current) {
97
- const next = {};
98
- for (const [key, value] of Object.entries(current)) {
99
- if (key === "C_Cpp" || key.startsWith("C_Cpp.")) {
100
- continue;
101
- }
102
- next[key] = value;
103
- }
104
- return next;
105
- }
106
48
  function readJsonObject(file) {
107
49
  if (!node_fs_1.default.existsSync(file)) {
108
50
  return {};
@@ -114,7 +56,7 @@ function readJsonObject(file) {
114
56
  }
115
57
  }
116
58
  catch {
117
- // ignore corrupt editor json
59
+ // ignore
118
60
  }
119
61
  return {};
120
62
  }
@@ -126,58 +68,6 @@ function writeJson(file, value) {
126
68
  }
127
69
  node_fs_1.default.writeFileSync(file, json, "utf8");
128
70
  }
129
- function clangdEditorArgs() {
130
- return [
131
- "--compile-commands-dir=${workspaceFolder}",
132
- "--header-insertion=never",
133
- "--query-driver=**/clang++*,**/clang++.exe,**/g++*,**/g++.exe",
134
- ];
135
- }
136
- function clangPath() {
137
- return (0, editor_install_js_1.findClangPlusPlus)() || "clang++";
138
- }
139
- function writeCompileCommands(root, srcDir) {
140
- const files = collectFiles(srcDir).filter((file) => isCppFile(file)).sort();
141
- const json = `${JSON.stringify(files.map((file) => compileCommandEntry(root, file)), null, "\t")}\n`;
142
- const dest = node_path_1.default.join(root, "compile_commands.json");
143
- if (node_fs_1.default.existsSync(dest) && node_fs_1.default.readFileSync(dest, "utf8") === json) {
144
- return false;
145
- }
146
- node_fs_1.default.writeFileSync(dest, json, "utf8");
147
- return true;
148
- }
149
- function writeClangd(root) {
150
- const flags = clangCompileArgs(root)
151
- .map((flag) => ` - ${flag}`)
152
- .join("\n");
153
- const contents = `CompileFlags:
154
- CompilationDatabase: .
155
- Add:
156
- ${flags}
157
-
158
- Diagnostics:
159
- Suppress: '*'
160
-
161
- ---
162
- If:
163
- PathMatch: .*\\.(cpp|cc|cxx|c|h|hpp|hh)$
164
- CompileFlags:
165
- Add:
166
- - -xc++
167
-
168
- ---
169
- If:
170
- PathMatch: (out|libs)/.*
171
- Index:
172
- Background: Skip
173
- `;
174
- const dest = node_path_1.default.join(root, ".clangd");
175
- if (node_fs_1.default.existsSync(dest) && node_fs_1.default.readFileSync(dest, "utf8") === contents) {
176
- return false;
177
- }
178
- node_fs_1.default.writeFileSync(dest, contents, "utf8");
179
- return true;
180
- }
181
71
  function writeVscode(root) {
182
72
  const settingsPath = node_path_1.default.join(root, ".vscode", "settings.json");
183
73
  const current = readJsonObject(settingsPath);
@@ -185,61 +75,44 @@ function writeVscode(root) {
185
75
  ...((current["files.associations"] && typeof current["files.associations"] === "object" && !Array.isArray(current["files.associations"]))
186
76
  ? current["files.associations"]
187
77
  : {}),
188
- "*.hpp": "cpp",
189
- "*.h": "cpp",
190
- "*.server.cpp": "cpp",
191
- "*.client.cpp": "cpp",
192
- "*.plugin.cpp": "cpp",
193
- "*.legacy.cpp": "cpp",
194
- "*.legacy.server.cpp": "cpp",
195
- "*.legacy.client.cpp": "cpp",
78
+ "*.clpp": "clpp",
79
+ "*.clp": "clpp",
80
+ "*.clh": "clpp",
81
+ "*.server.clpp": "clpp",
82
+ "*.client.clpp": "clpp",
83
+ "*.plugin.clpp": "clpp",
196
84
  };
197
85
  writeJson(settingsPath, {
198
- ...stripCppToolsSettings(current),
199
- "clangd.enable": true,
200
- "clangd.arguments": clangdEditorArgs(),
86
+ ...current,
201
87
  "files.associations": associations,
202
88
  });
203
89
  const extensionsPath = node_path_1.default.join(root, ".vscode", "extensions.json");
204
90
  const extensions = readJsonObject(extensionsPath);
205
91
  writeJson(extensionsPath, {
206
92
  ...extensions,
207
- recommendations: uniqueStrings(extensions.recommendations, ["llvm-vs-code-extensions.vscode-clangd"]),
93
+ recommendations: uniqueStrings(extensions.recommendations),
208
94
  unwantedRecommendations: uniqueStrings(extensions.unwantedRecommendations, ["ms-vscode.cpptools"]),
209
95
  });
210
- const props = node_path_1.default.join(root, ".vscode", "c_cpp_properties.json");
211
- if (node_fs_1.default.existsSync(props)) {
212
- node_fs_1.default.unlinkSync(props);
213
- }
214
96
  }
215
- function diagnosticsFor(source, fileName, options = {}) {
97
+ function diagnosticsFor(source, fileName) {
98
+ if (!(0, runner_js_1.hasClpp)()) {
99
+ return [];
100
+ }
216
101
  try {
217
- const prepared = options.filePath ? (0, preprocess_js_1.preprocess)(source, options.filePath, options) : source;
218
- (0, parse_js_1.parse)(prepared, fileName || "input.cpp");
102
+ (0, runner_js_1.compileViaClpp)({ source, fileName: fileName || "input.clpp" });
219
103
  return [];
220
104
  }
221
105
  catch (err) {
222
- const error = err;
223
- const message = error.message ? String(error.message) : "parse error";
106
+ const message = err instanceof Error ? err.message : String(err);
224
107
  const match = message.match(/:(\d+):(\d+):\s*(.*)$/);
225
108
  if (match) {
226
109
  return [{ line: Number(match[1]), col: Number(match[2]), message: match[3], severity: "error" }];
227
110
  }
228
- return [{ line: error.line || 1, col: error.col || 1, message, severity: "error" }];
111
+ return [{ line: 1, col: 1, message, severity: "error" }];
229
112
  }
230
113
  }
231
- function syncEditorSupport(root, config = {}) {
232
- const srcDir = node_path_1.default.join(root, config.rootDir || "src");
233
- if (node_fs_1.default.existsSync(srcDir)) {
234
- writeCompileCommands(root, srcDir);
235
- }
236
- writeClangd(root);
114
+ function syncEditorSupport(root, _config = {}) {
237
115
  writeVscode(root);
238
- const flags = ["-xc++", "-std=c++20", "-ferror-limit=0", "-Iinclude", "-Isrc", "-include", "include/cluaupp/roblox.hpp"].join("\n") + "\n";
239
- const flagsFile = node_path_1.default.join(root, "compile_flags.txt");
240
- if (!node_fs_1.default.existsSync(flagsFile) || node_fs_1.default.readFileSync(flagsFile, "utf8") !== flags) {
241
- node_fs_1.default.writeFileSync(flagsFile, flags, "utf8");
242
- }
243
116
  }
244
117
  function installEditorExtension(cluauppRoot = package_info_js_1.projectRoot) {
245
118
  const from = node_path_1.default.join(cluauppRoot, "editors", "vscode");
@@ -261,12 +134,20 @@ function installEditorExtension(cluauppRoot = package_info_js_1.projectRoot) {
261
134
  }
262
135
  return installed;
263
136
  }
264
- async function installEditorSupport(cluauppRoot = package_info_js_1.projectRoot) {
265
- const local = installEditorExtension(cluauppRoot);
266
- const llvm = (0, editor_install_js_1.ensureLlvm)();
267
- (0, editor_install_js_1.reportInstall)(llvm, "LLVM clang++");
268
- const clangd = await (0, editor_install_js_1.installMarketplaceExtension)(editor_install_js_1.CLANGD_ID, "clangd (LLVM)");
269
- (0, editor_install_js_1.reportInstall)(clangd, "clangd");
270
- console.log("cluaupp: C++ completion is clangd — reload the editor (Ctrl+Shift+P → Developer: Reload Window)");
271
- return { local, llvm, clangd };
137
+ async function installEditorSupport() {
138
+ const local = installEditorExtension();
139
+ if ((0, runner_js_1.hasClpp)()) {
140
+ const result = (0, node_child_process_1.spawnSync)("clpp", ["install"], { encoding: "utf8", windowsHide: true });
141
+ if (result.status === 0) {
142
+ console.log(String(result.stderr || result.stdout || "clpp install ok").trim());
143
+ }
144
+ else {
145
+ console.log("cluaupp:", contract_js_1.CLPP_INSTALL_HINT);
146
+ }
147
+ }
148
+ else {
149
+ console.log("cluaupp:", contract_js_1.CLPP_INSTALL_HINT);
150
+ }
151
+ return { local };
272
152
  }
153
+ exports.isClppSource = paths_js_1.isSourceFile;
package/generated/libs.js CHANGED
@@ -259,7 +259,7 @@ function walk(node, visit) {
259
259
  function modulesFromIncludes(source) {
260
260
  const found = new Set();
261
261
  for (const line of String(source).split(/\r?\n/)) {
262
- const match = line.match(/^\s*#\s*include\s+<cluaupp\/(?:libs\/)?([A-Za-z0-9]+)\.hpp>/);
262
+ const match = line.match(/^\s*#\s*include\s+<(?:clpp|cluaupp)\/(?:libs\/)?([A-Za-z0-9]+)\.(?:clh|hpp)>/);
263
263
  if (!match) {
264
264
  continue;
265
265
  }
package/generated/lsp.js CHANGED
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.start = start;
7
- const node_path_1 = __importDefault(require("node:path"));
8
4
  const node_1 = require("vscode-languageserver/node");
9
5
  const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
10
6
  const intellisense_js_1 = require("./intellisense.js");
@@ -28,10 +24,7 @@ function start(options = {}) {
28
24
  }));
29
25
  const publish = (document) => {
30
26
  const file = uriPath(document.uri);
31
- const items = (0, intellisense_js_1.diagnosticsFor)(document.getText(), file, {
32
- filePath: file,
33
- includeDirs: [node_path_1.default.dirname(file), node_path_1.default.join(projectRoot, "src"), node_path_1.default.join(projectRoot, "include")],
34
- });
27
+ const items = (0, intellisense_js_1.diagnosticsFor)(document.getText(), file);
35
28
  connection.sendDiagnostics({
36
29
  uri: document.uri,
37
30
  diagnostics: items.map((item) => ({