@lakutata/cli 2.17.0 → 3.0.0-beta.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.
- package/README.md +455 -28
- package/dist/esm/CLIApp.js +6 -0
- package/dist/esm/Config.js +53 -0
- package/dist/esm/controllers/CommandLineController.js +180 -0
- package/dist/esm/controllers/I18nController.js +67 -0
- package/dist/esm/controllers/MigrationController.js +66 -0
- package/dist/esm/controllers/NativeController.js +41 -0
- package/dist/esm/controllers/PackController.js +88 -0
- package/dist/esm/controllers/WorkspaceController.js +91 -0
- package/dist/esm/dtos/AddPackageDTO.js +25 -0
- package/dist/esm/dtos/BundleDTO.js +29 -0
- package/dist/esm/dtos/CleanDTO.js +17 -0
- package/dist/esm/dtos/CreateProjectDTO.js +61 -0
- package/dist/esm/dtos/ExecutableDTO.js +37 -0
- package/dist/esm/dtos/I18nDTO.js +41 -0
- package/dist/esm/dtos/InstallerDTO.js +33 -0
- package/dist/{options/ListTemplatesOptions.js → esm/dtos/ListTemplatesDTO.js} +5 -14
- package/dist/esm/dtos/MigrationDTO.js +45 -0
- package/dist/esm/dtos/NativeDTO.js +41 -0
- package/dist/esm/dtos/RunScriptDTO.js +33 -0
- package/dist/esm/dtos/VersionDTO.js +29 -0
- package/dist/esm/lib/AddPackage.js +487 -0
- package/dist/esm/lib/Builder.js +21 -0
- package/dist/esm/lib/Clean.js +146 -0
- package/dist/esm/lib/Environment.js +11 -0
- package/dist/esm/lib/I18n.js +67 -0
- package/dist/esm/lib/Language.js +24 -0
- package/dist/esm/lib/Migration.js +94 -0
- package/dist/esm/lib/Output.js +40 -0
- package/dist/esm/lib/Processes.js +54 -0
- package/dist/esm/lib/ProjectCreator.js +191 -0
- package/dist/esm/lib/Registry.js +152 -0
- package/dist/esm/lib/Settings.js +25 -0
- package/dist/esm/lib/Tar.js +145 -0
- package/dist/esm/lib/TemplateCatalog.js +195 -0
- package/dist/esm/lib/TemplateFeatures.js +141 -0
- package/dist/esm/lib/Versions.js +58 -0
- package/dist/esm/lib/native/CMake.js +357 -0
- package/dist/esm/lib/native/Gyp.js +398 -0
- package/dist/esm/lib/native/NativeProject.js +370 -0
- package/dist/esm/lib/native/TextEdits.js +68 -0
- package/dist/esm/lib/native/Toml.js +325 -0
- package/dist/esm/lib/workspace/Run.js +111 -0
- package/dist/esm/lib/workspace/Version.js +144 -0
- package/dist/esm/lib/workspace/Workspace.js +231 -0
- package/dist/esm/locales/zh-CN.json +194 -0
- package/dist/esm/locales/zh-TW.json +194 -0
- package/dist/esm/types/ProcessResult.js +1 -0
- package/package.json +32 -43
- package/CHANGELOG.md +0 -452
- package/dist/CLIApp.d.ts +0 -3
- package/dist/CLIApp.d.ts.map +0 -1
- package/dist/CLIApp.js +0 -45
- package/dist/config/Config.d.ts +0 -3
- package/dist/config/Config.d.ts.map +0 -1
- package/dist/config/Config.js +0 -63
- package/dist/config/SetupCLIEntrypoint.d.ts +0 -3
- package/dist/config/SetupCLIEntrypoint.d.ts.map +0 -1
- package/dist/config/SetupCLIEntrypoint.js +0 -31
- package/dist/controllers/CommandLineController.d.ts +0 -25
- package/dist/controllers/CommandLineController.d.ts.map +0 -1
- package/dist/controllers/CommandLineController.js +0 -78
- package/dist/lib/ConvertDTO2Inquirer.d.ts +0 -3
- package/dist/lib/ConvertDTO2Inquirer.d.ts.map +0 -1
- package/dist/lib/ConvertDTO2Inquirer.js +0 -61
- package/dist/lib/GetDataDirectory.d.ts +0 -2
- package/dist/lib/GetDataDirectory.d.ts.map +0 -1
- package/dist/lib/GetDataDirectory.js +0 -11
- package/dist/lib/GetLocalDataFilename.d.ts +0 -2
- package/dist/lib/GetLocalDataFilename.d.ts.map +0 -1
- package/dist/lib/GetLocalDataFilename.js +0 -12
- package/dist/lib/ListTemplateNames.d.ts +0 -2
- package/dist/lib/ListTemplateNames.d.ts.map +0 -1
- package/dist/lib/ListTemplateNames.js +0 -44
- package/dist/lib/SpecialChar.d.ts +0 -9
- package/dist/lib/SpecialChar.d.ts.map +0 -1
- package/dist/lib/SpecialChar.js +0 -11
- package/dist/lib/components/DeGitPuller.d.ts +0 -19
- package/dist/lib/components/DeGitPuller.d.ts.map +0 -1
- package/dist/lib/components/DeGitPuller.js +0 -65
- package/dist/lib/components/Spinner.d.ts +0 -23
- package/dist/lib/components/Spinner.d.ts.map +0 -1
- package/dist/lib/components/Spinner.js +0 -61
- package/dist/lib/providers/Creator.d.ts +0 -46
- package/dist/lib/providers/Creator.d.ts.map +0 -1
- package/dist/lib/providers/Creator.js +0 -179
- package/dist/lib/providers/Information.d.ts +0 -91
- package/dist/lib/providers/Information.d.ts.map +0 -1
- package/dist/lib/providers/Information.js +0 -225
- package/dist/lib/providers/OnlineLatestVersion.d.ts +0 -14
- package/dist/lib/providers/OnlineLatestVersion.d.ts.map +0 -1
- package/dist/lib/providers/OnlineLatestVersion.js +0 -47
- package/dist/lib/providers/TemplateManager.d.ts +0 -36
- package/dist/lib/providers/TemplateManager.d.ts.map +0 -1
- package/dist/lib/providers/TemplateManager.js +0 -164
- package/dist/options/CreateProjectOptions.d.ts +0 -15
- package/dist/options/CreateProjectOptions.d.ts.map +0 -1
- package/dist/options/CreateProjectOptions.js +0 -94
- package/dist/options/ListTemplatesOptions.d.ts +0 -5
- package/dist/options/ListTemplatesOptions.d.ts.map +0 -1
- package/tsconfig.json +0 -7
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { applyEdits, indentUnit, lineEndOf, lineIndent, NativeSyntaxError } from './TextEdits.js';
|
|
3
|
+
/**
|
|
4
|
+
* The blocks of CMake, by their opening command
|
|
5
|
+
*/
|
|
6
|
+
const BLOCKS = { if: 'endif', foreach: 'endforeach', while: 'endwhile', function: 'endfunction', macro: 'endmacro', block: 'endblock' };
|
|
7
|
+
/**
|
|
8
|
+
* The parser of the files of CMake, by the grammar of cmake-language(7): the command invocations, their bracket, quoted
|
|
9
|
+
* and unquoted arguments (the parentheses nested), the line and the bracket comments
|
|
10
|
+
*/
|
|
11
|
+
class CMakeParser {
|
|
12
|
+
constructor(file, text) {
|
|
13
|
+
this.file = file;
|
|
14
|
+
this.text = text;
|
|
15
|
+
this.offset = 0;
|
|
16
|
+
}
|
|
17
|
+
error(message, offset = this.offset) {
|
|
18
|
+
throw new NativeSyntaxError(this.file, this.text, offset, message);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The length of the bracket opening at an offset ([==[: its = counted), -1 when there is none
|
|
22
|
+
* @param offset
|
|
23
|
+
*/
|
|
24
|
+
bracketLevel(offset) {
|
|
25
|
+
if (this.text[offset] !== '[')
|
|
26
|
+
return -1;
|
|
27
|
+
let end = offset + 1;
|
|
28
|
+
while (this.text[end] === '=')
|
|
29
|
+
end++;
|
|
30
|
+
return this.text[end] === '[' ? end - offset - 1 : -1;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Skip a bracket ([=[…]=]) at the offset, return its content
|
|
34
|
+
*/
|
|
35
|
+
bracket() {
|
|
36
|
+
const start = this.offset;
|
|
37
|
+
const level = this.bracketLevel(this.offset);
|
|
38
|
+
const close = `]${'='.repeat(level)}]`;
|
|
39
|
+
const contentStart = this.offset + level + 2;
|
|
40
|
+
const end = this.text.indexOf(close, contentStart);
|
|
41
|
+
if (end < 0)
|
|
42
|
+
this.error('unterminated bracket', start);
|
|
43
|
+
this.offset = end + close.length;
|
|
44
|
+
//The newline right after the opening bracket is not part of its content
|
|
45
|
+
return this.text.slice(contentStart, end).replace(/^\r?\n/, '');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Skip a comment at the offset (#…, #[[…]])
|
|
49
|
+
*/
|
|
50
|
+
comment() {
|
|
51
|
+
this.offset++;
|
|
52
|
+
if (this.bracketLevel(this.offset) >= 0) {
|
|
53
|
+
this.bracket();
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
while (this.offset < this.text.length && this.text[this.offset] !== '\n')
|
|
57
|
+
this.offset++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Skip the spaces, the newlines and the comments
|
|
62
|
+
*/
|
|
63
|
+
skip() {
|
|
64
|
+
for (;;) {
|
|
65
|
+
const char = this.text[this.offset];
|
|
66
|
+
if (char === ' ' || char === '\t' || char === '\r' || char === '\n')
|
|
67
|
+
this.offset++;
|
|
68
|
+
else if (char === '#')
|
|
69
|
+
this.comment();
|
|
70
|
+
else
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
parse() {
|
|
75
|
+
const commands = [];
|
|
76
|
+
let depth = 0;
|
|
77
|
+
for (;;) {
|
|
78
|
+
this.skip();
|
|
79
|
+
if (this.offset >= this.text.length)
|
|
80
|
+
return commands;
|
|
81
|
+
const start = this.offset;
|
|
82
|
+
const identifier = /^[A-Za-z_][A-Za-z0-9_]*/.exec(this.text.slice(this.offset));
|
|
83
|
+
if (!identifier)
|
|
84
|
+
this.error(`unexpected ${JSON.stringify(this.text[this.offset])}`);
|
|
85
|
+
this.offset += identifier[0].length;
|
|
86
|
+
while (this.text[this.offset] === ' ' || this.text[this.offset] === '\t')
|
|
87
|
+
this.offset++;
|
|
88
|
+
if (this.text[this.offset] !== '(')
|
|
89
|
+
this.error('expected "(" after the name of the command');
|
|
90
|
+
this.offset++;
|
|
91
|
+
const args = this.arguments();
|
|
92
|
+
const name = identifier[0].toLowerCase();
|
|
93
|
+
//The commands closing a block are at the depth of their opening one
|
|
94
|
+
if (Object.values(BLOCKS).includes(name))
|
|
95
|
+
depth = Math.max(0, depth - 1);
|
|
96
|
+
commands.push({ name: name, args: args, start: start, end: this.offset, depth: ['else', 'elseif'].includes(name) ? Math.max(0, depth - 1) : depth });
|
|
97
|
+
if (name in BLOCKS)
|
|
98
|
+
depth++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The arguments of a command, until its closing parenthesis (the parentheses nested are unquoted arguments)
|
|
103
|
+
*/
|
|
104
|
+
arguments() {
|
|
105
|
+
const args = [];
|
|
106
|
+
let nested = 0;
|
|
107
|
+
for (;;) {
|
|
108
|
+
this.skip();
|
|
109
|
+
if (this.offset >= this.text.length)
|
|
110
|
+
this.error('unterminated command');
|
|
111
|
+
const char = this.text[this.offset];
|
|
112
|
+
const start = this.offset;
|
|
113
|
+
if (char === ')') {
|
|
114
|
+
this.offset++;
|
|
115
|
+
if (nested === 0)
|
|
116
|
+
return args;
|
|
117
|
+
nested--;
|
|
118
|
+
args.push({ kind: 'unquoted', value: ')', start: start, end: this.offset });
|
|
119
|
+
}
|
|
120
|
+
else if (char === '(') {
|
|
121
|
+
this.offset++;
|
|
122
|
+
nested++;
|
|
123
|
+
args.push({ kind: 'unquoted', value: '(', start: start, end: this.offset });
|
|
124
|
+
}
|
|
125
|
+
else if (char === '[' && this.bracketLevel(this.offset) >= 0) {
|
|
126
|
+
args.push({ kind: 'bracket', value: this.bracket(), start: start, end: this.offset });
|
|
127
|
+
}
|
|
128
|
+
else if (char === '"') {
|
|
129
|
+
args.push({ kind: 'quoted', value: this.quoted(), start: start, end: this.offset });
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
args.push({ kind: 'unquoted', value: this.unquoted(), start: start, end: this.offset });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
quoted() {
|
|
137
|
+
const start = this.offset;
|
|
138
|
+
this.offset++;
|
|
139
|
+
let value = '';
|
|
140
|
+
for (;;) {
|
|
141
|
+
if (this.offset >= this.text.length)
|
|
142
|
+
this.error('unterminated quoted argument', start);
|
|
143
|
+
const char = this.text[this.offset];
|
|
144
|
+
if (char === '"') {
|
|
145
|
+
this.offset++;
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
if (char === '\\') {
|
|
149
|
+
const next = this.text[this.offset + 1] ?? '';
|
|
150
|
+
//A line continuation, an encoded escape, or the character escaped
|
|
151
|
+
value += next === '\n' ? '' : next === 't' ? '\t' : next === 'r' ? '\r' : next === 'n' ? '\n' : next === ';' ? '\;' : next;
|
|
152
|
+
this.offset += 2;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
value += char;
|
|
156
|
+
this.offset++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* An unquoted argument: its characters but the whitespaces and ()#"\ (escaped by \), with the quoted parts of the
|
|
161
|
+
* legacy arguments (-Da="b c")
|
|
162
|
+
*/
|
|
163
|
+
unquoted() {
|
|
164
|
+
let value = '';
|
|
165
|
+
for (;;) {
|
|
166
|
+
const char = this.text[this.offset];
|
|
167
|
+
if (char === undefined || /[\s()#]/.test(char))
|
|
168
|
+
return value;
|
|
169
|
+
if (char === '\\') {
|
|
170
|
+
value += this.text.slice(this.offset, this.offset + 2);
|
|
171
|
+
this.offset += 2;
|
|
172
|
+
}
|
|
173
|
+
else if (char === '"') {
|
|
174
|
+
//The quotes inside of a legacy unquoted argument
|
|
175
|
+
const end = this.text.indexOf('"', this.offset + 1);
|
|
176
|
+
if (end < 0)
|
|
177
|
+
this.error('unterminated quote');
|
|
178
|
+
value += this.text.slice(this.offset, end + 1);
|
|
179
|
+
this.offset = end + 1;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
value += char;
|
|
183
|
+
this.offset++;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* A file of CMake (CMakeLists.txt), parsed with the places of its commands: it is changed by edits of its text, its
|
|
190
|
+
* comments and its layout kept
|
|
191
|
+
*/
|
|
192
|
+
export class CMakeDocument {
|
|
193
|
+
constructor(file, text) {
|
|
194
|
+
this.file = file;
|
|
195
|
+
this.text = text;
|
|
196
|
+
this.edits = [];
|
|
197
|
+
this.commands = new CMakeParser(file, text).parse();
|
|
198
|
+
this.indent = indentUnit(text);
|
|
199
|
+
}
|
|
200
|
+
static async read(file) {
|
|
201
|
+
return new CMakeDocument(file, await readFile(file, 'utf8'));
|
|
202
|
+
}
|
|
203
|
+
get changes() {
|
|
204
|
+
return this.edits;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The document with its changes (parsed again)
|
|
208
|
+
*/
|
|
209
|
+
applied() {
|
|
210
|
+
return new CMakeDocument(this.file, applyEdits(this.text, this.edits));
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The value of an argument, its variables resolved (${PROJECT_NAME}, the variables set at the top level)
|
|
214
|
+
* @param value
|
|
215
|
+
*/
|
|
216
|
+
resolve(value) {
|
|
217
|
+
const variables = new Map();
|
|
218
|
+
for (const command of this.commands) {
|
|
219
|
+
if (command.depth !== 0)
|
|
220
|
+
continue;
|
|
221
|
+
if (command.name === 'project' && command.args[0])
|
|
222
|
+
variables.set('PROJECT_NAME', command.args[0].value);
|
|
223
|
+
if (command.name === 'set' && command.args.length === 2)
|
|
224
|
+
variables.set(command.args[0].value, command.args[1].value);
|
|
225
|
+
}
|
|
226
|
+
return value.replace(/\$\{([A-Za-z0-9_]+)\}/g, (all, name) => variables.get(name) ?? all);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The targets of the libraries and the executables: their name, and the text naming them in their command
|
|
230
|
+
*/
|
|
231
|
+
targets() {
|
|
232
|
+
return this.commands
|
|
233
|
+
.filter((command) => (command.name === 'add_library' || command.name === 'add_executable') && command.args.length > 0)
|
|
234
|
+
.map((command) => ({
|
|
235
|
+
name: this.resolve(command.args[0].value),
|
|
236
|
+
text: this.text.slice(command.args[0].start, command.args[0].end),
|
|
237
|
+
command: command
|
|
238
|
+
}));
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* The target changed: the one named, the only one by default
|
|
242
|
+
* @param name
|
|
243
|
+
*/
|
|
244
|
+
target(name) {
|
|
245
|
+
const targets = this.targets();
|
|
246
|
+
if (!targets.length)
|
|
247
|
+
throw new Error(`${this.file} declares no target (add_library)`);
|
|
248
|
+
if (name !== undefined) {
|
|
249
|
+
const target = targets.find((candidate) => candidate.name === name);
|
|
250
|
+
if (!target)
|
|
251
|
+
throw new Error(`${this.file} has no target ${name} (${targets.map((candidate) => candidate.name).join(', ')})`);
|
|
252
|
+
return target;
|
|
253
|
+
}
|
|
254
|
+
if (targets.length > 1)
|
|
255
|
+
throw new Error(`${this.file} has several targets (${targets.map((candidate) => candidate.name).join(', ')}): --target gives the one changed`);
|
|
256
|
+
return targets[0];
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Whether a command with these arguments exists (the arguments compared by their resolved values)
|
|
260
|
+
* @param name
|
|
261
|
+
* @param args
|
|
262
|
+
*/
|
|
263
|
+
has(name, args) {
|
|
264
|
+
const expected = args.map((arg) => this.resolve(arg.replace(/^"(.*)"$/, '$1')));
|
|
265
|
+
return this.commands.some((command) => command.name === name.toLowerCase() &&
|
|
266
|
+
command.args.length === expected.length &&
|
|
267
|
+
command.args.every((arg, index) => this.resolve(arg.value) === expected[index]));
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Insert commands after the last command of the top level about a target (its add_library, its target_* and
|
|
271
|
+
* set_target_properties commands, the add_custom_command of the target), on lines of their own
|
|
272
|
+
* @param target
|
|
273
|
+
* @param lines the commands, a line each
|
|
274
|
+
* @param condition the condition of the if block they are given in
|
|
275
|
+
*/
|
|
276
|
+
insertAfterTarget(target, lines, condition) {
|
|
277
|
+
const about = this.commands.filter((command) => command.depth === 0 && (command === target.command ||
|
|
278
|
+
((command.name.startsWith('target_') || command.name === 'set_target_properties') && command.args[0] !== undefined && this.resolve(command.args[0].value) === target.name) ||
|
|
279
|
+
(command.name === 'add_custom_command' && command.args[0]?.value.toUpperCase() === 'TARGET' && command.args[1] !== undefined && this.resolve(command.args[1].value) === target.name)));
|
|
280
|
+
//Inside of the block of the condition about the target already written
|
|
281
|
+
if (condition !== undefined) {
|
|
282
|
+
const block = this.conditionBlock(target, condition);
|
|
283
|
+
if (block) {
|
|
284
|
+
const last = this.commands[this.commands.indexOf(block) - 1];
|
|
285
|
+
const indent = this.commands[this.commands.indexOf(block) - 1].depth === 1 ? lineIndent(this.text, last.start) : lineIndent(this.text, block.start) + this.indent;
|
|
286
|
+
this.edits.push({ offset: lineEndOf(this.text, last.end), remove: 0, insert: `\n${lines.map((line) => `${indent}${line}`).join('\n')}` });
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
//The block of a condition: the if blocks of the target are followed by the next one
|
|
291
|
+
const anchor = this.blockEnd(about.at(-1));
|
|
292
|
+
const indent = lineIndent(this.text, anchor.start);
|
|
293
|
+
const block = condition === undefined
|
|
294
|
+
? lines.map((line) => `${indent}${line}`).join('\n')
|
|
295
|
+
: [`${indent}if(${condition})`, ...lines.map((line) => `${indent}${this.indent}${line}`), `${indent}endif()`].join('\n');
|
|
296
|
+
this.edits.push({ offset: lineEndOf(this.text, anchor.end), remove: 0, insert: `\n${block}` });
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* The endif of a block of the top level with a condition, after the target, holding only commands about it (its if
|
|
300
|
+
* has no else)
|
|
301
|
+
* @param target
|
|
302
|
+
* @param condition
|
|
303
|
+
*/
|
|
304
|
+
conditionBlock(target, condition) {
|
|
305
|
+
const normalize = (text) => text.replace(/\s+/g, ' ').trim();
|
|
306
|
+
for (let index = this.commands.indexOf(target.command) + 1; index < this.commands.length; index++) {
|
|
307
|
+
const command = this.commands[index];
|
|
308
|
+
if (command.name !== 'if' || command.depth !== 0)
|
|
309
|
+
continue;
|
|
310
|
+
const open = this.text.indexOf('(', command.start);
|
|
311
|
+
if (normalize(this.text.slice(open + 1, command.end - 1)) !== normalize(condition))
|
|
312
|
+
continue;
|
|
313
|
+
let end = index + 1;
|
|
314
|
+
let about = true;
|
|
315
|
+
while (end < this.commands.length && !(this.commands[end].depth === 0 && this.commands[end].name === 'endif')) {
|
|
316
|
+
const inner = this.commands[end];
|
|
317
|
+
if (inner.depth === 0)
|
|
318
|
+
about = false;
|
|
319
|
+
else if (inner.depth === 1 && !(['find_package', 'pkg_check_modules'].includes(inner.name) || (['target_link_libraries', 'target_include_directories', 'target_compile_definitions', 'set_target_properties', 'add_custom_command'].includes(inner.name) &&
|
|
320
|
+
[inner.args[0]?.value, inner.args[1]?.value].some((arg) => arg !== undefined && this.resolve(arg) === target.name))))
|
|
321
|
+
about = false;
|
|
322
|
+
end++;
|
|
323
|
+
}
|
|
324
|
+
if (about && end > index + 1 && end < this.commands.length)
|
|
325
|
+
return this.commands[end];
|
|
326
|
+
}
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* The last command of the if blocks following a command (the conditions about a target written after it)
|
|
331
|
+
* @param command
|
|
332
|
+
*/
|
|
333
|
+
blockEnd(command) {
|
|
334
|
+
let index = this.commands.indexOf(command);
|
|
335
|
+
for (;;) {
|
|
336
|
+
const next = this.commands[index + 1];
|
|
337
|
+
if (next?.name !== 'if' || next.depth !== 0)
|
|
338
|
+
return this.commands[index];
|
|
339
|
+
//The block, until its endif
|
|
340
|
+
let end = index + 2;
|
|
341
|
+
while (end < this.commands.length && !(this.commands[end].name === 'endif' && this.commands[end].depth === 0))
|
|
342
|
+
end++;
|
|
343
|
+
//Its commands are about the target only when the first one is
|
|
344
|
+
const first = this.commands[index + 2];
|
|
345
|
+
if (!first || first.depth !== 1 || !(first.name.startsWith('target_') || ['set_target_properties', 'add_custom_command', 'find_package', 'pkg_check_modules'].includes(first.name)))
|
|
346
|
+
return this.commands[index];
|
|
347
|
+
index = end;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* An argument of CMake for a value: quoted when it has spaces, semicolons, parentheses or quotes
|
|
353
|
+
* @param value
|
|
354
|
+
*/
|
|
355
|
+
export function cMakeArgumentText(value) {
|
|
356
|
+
return /[\s;()#"\\]/.test(value) && !/^\$<.*>$/.test(value) ? `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"` : value;
|
|
357
|
+
}
|