cluaupp 0.2.1 → 0.2.3
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 +12 -0
- package/README.md +1 -1
- package/docs/README.md +32 -20
- package/docs/cli.md +1 -1
- package/docs/cpp-advanced.md +6 -3
- package/docs/cpp-types.md +2 -0
- package/docs/examples/hud.md +1 -1
- package/docs/examples/index.md +1 -1
- package/docs/examples/leaderstats.md +44 -115
- package/docs/getting-started.md +4 -2
- package/docs/intellisense.md +4 -5
- package/docs/libraries/dataservice.md +4 -1
- package/docs/libraries/index.md +2 -1
- package/docs/libraries/more.md +3 -1
- package/docs/libraries/ui.md +76 -0
- package/docs/oop/index.md +20 -7
- package/docs/roblox-api.md +4 -56
- package/docs/syntax.md +112 -55
- package/editors/vscode/package.json +25 -25
- package/examples/game/.vscode/extensions.json +3 -0
- package/examples/game/.vscode/settings.json +0 -9
- package/examples/game/src/shared/config.h +2 -0
- package/generated/api.js +15 -1
- package/generated/compile.js +38 -0
- package/generated/emit.js +79 -3
- package/generated/intellisense.js +75 -80
- package/generated/lex.js +3 -0
- package/generated/parse.js +119 -24
- package/generated/parser/collector.js +37 -1
- package/generated/utils/rojo-mapper.js +23 -3
- package/include/cluaupp/datatypes.hpp +4 -0
- package/package.json +98 -87
- package/src/api.ts +15 -1
- package/src/compile.ts +43 -1
- package/src/emit.ts +81 -3
- package/src/intellisense.ts +80 -80
- package/src/lex.ts +3 -0
- package/src/parse.ts +124 -25
- package/src/parser/collector.ts +35 -2
- package/src/utils/rojo-mapper.ts +26 -3
- package/templates/game/.vscode/extensions.json +3 -0
- package/templates/game/.vscode/settings.json +0 -9
- package/templates/game/src/shared/config.h +2 -0
- package/examples/game/.vscode/c_cpp_properties.json +0 -27
- package/templates/game/.vscode/c_cpp_properties.json +0 -27
|
@@ -3,7 +3,6 @@ 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.intelliSenseMode = intelliSenseMode;
|
|
7
6
|
exports.clangPath = clangPath;
|
|
8
7
|
exports.writeCompileCommands = writeCompileCommands;
|
|
9
8
|
exports.writeClangd = writeClangd;
|
|
@@ -65,32 +64,6 @@ function compileCommandEntry(root, file) {
|
|
|
65
64
|
arguments: [clangPath(), ...clangCompileArgs(root), "-c", absFile],
|
|
66
65
|
};
|
|
67
66
|
}
|
|
68
|
-
function mergeJson(file, patch) {
|
|
69
|
-
let current = {};
|
|
70
|
-
if (node_fs_1.default.existsSync(file)) {
|
|
71
|
-
try {
|
|
72
|
-
current = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
current = {};
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
const next = { ...current, ...patch };
|
|
79
|
-
for (const key of Object.keys(patch)) {
|
|
80
|
-
const value = patch[key];
|
|
81
|
-
const existing = current[key];
|
|
82
|
-
if (value && typeof value === "object" && !Array.isArray(value) && existing && typeof existing === "object" && !Array.isArray(existing)) {
|
|
83
|
-
next[key] = { ...existing, ...value };
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const json = `${JSON.stringify(next, null, "\t")}\n`;
|
|
87
|
-
if (node_fs_1.default.existsSync(file) && node_fs_1.default.readFileSync(file, "utf8") === json) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
node_fs_1.default.mkdirSync(node_path_1.default.dirname(file), { recursive: true });
|
|
91
|
-
node_fs_1.default.writeFileSync(file, json, "utf8");
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
67
|
function copyDir(from, to) {
|
|
95
68
|
node_fs_1.default.mkdirSync(to, { recursive: true });
|
|
96
69
|
for (const entry of node_fs_1.default.readdirSync(from, { withFileTypes: true })) {
|
|
@@ -104,6 +77,55 @@ function copyDir(from, to) {
|
|
|
104
77
|
}
|
|
105
78
|
}
|
|
106
79
|
}
|
|
80
|
+
function uniqueStrings(...lists) {
|
|
81
|
+
const seen = new Set();
|
|
82
|
+
const out = [];
|
|
83
|
+
for (const list of lists) {
|
|
84
|
+
if (!Array.isArray(list)) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
for (const item of list) {
|
|
88
|
+
if (typeof item === "string" && item && !seen.has(item)) {
|
|
89
|
+
seen.add(item);
|
|
90
|
+
out.push(item);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
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
|
+
function readJsonObject(file) {
|
|
107
|
+
if (!node_fs_1.default.existsSync(file)) {
|
|
108
|
+
return {};
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const parsed = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
|
|
112
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
113
|
+
return parsed;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// ignore corrupt editor json
|
|
118
|
+
}
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
function writeJson(file, value) {
|
|
122
|
+
const json = `${JSON.stringify(value, null, "\t")}\n`;
|
|
123
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(file), { recursive: true });
|
|
124
|
+
if (node_fs_1.default.existsSync(file) && node_fs_1.default.readFileSync(file, "utf8") === json) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
node_fs_1.default.writeFileSync(file, json, "utf8");
|
|
128
|
+
}
|
|
107
129
|
function clangdEditorArgs() {
|
|
108
130
|
return [
|
|
109
131
|
"--compile-commands-dir=${workspaceFolder}",
|
|
@@ -111,16 +133,6 @@ function clangdEditorArgs() {
|
|
|
111
133
|
"--query-driver=**/clang++*,**/clang++.exe,**/g++*,**/g++.exe",
|
|
112
134
|
];
|
|
113
135
|
}
|
|
114
|
-
function intelliSenseMode() {
|
|
115
|
-
const arch = process.arch === "arm64" ? "arm64" : "x64";
|
|
116
|
-
if (process.platform === "win32") {
|
|
117
|
-
return `windows-clang-${arch}`;
|
|
118
|
-
}
|
|
119
|
-
if (process.platform === "darwin") {
|
|
120
|
-
return `macos-clang-${arch}`;
|
|
121
|
-
}
|
|
122
|
-
return `linux-clang-${arch}`;
|
|
123
|
-
}
|
|
124
136
|
function clangPath() {
|
|
125
137
|
return (0, editor_install_js_1.findClangPlusPlus)() || "clang++";
|
|
126
138
|
}
|
|
@@ -167,54 +179,37 @@ Index:
|
|
|
167
179
|
return true;
|
|
168
180
|
}
|
|
169
181
|
function writeVscode(root) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
"
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"
|
|
177
|
-
"
|
|
182
|
+
const settingsPath = node_path_1.default.join(root, ".vscode", "settings.json");
|
|
183
|
+
const current = readJsonObject(settingsPath);
|
|
184
|
+
const associations = {
|
|
185
|
+
...((current["files.associations"] && typeof current["files.associations"] === "object" && !Array.isArray(current["files.associations"]))
|
|
186
|
+
? current["files.associations"]
|
|
187
|
+
: {}),
|
|
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",
|
|
196
|
+
};
|
|
197
|
+
writeJson(settingsPath, {
|
|
198
|
+
...stripCppToolsSettings(current),
|
|
178
199
|
"clangd.enable": true,
|
|
179
200
|
"clangd.arguments": clangdEditorArgs(),
|
|
180
|
-
"files.associations":
|
|
181
|
-
"*.hpp": "cpp",
|
|
182
|
-
"*.h": "cpp",
|
|
183
|
-
"*.server.cpp": "cpp",
|
|
184
|
-
"*.client.cpp": "cpp",
|
|
185
|
-
"*.plugin.cpp": "cpp",
|
|
186
|
-
"*.legacy.cpp": "cpp",
|
|
187
|
-
"*.legacy.server.cpp": "cpp",
|
|
188
|
-
"*.legacy.client.cpp": "cpp",
|
|
189
|
-
},
|
|
201
|
+
"files.associations": associations,
|
|
190
202
|
});
|
|
191
|
-
|
|
192
|
-
|
|
203
|
+
const extensionsPath = node_path_1.default.join(root, ".vscode", "extensions.json");
|
|
204
|
+
const extensions = readJsonObject(extensionsPath);
|
|
205
|
+
writeJson(extensionsPath, {
|
|
206
|
+
...extensions,
|
|
207
|
+
recommendations: uniqueStrings(extensions.recommendations, ["llvm-vs-code-extensions.vscode-clangd"]),
|
|
208
|
+
unwantedRecommendations: uniqueStrings(extensions.unwantedRecommendations, ["ms-vscode.cpptools"]),
|
|
193
209
|
});
|
|
194
210
|
const props = node_path_1.default.join(root, ".vscode", "c_cpp_properties.json");
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
{
|
|
198
|
-
name: "Cluaupp",
|
|
199
|
-
compilerPath: clangPath(),
|
|
200
|
-
cStandard: "c17",
|
|
201
|
-
cppStandard: "c++20",
|
|
202
|
-
intelliSenseMode: intelliSenseMode(),
|
|
203
|
-
includePath: ["${workspaceFolder}/include", "${workspaceFolder}/src"],
|
|
204
|
-
forcedInclude: ["${workspaceFolder}/include/cluaupp/roblox.hpp"],
|
|
205
|
-
compileCommands: "${workspaceFolder}/compile_commands.json",
|
|
206
|
-
browse: {
|
|
207
|
-
path: ["${workspaceFolder}/include", "${workspaceFolder}/src"],
|
|
208
|
-
limitSymbolsToIncludedHeaders: true,
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
],
|
|
212
|
-
version: 4,
|
|
213
|
-
};
|
|
214
|
-
const json = `${JSON.stringify(nextProps, null, "\t")}\n`;
|
|
215
|
-
node_fs_1.default.mkdirSync(node_path_1.default.dirname(props), { recursive: true });
|
|
216
|
-
if (!node_fs_1.default.existsSync(props) || node_fs_1.default.readFileSync(props, "utf8") !== json) {
|
|
217
|
-
node_fs_1.default.writeFileSync(props, json, "utf8");
|
|
211
|
+
if (node_fs_1.default.existsSync(props)) {
|
|
212
|
+
node_fs_1.default.unlinkSync(props);
|
|
218
213
|
}
|
|
219
214
|
}
|
|
220
215
|
function diagnosticsFor(source, fileName, options = {}) {
|
package/generated/lex.js
CHANGED
package/generated/parse.js
CHANGED
|
@@ -46,21 +46,124 @@ function parse(source, fileName) {
|
|
|
46
46
|
eat("op", ">");
|
|
47
47
|
return name;
|
|
48
48
|
};
|
|
49
|
+
const CAST_NAMES = new Set(["static_cast", "const_cast", "reinterpret_cast", "dynamic_cast"]);
|
|
50
|
+
function skipSpecifiers() {
|
|
51
|
+
let isConst = false;
|
|
52
|
+
while (at("kw", "static") || at("kw", "inline") || at("kw", "constexpr") || at("kw", "const")) {
|
|
53
|
+
if (at("kw", "constexpr") || at("kw", "const")) {
|
|
54
|
+
isConst = true;
|
|
55
|
+
}
|
|
56
|
+
i += 1;
|
|
57
|
+
}
|
|
58
|
+
return isConst;
|
|
59
|
+
}
|
|
60
|
+
function looksLikePrimaryStart() {
|
|
61
|
+
if (at("ident") || at("number") || at("string")) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (at("kw", "true") || at("kw", "false") || at("kw", "nullptr") || at("kw", "new")) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return at("op", "(") || at("op", "{") || at("op", "[") || at("op", "-") || at("op", "!");
|
|
68
|
+
}
|
|
69
|
+
function parseLambda() {
|
|
70
|
+
eat("op", "[");
|
|
71
|
+
while (!at("eof") && !at("op", "]")) {
|
|
72
|
+
i += 1;
|
|
73
|
+
}
|
|
74
|
+
eat("op", "]");
|
|
75
|
+
const params = [];
|
|
76
|
+
if (at("op", "(")) {
|
|
77
|
+
i += 1;
|
|
78
|
+
if (!at("op", ")")) {
|
|
79
|
+
params.push(parseParam());
|
|
80
|
+
while (at("op", ",")) {
|
|
81
|
+
i += 1;
|
|
82
|
+
params.push(parseParam());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
eat("op", ")");
|
|
86
|
+
}
|
|
87
|
+
const body = parseBlock();
|
|
88
|
+
return { type: "lambda", params, body };
|
|
89
|
+
}
|
|
90
|
+
function parseNamedCast() {
|
|
91
|
+
i += 1;
|
|
92
|
+
eat("op", "<");
|
|
93
|
+
const valueType = parseType() || "any";
|
|
94
|
+
eat("op", ">");
|
|
95
|
+
const args = parseArgs();
|
|
96
|
+
return { type: "cast", valueType, argument: args[0] || { type: "null" } };
|
|
97
|
+
}
|
|
98
|
+
function parseParenPrimary() {
|
|
99
|
+
eat("op", "(");
|
|
100
|
+
const saved = i;
|
|
101
|
+
skipSpecifiers();
|
|
102
|
+
const valueType = parseType();
|
|
103
|
+
if (valueType && at("op", ")")) {
|
|
104
|
+
i += 1;
|
|
105
|
+
if (looksLikePrimaryStart()) {
|
|
106
|
+
return { type: "cast", valueType, argument: parseUnary() };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
i = saved;
|
|
110
|
+
const expr = parseExpr();
|
|
111
|
+
eat("op", ")");
|
|
112
|
+
return expr;
|
|
113
|
+
}
|
|
114
|
+
function eatGeneric() {
|
|
115
|
+
let text = "";
|
|
116
|
+
let depth = 0;
|
|
117
|
+
while (!at("eof")) {
|
|
118
|
+
const token = peek();
|
|
119
|
+
if (at("op", "<")) {
|
|
120
|
+
depth += 1;
|
|
121
|
+
text += "<";
|
|
122
|
+
i += 1;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (at("op", ">")) {
|
|
126
|
+
depth -= 1;
|
|
127
|
+
text += ">";
|
|
128
|
+
i += 1;
|
|
129
|
+
if (depth === 0) {
|
|
130
|
+
return text;
|
|
131
|
+
}
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (token.type === "string") {
|
|
135
|
+
text += `"${token.value}"`;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
text += token.value;
|
|
139
|
+
}
|
|
140
|
+
i += 1;
|
|
141
|
+
}
|
|
142
|
+
return text;
|
|
143
|
+
}
|
|
49
144
|
function parseType() {
|
|
50
145
|
if (at("kw", "const")) {
|
|
51
146
|
i += 1;
|
|
52
147
|
}
|
|
148
|
+
let name = null;
|
|
53
149
|
if (at("kw", "auto") || at("kw", "void") || at("kw", "int") || at("kw", "bool") || at("kw", "float") || at("kw", "double")) {
|
|
54
|
-
|
|
55
|
-
|
|
150
|
+
name = eat("kw").value;
|
|
151
|
+
}
|
|
152
|
+
else if (at("ident")) {
|
|
153
|
+
name = eat("ident").value;
|
|
154
|
+
while (at("op", "::")) {
|
|
56
155
|
i += 1;
|
|
156
|
+
if (at("ident")) {
|
|
157
|
+
name += `::${eat("ident").value}`;
|
|
158
|
+
}
|
|
57
159
|
}
|
|
58
|
-
return name;
|
|
59
160
|
}
|
|
60
|
-
|
|
161
|
+
else {
|
|
61
162
|
return null;
|
|
62
163
|
}
|
|
63
|
-
|
|
164
|
+
if (at("op", "<")) {
|
|
165
|
+
name += eatGeneric();
|
|
166
|
+
}
|
|
64
167
|
while (at("op", "*")) {
|
|
65
168
|
i += 1;
|
|
66
169
|
}
|
|
@@ -129,14 +232,17 @@ function parse(source, fileName) {
|
|
|
129
232
|
eat("op", ")");
|
|
130
233
|
return { type: "getService", service };
|
|
131
234
|
}
|
|
235
|
+
if (at("ident") && CAST_NAMES.has(peek().value) && peek(1).value === "<") {
|
|
236
|
+
return parseNamedCast();
|
|
237
|
+
}
|
|
132
238
|
if (at("ident")) {
|
|
133
239
|
return { type: "ident", name: eat("ident").value };
|
|
134
240
|
}
|
|
241
|
+
if (at("op", "[")) {
|
|
242
|
+
return parseLambda();
|
|
243
|
+
}
|
|
135
244
|
if (at("op", "(")) {
|
|
136
|
-
|
|
137
|
-
const expr = parseExpr();
|
|
138
|
-
eat("op", ")");
|
|
139
|
-
return expr;
|
|
245
|
+
return parseParenPrimary();
|
|
140
246
|
}
|
|
141
247
|
if (at("op", "{")) {
|
|
142
248
|
return parseInitList();
|
|
@@ -309,11 +415,8 @@ function parse(source, fileName) {
|
|
|
309
415
|
throw error("only range-for is supported: for (auto* x : list)");
|
|
310
416
|
}
|
|
311
417
|
function parseDeclOrExpr() {
|
|
312
|
-
const isConst = at("kw", "const");
|
|
313
|
-
if (isConst) {
|
|
314
|
-
i += 1;
|
|
315
|
-
}
|
|
316
418
|
const saved = i;
|
|
419
|
+
const isConst = skipSpecifiers();
|
|
317
420
|
const maybeType = parseType();
|
|
318
421
|
if (maybeType && at("ident") && (peek(1).value === "=" || peek(1).value === ";")) {
|
|
319
422
|
const name = eat("ident").value;
|
|
@@ -325,9 +428,6 @@ function parse(source, fileName) {
|
|
|
325
428
|
return { type: "decl", name, valueType: maybeType, value, isConst: isConst || maybeType === "const" };
|
|
326
429
|
}
|
|
327
430
|
i = saved;
|
|
328
|
-
if (isConst) {
|
|
329
|
-
i = saved - 1;
|
|
330
|
-
}
|
|
331
431
|
return { type: "expr", expr: parseExpr() };
|
|
332
432
|
}
|
|
333
433
|
function parseStmt() {
|
|
@@ -380,6 +480,7 @@ function parse(source, fileName) {
|
|
|
380
480
|
};
|
|
381
481
|
}
|
|
382
482
|
function parseFunction() {
|
|
483
|
+
skipSpecifiers();
|
|
383
484
|
const returnType = parseType();
|
|
384
485
|
if (!returnType || !at("ident")) {
|
|
385
486
|
throw error("invalid function declaration");
|
|
@@ -449,10 +550,7 @@ function parse(source, fileName) {
|
|
|
449
550
|
continue;
|
|
450
551
|
}
|
|
451
552
|
const saved = i;
|
|
452
|
-
const isConst =
|
|
453
|
-
if (isConst) {
|
|
454
|
-
i += 1;
|
|
455
|
-
}
|
|
553
|
+
const isConst = skipSpecifiers();
|
|
456
554
|
const valueType = parseType();
|
|
457
555
|
if (valueType && at("ident")) {
|
|
458
556
|
if (peek(1).value === "(") {
|
|
@@ -573,10 +671,7 @@ function parse(source, fileName) {
|
|
|
573
671
|
continue;
|
|
574
672
|
}
|
|
575
673
|
const saved = i;
|
|
576
|
-
const isConst =
|
|
577
|
-
if (isConst) {
|
|
578
|
-
i += 1;
|
|
579
|
-
}
|
|
674
|
+
const isConst = skipSpecifiers();
|
|
580
675
|
const maybeType = parseType();
|
|
581
676
|
if (maybeType && at("ident")) {
|
|
582
677
|
const next = peek(1);
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.ASTCollector = void 0;
|
|
4
7
|
exports.emptyState = emptyState;
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const preprocess_js_1 = require("../preprocess.js");
|
|
5
10
|
const translators_js_1 = require("../emitter/translators.js");
|
|
6
11
|
function emptyState(strict = false) {
|
|
7
12
|
return {
|
|
@@ -16,9 +21,11 @@ function emptyState(strict = false) {
|
|
|
16
21
|
}
|
|
17
22
|
class ASTCollector {
|
|
18
23
|
mapper;
|
|
24
|
+
context;
|
|
19
25
|
state;
|
|
20
26
|
constructor(mapper, context = { fileName: "input.cpp" }) {
|
|
21
27
|
this.mapper = mapper;
|
|
28
|
+
this.context = context;
|
|
22
29
|
this.state = emptyState(context.strict === true);
|
|
23
30
|
}
|
|
24
31
|
collect(rootNode) {
|
|
@@ -58,12 +65,41 @@ class ASTCollector {
|
|
|
58
65
|
}
|
|
59
66
|
}
|
|
60
67
|
}
|
|
68
|
+
includeTarget(raw) {
|
|
69
|
+
const from = this.context.sourcePath;
|
|
70
|
+
if (!from) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const cleaned = raw.replace(/[<>'"]/g, "").trim();
|
|
74
|
+
if (!cleaned || raw.includes("<")) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return node_path_1.default.resolve(node_path_1.default.dirname(from), cleaned);
|
|
78
|
+
}
|
|
79
|
+
isOwnHeader(raw) {
|
|
80
|
+
const from = this.context.sourcePath;
|
|
81
|
+
if (!from) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const target = this.includeTarget(raw);
|
|
85
|
+
if (!target) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (node_path_1.default.resolve(from) === target) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
const header = (0, preprocess_js_1.siblingHeader)(from);
|
|
92
|
+
return Boolean(header && node_path_1.default.resolve(header) === target);
|
|
93
|
+
}
|
|
61
94
|
collectInclude(node) {
|
|
62
95
|
const pathNode = node.childForFieldName("path") || node.namedChildren[0] || node.child(1);
|
|
63
96
|
if (!pathNode) {
|
|
64
97
|
return;
|
|
65
98
|
}
|
|
66
|
-
|
|
99
|
+
if (this.isOwnHeader(pathNode.text)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const resolved = this.mapper.resolveIncludeToRequire(pathNode.text, this.context.sourcePath);
|
|
67
103
|
if (resolved) {
|
|
68
104
|
this.state.moduleRequires.set(resolved.alias, resolved.path);
|
|
69
105
|
}
|
|
@@ -64,7 +64,23 @@ class RojoMapper {
|
|
|
64
64
|
this.config = (0, comment_json_1.parse)(content);
|
|
65
65
|
this.bindings = this.walkTree(this.config.tree, []);
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
resolveQuotedFile(raw, fromFile) {
|
|
68
|
+
const bases = [];
|
|
69
|
+
if (fromFile) {
|
|
70
|
+
bases.push(node_path_1.default.dirname(fromFile));
|
|
71
|
+
}
|
|
72
|
+
if (this.srcDir) {
|
|
73
|
+
bases.push(this.srcDir);
|
|
74
|
+
}
|
|
75
|
+
for (const base of bases) {
|
|
76
|
+
const candidate = node_path_1.default.resolve(base, raw);
|
|
77
|
+
if (node_fs_1.default.existsSync(candidate) && node_fs_1.default.statSync(candidate).isFile()) {
|
|
78
|
+
return candidate;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
resolveIncludeToRequire(includePath, fromFile) {
|
|
68
84
|
const raw = includePath.replace(/[<>'"]/g, "").trim();
|
|
69
85
|
if (!raw) {
|
|
70
86
|
return null;
|
|
@@ -79,11 +95,15 @@ class RojoMapper {
|
|
|
79
95
|
if (library) {
|
|
80
96
|
return library;
|
|
81
97
|
}
|
|
82
|
-
const
|
|
98
|
+
const resolvedFile = this.resolveQuotedFile(raw, fromFile);
|
|
99
|
+
const lookupPath = resolvedFile && this.srcDir
|
|
100
|
+
? posix(node_path_1.default.relative(this.srcDir, resolvedFile)).replace(/\.h(pp|h)?$/i, "")
|
|
101
|
+
: cleanPath;
|
|
102
|
+
const fromTree = this.resolveFromRojoTree(lookupPath, baseName);
|
|
83
103
|
if (fromTree) {
|
|
84
104
|
return fromTree;
|
|
85
105
|
}
|
|
86
|
-
const segments =
|
|
106
|
+
const segments = lookupPath.split("/").filter(Boolean);
|
|
87
107
|
if (segments[0] === "src") {
|
|
88
108
|
segments.shift();
|
|
89
109
|
}
|