Skip to content

Commit 684425d

Browse files
committed
✨ - Support rewatch for incremental compilation
1 parent 3aeb7e3 commit 684425d

File tree

1 file changed

+112
-58
lines changed

1 file changed

+112
-58
lines changed

Diff for: server/src/incrementalCompilation.ts

+112-58
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ function debug() {
2020
const INCREMENTAL_FOLDER_NAME = "___incremental";
2121
const INCREMENTAL_FILE_FOLDER_LOCATION = `lib/bs/${INCREMENTAL_FOLDER_NAME}`;
2222

23+
type RewatchCompilerArgs = {
24+
compiler_args: Array<string>;
25+
parser_args: Array<string>;
26+
};
27+
2328
type IncrementallyCompiledFileInfo = {
2429
file: {
2530
/** File type. */
@@ -44,6 +49,10 @@ type IncrementallyCompiledFileInfo = {
4449
/** The raw, extracted needed info from build.ninja. Needs processing. */
4550
rawExtracted: Array<string>;
4651
} | null;
52+
/** Cache for rewatch compiler args. */
53+
buildRewatch: {
54+
compilerArgs: RewatchCompilerArgs;
55+
} | null;
4756
/** Info of the currently active incremental compilation. `null` if no incremental compilation is active. */
4857
compilation: {
4958
/** The timeout of the currently active compilation for this incremental file. */
@@ -176,18 +185,28 @@ export function cleanUpIncrementalFiles(
176185
}
177186
function getBscArgs(
178187
entry: IncrementallyCompiledFileInfo
179-
): Promise<Array<string> | null> {
188+
): Promise<Array<string> | RewatchCompilerArgs | null> {
180189
const buildNinjaPath = path.resolve(
181190
entry.project.rootPath,
182191
"lib/bs/build.ninja"
183192
);
193+
const rewatchLockfile = path.resolve(
194+
entry.project.rootPath,
195+
"lib/rewatch.lock"
196+
);
197+
let buildSystem: "bsb" | "rewatch" | null = null;
198+
184199
let stat: fs.Stats | null = null;
185200
try {
186201
stat = fs.statSync(buildNinjaPath);
187-
} catch {
188-
if (debug()) {
189-
console.log("Did not find build.ninja, cannot proceed..");
190-
}
202+
buildSystem = "bsb";
203+
} catch {}
204+
try {
205+
stat = fs.statSync(rewatchLockfile);
206+
buildSystem = "rewatch";
207+
} catch {}
208+
if (buildSystem == null) {
209+
console.log("Did not find build.ninja or rewatch.lock, cannot proceed..");
191210
return Promise.resolve(null);
192211
}
193212
const cacheEntry = entry.buildNinja;
@@ -199,73 +218,91 @@ function getBscArgs(
199218
return Promise.resolve(cacheEntry.rawExtracted);
200219
}
201220
return new Promise((resolve, _reject) => {
202-
function resolveResult(result: Array<string>) {
203-
if (stat != null) {
221+
function resolveResult(result: Array<string> | RewatchCompilerArgs) {
222+
if (stat != null && Array.isArray(result)) {
204223
entry.buildNinja = {
205224
fileMtime: stat.mtimeMs,
206225
rawExtracted: result,
207226
};
208227
}
209228
resolve(result);
210229
}
211-
const fileStream = fs.createReadStream(buildNinjaPath);
212-
const rl = readline.createInterface({
213-
input: fileStream,
214-
crlfDelay: Infinity,
215-
});
216-
let captureNextLine = false;
217-
let done = false;
218-
let stopped = false;
219-
const captured: Array<string> = [];
220-
rl.on("line", (line) => {
221-
if (stopped) {
222-
return;
223-
}
224-
if (captureNextLine) {
225-
captured.push(line);
226-
captureNextLine = false;
227-
}
228-
if (done) {
229-
fileStream.destroy();
230-
rl.close();
230+
231+
if (buildSystem === "bsb") {
232+
const fileStream = fs.createReadStream(buildNinjaPath);
233+
const rl = readline.createInterface({
234+
input: fileStream,
235+
crlfDelay: Infinity,
236+
});
237+
let captureNextLine = false;
238+
let done = false;
239+
let stopped = false;
240+
const captured: Array<string> = [];
241+
rl.on("line", (line) => {
242+
if (stopped) {
243+
return;
244+
}
245+
if (captureNextLine) {
246+
captured.push(line);
247+
captureNextLine = false;
248+
}
249+
if (done) {
250+
fileStream.destroy();
251+
rl.close();
252+
resolveResult(captured);
253+
stopped = true;
254+
return;
255+
}
256+
if (line.startsWith("rule astj")) {
257+
captureNextLine = true;
258+
}
259+
if (line.startsWith("rule mij")) {
260+
captureNextLine = true;
261+
done = true;
262+
}
263+
});
264+
rl.on("close", () => {
231265
resolveResult(captured);
232-
stopped = true;
233-
return;
234-
}
235-
if (line.startsWith("rule astj")) {
236-
captureNextLine = true;
237-
}
238-
if (line.startsWith("rule mij")) {
239-
captureNextLine = true;
240-
done = true;
266+
});
267+
} else if (buildSystem === "rewatch") {
268+
try {
269+
let rewatchPath = path.resolve(
270+
entry.project.rootPath,
271+
"../rewatch/target/debug/rewatch"
272+
);
273+
const compilerArgs = JSON.parse(
274+
cp
275+
.execFileSync(rewatchPath, [
276+
"--rescript-version",
277+
entry.project.rescriptVersion,
278+
"--get-compiler-args",
279+
entry.file.sourceFilePath,
280+
])
281+
.toString()
282+
.trim()
283+
) as RewatchCompilerArgs;
284+
resolveResult(compilerArgs);
285+
} catch (e) {
286+
console.error(e);
241287
}
242-
});
243-
rl.on("close", () => {
244-
resolveResult(captured);
245-
});
288+
}
246289
});
247290
}
248-
function argsFromCommandString(cmdString: string): Array<Array<string>> {
249-
const s = cmdString
250-
.trim()
251-
.split("command = ")[1]
252-
.split(" ")
253-
.map((v) => v.trim())
254-
.filter((v) => v !== "");
255-
const args: Array<Array<string>> = [];
256291

257-
for (let i = 0; i <= s.length - 1; i++) {
258-
const item = s[i];
292+
function argCouples(argList: string[]): string[][] {
293+
let args: string[][] = [];
294+
for (let i = 0; i <= argList.length - 1; i++) {
295+
const item = argList[i];
259296
const nextIndex = i + 1;
260-
const nextItem = s[nextIndex] ?? "";
297+
const nextItem = argList[nextIndex] ?? "";
261298
if (item.startsWith("-") && nextItem.startsWith("-")) {
262299
// Single entry arg
263300
args.push([item]);
264301
} else if (item.startsWith("-") && nextItem.startsWith("'")) {
265302
// Quoted arg, take until ending '
266303
const arg = [nextItem.slice(1)];
267-
for (let x = nextIndex + 1; x <= s.length - 1; x++) {
268-
let subItem = s[x];
304+
for (let x = nextIndex + 1; x <= argList.length - 1; x++) {
305+
let subItem = argList[x];
269306
let break_ = false;
270307
if (subItem.endsWith("'")) {
271308
subItem = subItem.slice(0, subItem.length - 1);
@@ -284,6 +321,17 @@ function argsFromCommandString(cmdString: string): Array<Array<string>> {
284321
}
285322
return args;
286323
}
324+
325+
function argsFromCommandString(cmdString: string): Array<Array<string>> {
326+
const argList = cmdString
327+
.trim()
328+
.split("command = ")[1]
329+
.split(" ")
330+
.map((v) => v.trim())
331+
.filter((v) => v !== "");
332+
333+
return argCouples(argList);
334+
}
287335
function removeAnsiCodes(s: string): string {
288336
const ansiEscape = /\x1B[@-_][0-?]*[ -/]*[@-~]/g;
289337
return s.replace(ansiEscape, "");
@@ -368,6 +416,7 @@ function triggerIncrementalCompilationOfFile(
368416
incrementalFolderPath,
369417
rescriptVersion,
370418
},
419+
buildRewatch: null,
371420
buildNinja: null,
372421
compilation: null,
373422
killCompilationListeners: [],
@@ -419,11 +468,16 @@ function verifyTriggerToken(filePath: string, triggerToken: number): boolean {
419468
async function figureOutBscArgs(entry: IncrementallyCompiledFileInfo) {
420469
const res = await getBscArgs(entry);
421470
if (res == null) return null;
422-
const [astBuildCommand, fullBuildCommand] = res;
423-
424-
const astArgs = argsFromCommandString(astBuildCommand);
425-
const buildArgs = argsFromCommandString(fullBuildCommand);
426-
471+
let astArgs: Array<Array<string>> = [];
472+
let buildArgs: Array<Array<string>> = [];
473+
if (Array.isArray(res)) {
474+
const [astBuildCommand, fullBuildCommand] = res;
475+
astArgs = argsFromCommandString(astBuildCommand);
476+
buildArgs = argsFromCommandString(fullBuildCommand);
477+
} else {
478+
astArgs = argCouples(res.parser_args);
479+
buildArgs = argCouples(res.compiler_args);
480+
}
427481
let callArgs: Array<string> = [];
428482

429483
if (config.extensionConfiguration.incrementalTypechecking?.acrossFiles) {

0 commit comments

Comments
 (0)