@alint-js/core 0.0.28 → 0.0.30
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/dist/{retry-C4sGjSE5.mjs → agent-weXkvGkc.mjs} +20 -1
- package/dist/agent.d.mts +3 -2
- package/dist/agent.mjs +2 -15
- package/dist/extract-CIWssxNK.mjs +358 -0
- package/dist/index.d.mts +56 -87
- package/dist/index.mjs +434 -885
- package/dist/languages-js.d.mts +5 -0
- package/dist/languages-js.mjs +2 -0
- package/dist/structured-output.d.mts +1 -1
- package/dist/structured-output.mjs +5 -4
- package/dist/{types-BM_nUu_Z.d.mts → types-CR_Grd6q.d.mts} +2 -87
- package/dist/types-DSvXUVZ7.d.mts +86 -0
- package/package.json +6 -2
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as withAgentRetry, t as combineAbortSignals } from "./agent-weXkvGkc.mjs";
|
|
2
|
+
import { a as sliceRange, i as sliceLines, n as createSourceFile, r as createSourceRuntime, t as extractJsSourceTargets } from "./extract-CIWssxNK.mjs";
|
|
2
3
|
import { minimatch } from "minimatch";
|
|
3
4
|
import { isAbsolute, relative, resolve } from "pathe";
|
|
4
5
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
5
6
|
import { dirname, extname, isAbsolute as isAbsolute$1, join, relative as relative$1, resolve as resolve$1, sep } from "node:path";
|
|
6
|
-
import { clamp } from "es-toolkit";
|
|
7
|
-
import { parseSync } from "oxc-parser";
|
|
8
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
8
|
import process, { cwd } from "node:process";
|
|
10
|
-
import { errorCauseFrom, errorMessageFrom } from "@moeru/std/error";
|
|
11
9
|
import { createHash, randomUUID } from "node:crypto";
|
|
12
10
|
import { statSync } from "node:fs";
|
|
13
11
|
import { array, check, description, is, literal, number, object, optional, pipe, record, string, union, unknown } from "valibot";
|
|
12
|
+
import { errorMessageFrom } from "@moeru/std/error";
|
|
14
13
|
//#region src/config/config-array.ts
|
|
15
14
|
const effectiveBasePathSymbol = Symbol("effectiveBasePath");
|
|
16
15
|
const inheritedMatcherScopesSymbol = Symbol("inheritedMatcherScopes");
|
|
@@ -233,359 +232,6 @@ function withExpansionMetadata(item, inheritedMatcherScopes, effectiveBasePath)
|
|
|
233
232
|
return item;
|
|
234
233
|
}
|
|
235
234
|
//#endregion
|
|
236
|
-
//#region src/core/source/runtime.ts
|
|
237
|
-
function createSourceFile(path, text) {
|
|
238
|
-
return {
|
|
239
|
-
language: inferLanguage(path),
|
|
240
|
-
lines: text.split(/\r?\n/),
|
|
241
|
-
path,
|
|
242
|
-
text
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
function createSourceRuntime() {
|
|
246
|
-
return {
|
|
247
|
-
getText,
|
|
248
|
-
readFile: async (filePath) => createSourceFile(filePath, await readFile(filePath, "utf8")),
|
|
249
|
-
sliceLines,
|
|
250
|
-
sliceRange
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
function getText(target) {
|
|
254
|
-
return target.text;
|
|
255
|
-
}
|
|
256
|
-
function sliceLines(file, range) {
|
|
257
|
-
const startLine = clampLine(range.startLine, file.lines.length);
|
|
258
|
-
const endLine = clampLine(range.endLine, file.lines.length);
|
|
259
|
-
const orderedStartLine = Math.min(startLine, endLine);
|
|
260
|
-
const orderedEndLine = Math.max(startLine, endLine);
|
|
261
|
-
const text = file.lines.slice(orderedStartLine - 1, orderedEndLine).join("\n");
|
|
262
|
-
return {
|
|
263
|
-
filePath: file.path,
|
|
264
|
-
loc: {
|
|
265
|
-
end: {
|
|
266
|
-
column: file.lines[orderedEndLine - 1]?.length ?? 0,
|
|
267
|
-
line: orderedEndLine
|
|
268
|
-
},
|
|
269
|
-
start: {
|
|
270
|
-
column: 0,
|
|
271
|
-
line: orderedStartLine
|
|
272
|
-
}
|
|
273
|
-
},
|
|
274
|
-
text
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
function sliceRange(file, range) {
|
|
278
|
-
const start = clampOffset(range.start, file.text.length);
|
|
279
|
-
const end = clampOffset(range.end, file.text.length);
|
|
280
|
-
const orderedStart = Math.min(start, end);
|
|
281
|
-
const orderedEnd = Math.max(start, end);
|
|
282
|
-
return {
|
|
283
|
-
filePath: file.path,
|
|
284
|
-
loc: {
|
|
285
|
-
end: getPosition(file.text, orderedEnd),
|
|
286
|
-
start: getPosition(file.text, orderedStart)
|
|
287
|
-
},
|
|
288
|
-
text: file.text.slice(orderedStart, orderedEnd)
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
function clampLine(line, lineCount) {
|
|
292
|
-
if (lineCount === 0) return 1;
|
|
293
|
-
return clamp(Math.trunc(line), 1, lineCount);
|
|
294
|
-
}
|
|
295
|
-
function clampOffset(offset, textLength) {
|
|
296
|
-
return clamp(Math.trunc(offset), 0, textLength);
|
|
297
|
-
}
|
|
298
|
-
function getPosition(text, offset) {
|
|
299
|
-
let line = 1;
|
|
300
|
-
let column = 0;
|
|
301
|
-
let index = 0;
|
|
302
|
-
while (index < offset) {
|
|
303
|
-
const character = text[index];
|
|
304
|
-
if (character === "\r") {
|
|
305
|
-
if (text[index + 1] === "\n" && index + 1 < offset) index += 1;
|
|
306
|
-
line += 1;
|
|
307
|
-
column = 0;
|
|
308
|
-
} else if (character === "\n") {
|
|
309
|
-
line += 1;
|
|
310
|
-
column = 0;
|
|
311
|
-
} else column += 1;
|
|
312
|
-
index += 1;
|
|
313
|
-
}
|
|
314
|
-
return {
|
|
315
|
-
column,
|
|
316
|
-
line
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
function inferLanguage(path) {
|
|
320
|
-
switch (extname(path)) {
|
|
321
|
-
case ".cjs":
|
|
322
|
-
case ".js":
|
|
323
|
-
case ".jsx":
|
|
324
|
-
case ".mjs": return "javascript";
|
|
325
|
-
case ".cts":
|
|
326
|
-
case ".mts":
|
|
327
|
-
case ".ts":
|
|
328
|
-
case ".tsx": return "typescript";
|
|
329
|
-
default: return "unknown";
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
//#endregion
|
|
333
|
-
//#region src/core/languages/js/parser.ts
|
|
334
|
-
function parseSync$1(filename, sourceText, options) {
|
|
335
|
-
return parseSync(filename, sourceText, options);
|
|
336
|
-
}
|
|
337
|
-
//#endregion
|
|
338
|
-
//#region src/core/languages/js/extract.ts
|
|
339
|
-
function extractJsSourceTargets(file) {
|
|
340
|
-
const result = parseSync$1(file.path, file.text, { sourceType: "module" });
|
|
341
|
-
const state = {
|
|
342
|
-
bindingNodes: /* @__PURE__ */ new Map(),
|
|
343
|
-
exportedNodes: /* @__PURE__ */ new Set(),
|
|
344
|
-
file,
|
|
345
|
-
inferredNames: /* @__PURE__ */ new Map(),
|
|
346
|
-
seenClasses: /* @__PURE__ */ new Set(),
|
|
347
|
-
seenFunctions: /* @__PURE__ */ new Set(),
|
|
348
|
-
targets: [],
|
|
349
|
-
visited: /* @__PURE__ */ new Set()
|
|
350
|
-
};
|
|
351
|
-
collectModuleBindings(result.program, state);
|
|
352
|
-
collectExportedBindings(result.program, state);
|
|
353
|
-
visit(result.program, state);
|
|
354
|
-
const sortedTargets = [...state.targets].sort((left, right) => (left.range?.start ?? 0) - (right.range?.start ?? 0));
|
|
355
|
-
return [createFileTarget(file), ...withStableIdentities(sortedTargets)];
|
|
356
|
-
}
|
|
357
|
-
function addClassTarget(node, state) {
|
|
358
|
-
if (state.seenClasses.has(node)) return;
|
|
359
|
-
const target = createClassTarget(node, state);
|
|
360
|
-
if (!target) return;
|
|
361
|
-
state.seenClasses.add(node);
|
|
362
|
-
state.targets.push(target);
|
|
363
|
-
}
|
|
364
|
-
function addFunctionTarget(node, state) {
|
|
365
|
-
if (state.seenFunctions.has(node)) return;
|
|
366
|
-
const target = createFunctionTarget(node, state);
|
|
367
|
-
if (!target) return;
|
|
368
|
-
state.seenFunctions.add(node);
|
|
369
|
-
state.targets.push(target);
|
|
370
|
-
}
|
|
371
|
-
function asAstNode(value) {
|
|
372
|
-
return isAstNode(value) ? value : void 0;
|
|
373
|
-
}
|
|
374
|
-
function collectDeclarationBindings(node, state) {
|
|
375
|
-
const name = getNodeName(node);
|
|
376
|
-
if (name && (isClassNode(node) || isFunctionNode(node))) {
|
|
377
|
-
state.bindingNodes.set(name, node);
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
if (node.type !== "VariableDeclaration" || !Array.isArray(node.declarations)) return;
|
|
381
|
-
for (const declarator of node.declarations) {
|
|
382
|
-
if (!isAstNode(declarator)) continue;
|
|
383
|
-
const id = asAstNode(declarator.id);
|
|
384
|
-
const initializer = asAstNode(declarator.init);
|
|
385
|
-
if (typeof id?.name === "string" && initializer && (isClassNode(initializer) || isFunctionNode(initializer))) state.bindingNodes.set(id.name, initializer);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
function collectExportedBindings(node, state) {
|
|
389
|
-
if (!node) return;
|
|
390
|
-
if (Array.isArray(node)) {
|
|
391
|
-
for (const child of node) collectExportedBindings(child, state);
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
if (node.type === "ExportNamedDeclaration" && !node.source && Array.isArray(node.specifiers)) for (const specifier of node.specifiers) {
|
|
395
|
-
if (!isAstNode(specifier) || specifier.type !== "ExportSpecifier") continue;
|
|
396
|
-
const local = asAstNode(specifier.local);
|
|
397
|
-
if (typeof local?.name === "string") markExportedBinding(local.name, state);
|
|
398
|
-
}
|
|
399
|
-
else if (node.type === "ExportDefaultDeclaration") {
|
|
400
|
-
const declaration = asAstNode(node.declaration);
|
|
401
|
-
if (typeof declaration?.name === "string") markExportedBinding(declaration.name, state);
|
|
402
|
-
}
|
|
403
|
-
for (const value of Object.values(node)) if (Array.isArray(value)) collectExportedBindings(value.filter(isAstNode), state);
|
|
404
|
-
else if (isAstNode(value)) collectExportedBindings(value, state);
|
|
405
|
-
}
|
|
406
|
-
function collectModuleBindings(program, state) {
|
|
407
|
-
if (!Array.isArray(program.body)) return;
|
|
408
|
-
for (const statement of program.body) {
|
|
409
|
-
if (!isAstNode(statement)) continue;
|
|
410
|
-
const declaration = isExportDeclaration(statement) ? asAstNode(statement.declaration) : statement;
|
|
411
|
-
if (declaration) collectDeclarationBindings(declaration, state);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
function createClassTarget(node, state) {
|
|
415
|
-
const range = getRange(node);
|
|
416
|
-
if (!range) return;
|
|
417
|
-
const source = sliceRange(state.file, range);
|
|
418
|
-
const name = getNodeName(node) ?? state.inferredNames.get(node);
|
|
419
|
-
return {
|
|
420
|
-
file: state.file,
|
|
421
|
-
identity: createRangeIdentity("class", name, range),
|
|
422
|
-
kind: "class",
|
|
423
|
-
language: state.file.language,
|
|
424
|
-
loc: source.loc,
|
|
425
|
-
metadata: { exported: isExportedTarget(node, state) },
|
|
426
|
-
name,
|
|
427
|
-
origin: {
|
|
428
|
-
physicalPath: state.file.path,
|
|
429
|
-
range
|
|
430
|
-
},
|
|
431
|
-
range,
|
|
432
|
-
text: source.text
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
function createFileTarget(file) {
|
|
436
|
-
return {
|
|
437
|
-
file,
|
|
438
|
-
identity: "file",
|
|
439
|
-
kind: "file",
|
|
440
|
-
language: file.language,
|
|
441
|
-
origin: { physicalPath: file.path },
|
|
442
|
-
text: file.text
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
function createFunctionTarget(node, state) {
|
|
446
|
-
const range = getRange(node);
|
|
447
|
-
if (!range) return;
|
|
448
|
-
const source = sliceRange(state.file, range);
|
|
449
|
-
const functionNode = node.type === "MethodDefinition" ? asAstNode(node.value) : node;
|
|
450
|
-
const name = getNodeName(node) ?? getNodeName(functionNode) ?? state.inferredNames.get(node);
|
|
451
|
-
return {
|
|
452
|
-
file: state.file,
|
|
453
|
-
identity: createRangeIdentity("function", name, range),
|
|
454
|
-
kind: "function",
|
|
455
|
-
language: state.file.language,
|
|
456
|
-
loc: source.loc,
|
|
457
|
-
metadata: {
|
|
458
|
-
async: functionNode?.async === true,
|
|
459
|
-
exported: isExportedTarget(node, state)
|
|
460
|
-
},
|
|
461
|
-
name,
|
|
462
|
-
origin: {
|
|
463
|
-
physicalPath: state.file.path,
|
|
464
|
-
range
|
|
465
|
-
},
|
|
466
|
-
range,
|
|
467
|
-
text: source.text
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
function createRangeIdentity(kind, name, range) {
|
|
471
|
-
return `${kind}:${name ?? "anonymous"}:${range.start}:${range.end}`;
|
|
472
|
-
}
|
|
473
|
-
function createSemanticIdentity(target) {
|
|
474
|
-
if (target.kind !== "class" && target.kind !== "function" || !target.name) return;
|
|
475
|
-
return `${target.kind}:${target.name}`;
|
|
476
|
-
}
|
|
477
|
-
function getNodeName(node) {
|
|
478
|
-
if (!node) return;
|
|
479
|
-
if (typeof node.name === "string") return node.name;
|
|
480
|
-
const id = asAstNode(node.id);
|
|
481
|
-
if (typeof id?.name === "string") return id.name;
|
|
482
|
-
const key = asAstNode(node.key);
|
|
483
|
-
if (typeof key?.name === "string") return key.name;
|
|
484
|
-
if (typeof key?.value === "string" || typeof key?.value === "number") return String(key.value);
|
|
485
|
-
}
|
|
486
|
-
function getRange(node) {
|
|
487
|
-
if (typeof node.start === "number" && typeof node.end === "number") return {
|
|
488
|
-
end: node.end,
|
|
489
|
-
start: node.start
|
|
490
|
-
};
|
|
491
|
-
if (Array.isArray(node.range) && node.range.length === 2) return {
|
|
492
|
-
end: node.range[1],
|
|
493
|
-
start: node.range[0]
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
function inferChildName(parent, key, child, state) {
|
|
497
|
-
if (state.inferredNames.has(child)) return;
|
|
498
|
-
if (parent.type === "VariableDeclarator" && key === "init") {
|
|
499
|
-
const id = asAstNode(parent.id);
|
|
500
|
-
if (typeof id?.name === "string") state.inferredNames.set(child, id.name);
|
|
501
|
-
}
|
|
502
|
-
if (parent.type === "Property" && key === "value") {
|
|
503
|
-
const name = getNodeName(parent);
|
|
504
|
-
if (name) state.inferredNames.set(child, name);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
function isAstNode(value) {
|
|
508
|
-
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
509
|
-
}
|
|
510
|
-
function isClassNode(node) {
|
|
511
|
-
return node.type === "ClassDeclaration" || node.type === "ClassExpression";
|
|
512
|
-
}
|
|
513
|
-
function isExportDeclaration(node) {
|
|
514
|
-
return node.type === "ExportDefaultDeclaration" || node.type === "ExportNamedDeclaration";
|
|
515
|
-
}
|
|
516
|
-
function isExportedTarget(node, state) {
|
|
517
|
-
return state.exportedNodes.has(node);
|
|
518
|
-
}
|
|
519
|
-
function isFunctionNode(node) {
|
|
520
|
-
return node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
|
|
521
|
-
}
|
|
522
|
-
function markExportedBinding(name, state) {
|
|
523
|
-
const bindingNode = state.bindingNodes.get(name);
|
|
524
|
-
if (bindingNode) state.exportedNodes.add(bindingNode);
|
|
525
|
-
}
|
|
526
|
-
function markExportedDeclaration(node, state) {
|
|
527
|
-
state.exportedNodes.add(node);
|
|
528
|
-
if (node.type !== "VariableDeclaration" || !Array.isArray(node.declarations)) return;
|
|
529
|
-
for (const declarator of node.declarations) {
|
|
530
|
-
if (!isAstNode(declarator)) continue;
|
|
531
|
-
const initializer = asAstNode(declarator.init);
|
|
532
|
-
if (initializer && (isClassNode(initializer) || isFunctionNode(initializer))) state.exportedNodes.add(initializer);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
function visit(node, state) {
|
|
536
|
-
if (!node) return;
|
|
537
|
-
if (Array.isArray(node)) {
|
|
538
|
-
for (const child of node) visit(child, state);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
if (state.visited.has(node)) return;
|
|
542
|
-
state.visited.add(node);
|
|
543
|
-
if (node.type === "ExportDefaultDeclaration" || node.type === "ExportNamedDeclaration") {
|
|
544
|
-
if (node.declaration) {
|
|
545
|
-
markExportedDeclaration(node.declaration, state);
|
|
546
|
-
visit(node.declaration, state);
|
|
547
|
-
}
|
|
548
|
-
visitChildren(node, state, /* @__PURE__ */ new Set(["declaration"]));
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
if (isClassNode(node)) addClassTarget(node, state);
|
|
552
|
-
else if (isFunctionNode(node) || node.type === "MethodDefinition") {
|
|
553
|
-
addFunctionTarget(node, state);
|
|
554
|
-
const methodValue = node.type === "MethodDefinition" ? asAstNode(node.value) : void 0;
|
|
555
|
-
if (methodValue) state.seenFunctions.add(methodValue);
|
|
556
|
-
}
|
|
557
|
-
visitChildren(node, state);
|
|
558
|
-
}
|
|
559
|
-
function visitChildren(node, state, skippedKeys = /* @__PURE__ */ new Set()) {
|
|
560
|
-
for (const [key, value] of Object.entries(node)) {
|
|
561
|
-
if (skippedKeys.has(key) || key === "type" || key === "start" || key === "end" || key === "range") continue;
|
|
562
|
-
if (Array.isArray(value)) {
|
|
563
|
-
for (const child of value) if (isAstNode(child)) {
|
|
564
|
-
inferChildName(node, key, child, state);
|
|
565
|
-
visit(child, state);
|
|
566
|
-
}
|
|
567
|
-
} else if (isAstNode(value)) {
|
|
568
|
-
inferChildName(node, key, value, state);
|
|
569
|
-
visit(value, state);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
function withStableIdentities(targets) {
|
|
574
|
-
const semanticIdentityCounts = /* @__PURE__ */ new Map();
|
|
575
|
-
for (const target of targets) {
|
|
576
|
-
const semanticIdentity = createSemanticIdentity(target);
|
|
577
|
-
if (semanticIdentity) semanticIdentityCounts.set(semanticIdentity, (semanticIdentityCounts.get(semanticIdentity) ?? 0) + 1);
|
|
578
|
-
}
|
|
579
|
-
return targets.map((target) => {
|
|
580
|
-
const semanticIdentity = createSemanticIdentity(target);
|
|
581
|
-
if (!semanticIdentity || semanticIdentityCounts.get(semanticIdentity) !== 1) return target;
|
|
582
|
-
return {
|
|
583
|
-
...target,
|
|
584
|
-
identity: semanticIdentity
|
|
585
|
-
};
|
|
586
|
-
});
|
|
587
|
-
}
|
|
588
|
-
//#endregion
|
|
589
235
|
//#region src/core/languages/js/index.ts
|
|
590
236
|
const javascriptLanguage = {
|
|
591
237
|
extensions: [
|
|
@@ -934,99 +580,177 @@ function statSyncIsDirectory(path) {
|
|
|
934
580
|
return statSync(path).isDirectory();
|
|
935
581
|
}
|
|
936
582
|
//#endregion
|
|
937
|
-
//#region src/core/targets/directory.ts
|
|
938
|
-
function createDirectoryExecutionPlans(directories, fileOffset) {
|
|
939
|
-
return directories.map((directory, directoryOffset) => {
|
|
940
|
-
const executions = directory.ruleRuntimes.map((runtime) => {
|
|
941
|
-
if (runtime.handlers.onTargetWith) return {
|
|
942
|
-
run: () => runtime.handlers.onTargetWith?.(directory.target),
|
|
943
|
-
runtime
|
|
944
|
-
};
|
|
945
|
-
if (runtime.handlers.onTargetDirectory) return {
|
|
946
|
-
run: () => runtime.handlers.onTargetDirectory?.(directory.target),
|
|
947
|
-
runtime
|
|
948
|
-
};
|
|
949
|
-
}).filter((execution) => execution !== void 0);
|
|
950
|
-
const targets = executions.length === 0 ? [] : [{
|
|
951
|
-
activeFilePath: directory.target.path,
|
|
952
|
-
cacheFilePaths: [],
|
|
953
|
-
configHash: directory.configHash,
|
|
954
|
-
executions,
|
|
955
|
-
identity: directory.target.path,
|
|
956
|
-
kind: "directory",
|
|
957
|
-
language: "directory",
|
|
958
|
-
text: directory.target.path
|
|
959
|
-
}];
|
|
960
|
-
return {
|
|
961
|
-
emitFileProgress: true,
|
|
962
|
-
fileIndex: fileOffset + directoryOffset + 1,
|
|
963
|
-
path: directory.target.path,
|
|
964
|
-
planned: executions.length,
|
|
965
|
-
targets
|
|
966
|
-
};
|
|
967
|
-
});
|
|
968
|
-
}
|
|
969
|
-
//#endregion
|
|
970
583
|
//#region package.json
|
|
971
|
-
var version = "0.0.
|
|
584
|
+
var version = "0.0.30";
|
|
972
585
|
//#endregion
|
|
973
|
-
//#region src/core/
|
|
974
|
-
var
|
|
975
|
-
|
|
976
|
-
constructor(
|
|
977
|
-
|
|
978
|
-
super(message, { cause: error });
|
|
979
|
-
this.name = "AlintRuleExecutionError";
|
|
980
|
-
this.failure = {
|
|
981
|
-
filePath: path.file.path,
|
|
982
|
-
message,
|
|
983
|
-
ruleId: path.rule.id,
|
|
984
|
-
target: {
|
|
985
|
-
kind: path.target.kind,
|
|
986
|
-
name: path.target.name
|
|
987
|
-
}
|
|
988
|
-
};
|
|
586
|
+
//#region src/core/execution/job.ts
|
|
587
|
+
var CacheReplayProcessingError = class {
|
|
588
|
+
cause;
|
|
589
|
+
constructor(cause) {
|
|
590
|
+
this.cause = cause;
|
|
989
591
|
}
|
|
990
592
|
};
|
|
991
|
-
|
|
992
|
-
|
|
593
|
+
function createRuleJobs(plans) {
|
|
594
|
+
const jobs = [];
|
|
595
|
+
const total = plans.reduce((sum, plan) => sum + plan.planned, 0);
|
|
596
|
+
for (const plan of plans) for (const target of plan.targets) for (const execution of target.executions) {
|
|
597
|
+
const ruleId = execution.runtime.enabledRule.id;
|
|
598
|
+
const index = jobs.length + 1;
|
|
599
|
+
jobs.push({
|
|
600
|
+
execution,
|
|
601
|
+
job: {
|
|
602
|
+
id: stableHash({
|
|
603
|
+
index,
|
|
604
|
+
planId: plan.id,
|
|
605
|
+
ruleId,
|
|
606
|
+
targetIdentity: target.identity
|
|
607
|
+
}),
|
|
608
|
+
index,
|
|
609
|
+
inputPath: plan.path,
|
|
610
|
+
ruleId,
|
|
611
|
+
target: {
|
|
612
|
+
identity: target.identity,
|
|
613
|
+
kind: target.kind,
|
|
614
|
+
name: target.name
|
|
615
|
+
},
|
|
616
|
+
total
|
|
617
|
+
},
|
|
618
|
+
target
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
return jobs;
|
|
993
622
|
}
|
|
994
|
-
function
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
623
|
+
async function executeRuleJob(job, options) {
|
|
624
|
+
const bucket = {
|
|
625
|
+
diagnostics: [],
|
|
626
|
+
usage: []
|
|
627
|
+
};
|
|
628
|
+
if (options.runSignal?.aborted) return finish(job, options, bucket, {
|
|
629
|
+
cache: "miss",
|
|
630
|
+
state: "cancelled"
|
|
631
|
+
});
|
|
632
|
+
const cacheKey = createExecutionCacheKey(job, options.cache);
|
|
633
|
+
const cachedEntry = cacheKey ? options.cache.store.get(cacheKey) : void 0;
|
|
634
|
+
if (cacheKey && cachedEntry) {
|
|
635
|
+
rememberCacheEntry(options.cache, job.target.cacheFilePaths, cacheKey);
|
|
636
|
+
try {
|
|
637
|
+
replayCachedEntry(cachedEntry, bucket, job.job, options.progress);
|
|
638
|
+
} catch (error) {
|
|
639
|
+
if (!(error instanceof CacheReplayProcessingError)) throw error;
|
|
640
|
+
return finish(job, options, bucket, {
|
|
641
|
+
cache: "hit",
|
|
642
|
+
cause: error.cause,
|
|
643
|
+
failure: failure(error.cause, job, "cache-replay"),
|
|
644
|
+
state: "failed"
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
return finish(job, options, bucket, {
|
|
648
|
+
cache: "hit",
|
|
649
|
+
state: "cached"
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
if (options.cacheOnly) return finish(job, options, bucket, {
|
|
653
|
+
cache: "miss",
|
|
654
|
+
state: "skipped"
|
|
655
|
+
});
|
|
656
|
+
const controller = new AbortController();
|
|
657
|
+
let timedOut = false;
|
|
658
|
+
let deadlineError;
|
|
659
|
+
const forwardRunAbort = () => controller.abort(options.runSignal?.reason);
|
|
660
|
+
if (options.runSignal?.aborted) forwardRunAbort();
|
|
661
|
+
else options.runSignal?.addEventListener("abort", forwardRunAbort, { once: true });
|
|
662
|
+
const timer = options.timeoutMs == null ? void 0 : setTimeout(() => {
|
|
663
|
+
timedOut = true;
|
|
664
|
+
deadlineError = /* @__PURE__ */ new Error(`Rule execution timed out after ${options.timeoutMs}ms.`);
|
|
665
|
+
controller.abort(deadlineError);
|
|
666
|
+
}, options.timeoutMs);
|
|
667
|
+
const state = {
|
|
668
|
+
activeFilePath: job.target.activeFilePath,
|
|
669
|
+
bucket,
|
|
670
|
+
job: job.job,
|
|
671
|
+
reporterFailed: false,
|
|
672
|
+
signal: controller.signal
|
|
673
|
+
};
|
|
674
|
+
let handlerCause;
|
|
675
|
+
let handlerFailed = false;
|
|
676
|
+
try {
|
|
677
|
+
await job.execution.runtime.executionState.run(state, job.execution.run);
|
|
678
|
+
} catch (cause) {
|
|
679
|
+
if (state.reporterFailed) throw state.reporterCause;
|
|
680
|
+
handlerCause = cause;
|
|
681
|
+
handlerFailed = true;
|
|
682
|
+
} finally {
|
|
683
|
+
if (timer != null) clearTimeout(timer);
|
|
684
|
+
options.runSignal?.removeEventListener("abort", forwardRunAbort);
|
|
685
|
+
}
|
|
686
|
+
if (state.reporterFailed) throw state.reporterCause;
|
|
687
|
+
if (!timedOut && !handlerFailed && cacheKey) try {
|
|
688
|
+
options.cache.store.set(cacheKey, createCacheEntry(job, options.cache, bucket));
|
|
689
|
+
rememberCacheEntry(options.cache, job.target.cacheFilePaths, cacheKey);
|
|
690
|
+
} catch {}
|
|
691
|
+
if (options.runSignal?.aborted) return finish(job, options, bucket, {
|
|
692
|
+
cache: "miss",
|
|
693
|
+
state: "cancelled"
|
|
1006
694
|
});
|
|
695
|
+
if (timedOut) return finish(job, options, bucket, {
|
|
696
|
+
cache: "miss",
|
|
697
|
+
cause: deadlineError,
|
|
698
|
+
failure: failure(deadlineError, job, "timeout"),
|
|
699
|
+
state: "failed"
|
|
700
|
+
});
|
|
701
|
+
if (handlerFailed) return finish(job, options, bucket, {
|
|
702
|
+
cache: "miss",
|
|
703
|
+
cause: handlerCause,
|
|
704
|
+
failure: failure(handlerCause, job, "handler"),
|
|
705
|
+
state: "failed"
|
|
706
|
+
});
|
|
707
|
+
return finish(job, options, bucket, {
|
|
708
|
+
cache: "miss",
|
|
709
|
+
state: "completed"
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
function resolveRuleExecutionTimeout(timeoutMs) {
|
|
713
|
+
if (timeoutMs === void 0) return void 0;
|
|
714
|
+
if (!Number.isFinite(timeoutMs) || !Number.isInteger(timeoutMs) || timeoutMs <= 0) throw new TypeError("Rule execution timeout must be a finite positive integer.");
|
|
715
|
+
return timeoutMs;
|
|
1007
716
|
}
|
|
1008
|
-
function
|
|
717
|
+
function createCacheEntry(job, cache, bucket) {
|
|
1009
718
|
return {
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
id: ruleId,
|
|
1018
|
-
index: entry.ruleIndex,
|
|
1019
|
-
total: entry.ruleTotal
|
|
719
|
+
diagnostics: bucket.diagnostics,
|
|
720
|
+
filePath: normalizeCachePath(cache.cwd, job.job.inputPath),
|
|
721
|
+
fingerprint: {
|
|
722
|
+
alintVersion: version,
|
|
723
|
+
configHash: job.target.configHash,
|
|
724
|
+
modelHash: cache.modelHash,
|
|
725
|
+
ruleHash: job.execution.runtime.ruleHash
|
|
1020
726
|
},
|
|
1021
727
|
target: {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
728
|
+
hash: createTargetHash(job),
|
|
729
|
+
identity: job.target.identity,
|
|
730
|
+
kind: job.target.kind,
|
|
731
|
+
loc: job.target.loc,
|
|
732
|
+
name: job.target.name,
|
|
733
|
+
range: job.target.range
|
|
734
|
+
},
|
|
735
|
+
usage: bucket.usage
|
|
1027
736
|
};
|
|
1028
737
|
}
|
|
1029
|
-
function
|
|
738
|
+
function createExecutionCacheKey(job, cache) {
|
|
739
|
+
if (!cache.enabled || !job.execution.runtime.cacheable || job.target.cacheFilePaths.length === 0) return void 0;
|
|
740
|
+
return createCacheKey({
|
|
741
|
+
alintVersion: version,
|
|
742
|
+
configHash: job.target.configHash,
|
|
743
|
+
filePath: normalizeCachePath(cache.cwd, job.job.inputPath),
|
|
744
|
+
modelHash: cache.modelHash,
|
|
745
|
+
ruleHash: job.execution.runtime.ruleHash,
|
|
746
|
+
schemaVersion: 1,
|
|
747
|
+
targetHash: createTargetHash(job),
|
|
748
|
+
targetIdentity: job.target.identity,
|
|
749
|
+
targetKind: job.target.kind
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
function createTargetHash(job) {
|
|
753
|
+
const target = job.target;
|
|
1030
754
|
return stableHash({
|
|
1031
755
|
language: target.language,
|
|
1032
756
|
loc: target.loc,
|
|
@@ -1037,191 +761,28 @@ function createTargetHash(target) {
|
|
|
1037
761
|
text: target.text
|
|
1038
762
|
});
|
|
1039
763
|
}
|
|
1040
|
-
function
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
startedAt,
|
|
1047
|
-
state: "errored"
|
|
1048
|
-
});
|
|
1049
|
-
} catch {}
|
|
1050
|
-
}
|
|
1051
|
-
async function executeRule(execution, path, target, options) {
|
|
1052
|
-
const { cache, clock, counters, diagnostics, progress, signal, usage } = options;
|
|
1053
|
-
signal?.throwIfAborted();
|
|
1054
|
-
const startedAt = clock();
|
|
1055
|
-
const cacheKey = createExecutionCacheKey(execution.runtime, target, path, cache);
|
|
1056
|
-
const cachedEntry = cacheKey ? cache.store.get(cacheKey) : void 0;
|
|
1057
|
-
progress?.onRuleStart?.({
|
|
1058
|
-
path,
|
|
1059
|
-
startedAt
|
|
1060
|
-
});
|
|
1061
|
-
if (cacheKey && cachedEntry) {
|
|
1062
|
-
rememberCacheEntry(cache, target.cacheFilePaths, cacheKey);
|
|
1063
|
-
try {
|
|
1064
|
-
replayCachedEntry(cachedEntry, path, diagnostics, usage, progress);
|
|
1065
|
-
} catch (error) {
|
|
1066
|
-
counters.error();
|
|
1067
|
-
emitErroredRuleEnd(progress, clock, path, startedAt, "hit");
|
|
1068
|
-
throw new AlintRuleExecutionError(error, path);
|
|
1069
|
-
}
|
|
1070
|
-
counters.cache();
|
|
1071
|
-
progress?.onRuleEnd?.({
|
|
1072
|
-
cache: "hit",
|
|
1073
|
-
endedAt: clock(),
|
|
1074
|
-
path,
|
|
1075
|
-
startedAt,
|
|
1076
|
-
state: "completed"
|
|
1077
|
-
});
|
|
1078
|
-
return;
|
|
1079
|
-
}
|
|
1080
|
-
if (options.cacheOnly) {
|
|
1081
|
-
counters.skip();
|
|
1082
|
-
progress?.onRuleEnd?.({
|
|
1083
|
-
cache: "miss",
|
|
1084
|
-
endedAt: clock(),
|
|
1085
|
-
path,
|
|
1086
|
-
startedAt,
|
|
1087
|
-
state: "skipped"
|
|
1088
|
-
});
|
|
1089
|
-
return;
|
|
1090
|
-
}
|
|
1091
|
-
let handlerError;
|
|
1092
|
-
let handlerFailed = false;
|
|
1093
|
-
const cacheDiagnostics = cacheKey ? [] : void 0;
|
|
1094
|
-
const cacheUsage = cacheKey ? [] : void 0;
|
|
1095
|
-
try {
|
|
1096
|
-
await execution.runtime.executionState.run({
|
|
1097
|
-
activeFilePath: target.activeFilePath,
|
|
1098
|
-
cacheDiagnostics,
|
|
1099
|
-
cacheUsage,
|
|
1100
|
-
progressPath: path
|
|
1101
|
-
}, execution.run);
|
|
1102
|
-
} catch (error) {
|
|
1103
|
-
handlerError = error;
|
|
1104
|
-
handlerFailed = true;
|
|
1105
|
-
}
|
|
1106
|
-
if (handlerFailed) {
|
|
1107
|
-
signal?.throwIfAborted();
|
|
1108
|
-
counters.error();
|
|
1109
|
-
emitErroredRuleEnd(progress, clock, path, startedAt, "miss");
|
|
1110
|
-
throw new AlintRuleExecutionError(handlerError, path);
|
|
1111
|
-
}
|
|
1112
|
-
if (cacheKey) {
|
|
1113
|
-
cache.store.set(cacheKey, {
|
|
1114
|
-
diagnostics: cacheDiagnostics ?? [],
|
|
1115
|
-
filePath: normalizeCachePath(cache.cwd, path.file.path),
|
|
1116
|
-
fingerprint: {
|
|
1117
|
-
alintVersion: version,
|
|
1118
|
-
configHash: target.configHash,
|
|
1119
|
-
modelHash: cache.modelHash,
|
|
1120
|
-
ruleHash: execution.runtime.ruleHash
|
|
1121
|
-
},
|
|
1122
|
-
target: {
|
|
1123
|
-
hash: createTargetHash(target),
|
|
1124
|
-
identity: target.identity,
|
|
1125
|
-
kind: target.kind,
|
|
1126
|
-
loc: target.loc,
|
|
1127
|
-
name: target.name,
|
|
1128
|
-
range: target.range
|
|
1129
|
-
},
|
|
1130
|
-
usage: cacheUsage ?? []
|
|
1131
|
-
});
|
|
1132
|
-
rememberCacheEntry(cache, target.cacheFilePaths, cacheKey);
|
|
1133
|
-
}
|
|
1134
|
-
counters.complete();
|
|
1135
|
-
progress?.onRuleEnd?.({
|
|
1136
|
-
cache: "miss",
|
|
1137
|
-
endedAt: clock(),
|
|
1138
|
-
path,
|
|
1139
|
-
startedAt,
|
|
1140
|
-
state: "completed"
|
|
1141
|
-
});
|
|
764
|
+
function failure(cause, job, kind) {
|
|
765
|
+
return {
|
|
766
|
+
job: job.job,
|
|
767
|
+
kind,
|
|
768
|
+
message: errorMessageFrom(cause) ?? String(cause)
|
|
769
|
+
};
|
|
1142
770
|
}
|
|
1143
|
-
|
|
1144
|
-
const
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
path: plan.path,
|
|
1149
|
-
planned: plan.planned,
|
|
1150
|
-
total: filesTotal
|
|
771
|
+
function finish(job, options, bucket, terminal) {
|
|
772
|
+
const outcome = {
|
|
773
|
+
bucket,
|
|
774
|
+
job,
|
|
775
|
+
...terminal
|
|
1151
776
|
};
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
777
|
+
options.progress?.onJobEnd?.({
|
|
778
|
+
cache: outcome.cache,
|
|
779
|
+
endedAt: options.clock(),
|
|
780
|
+
failure: outcome.failure,
|
|
781
|
+
job: job.job,
|
|
782
|
+
startedAt: options.startedAt,
|
|
783
|
+
state: outcome.state
|
|
1155
784
|
});
|
|
1156
|
-
|
|
1157
|
-
let planFailed = false;
|
|
1158
|
-
try {
|
|
1159
|
-
for (const [targetOffset, target] of plan.targets.entries()) {
|
|
1160
|
-
const targetPath = createProgressPath(plan.path, target.executions[0]?.runtime.enabledRule.id ?? "", {
|
|
1161
|
-
fileIndex: plan.fileIndex,
|
|
1162
|
-
filePlanned: plan.planned,
|
|
1163
|
-
fileTotal: filesTotal,
|
|
1164
|
-
ruleIndex: 1,
|
|
1165
|
-
ruleTotal: target.executions.length,
|
|
1166
|
-
targetIndex: targetOffset + 1,
|
|
1167
|
-
targetKind: target.kind,
|
|
1168
|
-
targetName: target.name,
|
|
1169
|
-
targetTotal: plan.targets.length
|
|
1170
|
-
});
|
|
1171
|
-
const targetStartedAt = clock();
|
|
1172
|
-
progress?.onTargetStart?.({
|
|
1173
|
-
path: targetPath,
|
|
1174
|
-
startedAt: targetStartedAt
|
|
1175
|
-
});
|
|
1176
|
-
let targetError;
|
|
1177
|
-
let targetFailed = false;
|
|
1178
|
-
try {
|
|
1179
|
-
for (const [executionOffset, execution] of target.executions.entries()) await executeRule(execution, createProgressPath(plan.path, execution.runtime.enabledRule.id, {
|
|
1180
|
-
fileIndex: plan.fileIndex,
|
|
1181
|
-
filePlanned: plan.planned,
|
|
1182
|
-
fileTotal: filesTotal,
|
|
1183
|
-
ruleIndex: executionOffset + 1,
|
|
1184
|
-
ruleTotal: target.executions.length,
|
|
1185
|
-
targetIndex: targetOffset + 1,
|
|
1186
|
-
targetKind: target.kind,
|
|
1187
|
-
targetName: target.name,
|
|
1188
|
-
targetTotal: plan.targets.length
|
|
1189
|
-
}), target, options);
|
|
1190
|
-
} catch (error) {
|
|
1191
|
-
targetError = error;
|
|
1192
|
-
targetFailed = true;
|
|
1193
|
-
}
|
|
1194
|
-
try {
|
|
1195
|
-
progress?.onTargetEnd?.({
|
|
1196
|
-
endedAt: clock(),
|
|
1197
|
-
path: targetPath,
|
|
1198
|
-
startedAt: targetStartedAt
|
|
1199
|
-
});
|
|
1200
|
-
} catch (error) {
|
|
1201
|
-
if (!targetFailed) {
|
|
1202
|
-
targetError = error;
|
|
1203
|
-
targetFailed = true;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
if (targetFailed) throw targetError;
|
|
1207
|
-
}
|
|
1208
|
-
} catch (error) {
|
|
1209
|
-
planError = error;
|
|
1210
|
-
planFailed = true;
|
|
1211
|
-
}
|
|
1212
|
-
if (plan.emitFileProgress) try {
|
|
1213
|
-
progress?.onFileEnd?.({
|
|
1214
|
-
endedAt: clock(),
|
|
1215
|
-
file: fileProgress,
|
|
1216
|
-
startedAt: fileStartedAt
|
|
1217
|
-
});
|
|
1218
|
-
} catch (error) {
|
|
1219
|
-
if (!planFailed) {
|
|
1220
|
-
planError = error;
|
|
1221
|
-
planFailed = true;
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
if (planFailed) throw planError;
|
|
785
|
+
return outcome;
|
|
1225
786
|
}
|
|
1226
787
|
function rememberCacheEntry(cache, filePaths, cacheKey) {
|
|
1227
788
|
for (const filePath of filePaths) {
|
|
@@ -1231,29 +792,69 @@ function rememberCacheEntry(cache, filePaths, cacheKey) {
|
|
|
1231
792
|
cache.fileEntryKeys.set(normalizedPath, entries);
|
|
1232
793
|
}
|
|
1233
794
|
}
|
|
1234
|
-
function replayCachedEntry(entry,
|
|
1235
|
-
|
|
795
|
+
function replayCachedEntry(entry, bucket, job, progress) {
|
|
796
|
+
let diagnostics;
|
|
797
|
+
let usage;
|
|
798
|
+
try {
|
|
799
|
+
diagnostics = entry.diagnostics;
|
|
800
|
+
usage = entry.usage;
|
|
801
|
+
} catch (cause) {
|
|
802
|
+
throw new CacheReplayProcessingError(cause);
|
|
803
|
+
}
|
|
804
|
+
for (const cachedDiagnostic of diagnostics) {
|
|
1236
805
|
const diagnostic = {
|
|
1237
806
|
...cachedDiagnostic,
|
|
1238
807
|
cached: true
|
|
1239
808
|
};
|
|
1240
|
-
diagnostics.push(diagnostic);
|
|
809
|
+
bucket.diagnostics.push(diagnostic);
|
|
1241
810
|
progress?.onDiagnostic?.({
|
|
1242
811
|
diagnostic,
|
|
1243
|
-
|
|
1244
|
-
path
|
|
812
|
+
job
|
|
1245
813
|
});
|
|
1246
814
|
}
|
|
1247
|
-
for (const
|
|
1248
|
-
|
|
815
|
+
for (const record of usage) {
|
|
816
|
+
bucket.usage.push(record);
|
|
1249
817
|
progress?.onUsage?.({
|
|
1250
|
-
|
|
1251
|
-
record
|
|
1252
|
-
total: usage.toJSON()
|
|
818
|
+
job,
|
|
819
|
+
record
|
|
1253
820
|
});
|
|
1254
821
|
}
|
|
1255
822
|
}
|
|
1256
823
|
//#endregion
|
|
824
|
+
//#region src/core/targets/directory.ts
|
|
825
|
+
function createDirectoryExecutionPlans(directories, sourcePlanCount) {
|
|
826
|
+
return directories.map((directory, directoryOffset) => {
|
|
827
|
+
const executions = directory.ruleRuntimes.map((runtime) => {
|
|
828
|
+
if (runtime.handlers.onTargetWith) return {
|
|
829
|
+
run: () => runtime.handlers.onTargetWith?.(directory.target),
|
|
830
|
+
runtime
|
|
831
|
+
};
|
|
832
|
+
if (runtime.handlers.onTargetDirectory) return {
|
|
833
|
+
run: () => runtime.handlers.onTargetDirectory?.(directory.target),
|
|
834
|
+
runtime
|
|
835
|
+
};
|
|
836
|
+
}).filter((execution) => execution !== void 0);
|
|
837
|
+
const targets = executions.length === 0 ? [] : [{
|
|
838
|
+
activeFilePath: directory.target.path,
|
|
839
|
+
cacheFilePaths: [],
|
|
840
|
+
configHash: directory.configHash,
|
|
841
|
+
executions,
|
|
842
|
+
identity: directory.target.path,
|
|
843
|
+
kind: "directory",
|
|
844
|
+
language: "directory",
|
|
845
|
+
text: directory.target.path
|
|
846
|
+
}];
|
|
847
|
+
return {
|
|
848
|
+
id: `directory:${directory.target.path}`,
|
|
849
|
+
index: sourcePlanCount + directoryOffset + 1,
|
|
850
|
+
kind: "directory",
|
|
851
|
+
path: directory.target.path,
|
|
852
|
+
planned: executions.length,
|
|
853
|
+
targets
|
|
854
|
+
};
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
//#endregion
|
|
1257
858
|
//#region src/core/targets/project.ts
|
|
1258
859
|
function createProjectExecutionPlan(options) {
|
|
1259
860
|
const project = createProjectTarget(options.root, options.files);
|
|
@@ -1297,8 +898,9 @@ function createProjectExecutionPlan(options) {
|
|
|
1297
898
|
})
|
|
1298
899
|
};
|
|
1299
900
|
return {
|
|
1300
|
-
|
|
1301
|
-
|
|
901
|
+
id: `project:${options.root}`,
|
|
902
|
+
index: options.index,
|
|
903
|
+
kind: "project",
|
|
1302
904
|
path: options.root,
|
|
1303
905
|
planned: executions.length,
|
|
1304
906
|
targets: [target]
|
|
@@ -1333,8 +935,9 @@ function createSourceExecutionPlans(files, cwd) {
|
|
|
1333
935
|
const resolveTargetIdentity = createTargetIdentityResolver(targets.map((target) => toTargetIdentityInput(cwd, preparedFile.file.path, target)));
|
|
1334
936
|
for (const target of targets) target.identity = resolveTargetIdentity(toTargetIdentityInput(cwd, preparedFile.file.path, target));
|
|
1335
937
|
const filePlan = {
|
|
1336
|
-
|
|
1337
|
-
|
|
938
|
+
id: `source:${preparedFile.file.path}`,
|
|
939
|
+
index: fileOffset + 1,
|
|
940
|
+
kind: "source",
|
|
1338
941
|
path: preparedFile.file.path,
|
|
1339
942
|
planned: 0,
|
|
1340
943
|
preparedFile,
|
|
@@ -1401,29 +1004,34 @@ function toTargetIdentityInput(cwd, filePath, target) {
|
|
|
1401
1004
|
}
|
|
1402
1005
|
//#endregion
|
|
1403
1006
|
//#region src/core/run.ts
|
|
1404
|
-
var
|
|
1405
|
-
failure;
|
|
1007
|
+
var AlintRunCancelledError = class extends Error {
|
|
1406
1008
|
result;
|
|
1407
|
-
constructor(
|
|
1408
|
-
super(
|
|
1409
|
-
this.name = "
|
|
1410
|
-
this.failure = options.failure;
|
|
1009
|
+
constructor(result, cause) {
|
|
1010
|
+
super("Alint run cancelled.", { cause });
|
|
1011
|
+
this.name = "AlintRunCancelledError";
|
|
1411
1012
|
this.result = result;
|
|
1412
1013
|
}
|
|
1413
1014
|
};
|
|
1414
|
-
/**
|
|
1415
|
-
|
|
1416
|
-
*
|
|
1417
|
-
* Extends {@link AlintRunError} so existing handlers still receive the partial `result`, while
|
|
1418
|
-
* callers that treat cancellation differently from failure can test for this type.
|
|
1419
|
-
*/
|
|
1420
|
-
var AlintAbortError = class extends AlintRunError {
|
|
1015
|
+
/** Cancellation error carrying the partial result gathered before the abort. */
|
|
1016
|
+
var AlintAbortError = class extends AlintRunCancelledError {
|
|
1421
1017
|
constructor(result, options = {}) {
|
|
1422
|
-
super(
|
|
1018
|
+
super(result, options.cause);
|
|
1423
1019
|
this.name = "AlintAbortError";
|
|
1424
1020
|
}
|
|
1425
1021
|
};
|
|
1022
|
+
var AlintRunError = class extends Error {
|
|
1023
|
+
failures;
|
|
1024
|
+
result;
|
|
1025
|
+
constructor(message, result, options = {}) {
|
|
1026
|
+
super(message, { cause: options.cause });
|
|
1027
|
+
this.name = "AlintRunError";
|
|
1028
|
+
this.failures = options.failures ?? [];
|
|
1029
|
+
this.result = result;
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1426
1032
|
async function runAlint(options = {}) {
|
|
1033
|
+
const timeoutMs = resolveRuleExecutionTimeout(options.runner?.timeoutMs);
|
|
1034
|
+
const concurrency = resolveRuleConcurrency(options.runner?.ruleConcurrency);
|
|
1427
1035
|
const cwd$1 = options.cwd ?? cwd();
|
|
1428
1036
|
const config = options.config ?? [];
|
|
1429
1037
|
const setupConfig = options.setupConfig ?? {
|
|
@@ -1431,8 +1039,6 @@ async function runAlint(options = {}) {
|
|
|
1431
1039
|
version: 1
|
|
1432
1040
|
};
|
|
1433
1041
|
const clock = Date.now;
|
|
1434
|
-
const diagnostics = [];
|
|
1435
|
-
const usage = createUsageAccumulator();
|
|
1436
1042
|
const src = createSourceRuntime();
|
|
1437
1043
|
const normalizedCacheConfig = normalizeRunnerCacheConfig(options.runner?.cache, cwd$1);
|
|
1438
1044
|
const cacheStore = await createCacheStore({
|
|
@@ -1469,14 +1075,13 @@ async function runAlint(options = {}) {
|
|
|
1469
1075
|
const registry = buildRuleRegistry(effectiveConfig);
|
|
1470
1076
|
const ruleRuntimes = createRuleRuntimes({
|
|
1471
1077
|
cwd: cwd$1,
|
|
1472
|
-
diagnostics,
|
|
1473
1078
|
effectiveAgent: effectiveConfig.agent,
|
|
1474
1079
|
effectiveSettings: effectiveConfig.settings,
|
|
1475
1080
|
options,
|
|
1081
|
+
progress: options.progress,
|
|
1476
1082
|
registry,
|
|
1477
1083
|
setupConfig,
|
|
1478
|
-
src
|
|
1479
|
-
usage
|
|
1084
|
+
src
|
|
1480
1085
|
});
|
|
1481
1086
|
return {
|
|
1482
1087
|
configHash: stableHash({
|
|
@@ -1504,14 +1109,13 @@ async function runAlint(options = {}) {
|
|
|
1504
1109
|
configHash: stableHash({ settings: effectiveConfig.settings }),
|
|
1505
1110
|
ruleRuntimes: createRuleRuntimes({
|
|
1506
1111
|
cwd: cwd$1,
|
|
1507
|
-
diagnostics,
|
|
1508
1112
|
effectiveAgent: effectiveConfig.agent,
|
|
1509
1113
|
effectiveSettings: effectiveConfig.settings,
|
|
1510
1114
|
options,
|
|
1115
|
+
progress: options.progress,
|
|
1511
1116
|
registry,
|
|
1512
1117
|
setupConfig,
|
|
1513
|
-
src
|
|
1514
|
-
usage
|
|
1118
|
+
src
|
|
1515
1119
|
}),
|
|
1516
1120
|
target
|
|
1517
1121
|
};
|
|
@@ -1520,181 +1124,146 @@ async function runAlint(options = {}) {
|
|
|
1520
1124
|
const projectConfig = resolvedProjectConfig.config;
|
|
1521
1125
|
const projectRuleRuntimes = resolvedProjectConfig.ignored ? [] : createRuleRuntimes({
|
|
1522
1126
|
cwd: cwd$1,
|
|
1523
|
-
diagnostics,
|
|
1524
1127
|
effectiveAgent: projectConfig.agent,
|
|
1525
1128
|
effectiveSettings: projectConfig.settings,
|
|
1526
1129
|
options,
|
|
1130
|
+
progress: options.progress,
|
|
1527
1131
|
registry: buildRuleRegistry(projectConfig),
|
|
1528
1132
|
setupConfig,
|
|
1529
|
-
src
|
|
1530
|
-
|
|
1133
|
+
src
|
|
1134
|
+
});
|
|
1135
|
+
const filePlans = createSourceExecutionPlans(files, cwd$1);
|
|
1136
|
+
const directoryPlans = createDirectoryExecutionPlans(directories, filePlans.length);
|
|
1137
|
+
const projectPlan = resolvedProjectConfig.ignored ? void 0 : createProjectExecutionPlan({
|
|
1138
|
+
configHash: stableHash({ settings: projectConfig.settings }),
|
|
1139
|
+
files,
|
|
1140
|
+
index: filePlans.length + directoryPlans.length + 1,
|
|
1141
|
+
root: cwd$1,
|
|
1142
|
+
ruleRuntimes: projectRuleRuntimes
|
|
1531
1143
|
});
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1144
|
+
const jobs = createRuleJobs([
|
|
1145
|
+
...filePlans,
|
|
1146
|
+
...directoryPlans,
|
|
1147
|
+
...projectPlan ? [projectPlan] : []
|
|
1148
|
+
]);
|
|
1149
|
+
const runStartedAt = clock();
|
|
1150
|
+
const settledOutcomes = new Array(jobs.length);
|
|
1151
|
+
let infrastructureError;
|
|
1152
|
+
let infrastructureFailed = false;
|
|
1153
|
+
options.progress?.onRunStart?.({
|
|
1154
|
+
jobsTotal: jobs.length,
|
|
1155
|
+
startedAt: runStartedAt
|
|
1156
|
+
});
|
|
1157
|
+
for (const job of jobs) options.progress?.onJobQueued?.({ job: job.job });
|
|
1539
1158
|
try {
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
plans: [directoryPlan],
|
|
1583
|
-
progress: options.progress,
|
|
1584
|
-
signal: options.signal,
|
|
1585
|
-
usage
|
|
1586
|
-
}));
|
|
1587
|
-
if (projectPlan) await executeTargetPlans({
|
|
1588
|
-
cache: cacheContext,
|
|
1589
|
-
cacheOnly: options.cacheOnly,
|
|
1590
|
-
clock,
|
|
1591
|
-
counters,
|
|
1592
|
-
diagnostics,
|
|
1593
|
-
filesTotal: inputsTotal,
|
|
1594
|
-
plans: [projectPlan],
|
|
1595
|
-
progress: options.progress,
|
|
1596
|
-
signal: options.signal,
|
|
1597
|
-
usage
|
|
1598
|
-
});
|
|
1599
|
-
} catch (error) {
|
|
1600
|
-
runError = error;
|
|
1159
|
+
let cursor = 0;
|
|
1160
|
+
const worker = async () => {
|
|
1161
|
+
while (cursor < jobs.length) {
|
|
1162
|
+
const index = cursor;
|
|
1163
|
+
cursor += 1;
|
|
1164
|
+
const job = jobs[index];
|
|
1165
|
+
if (options.signal?.aborted) {
|
|
1166
|
+
settledOutcomes[index] = {
|
|
1167
|
+
bucket: {
|
|
1168
|
+
diagnostics: [],
|
|
1169
|
+
usage: []
|
|
1170
|
+
},
|
|
1171
|
+
cache: "miss",
|
|
1172
|
+
job,
|
|
1173
|
+
state: "cancelled"
|
|
1174
|
+
};
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
try {
|
|
1178
|
+
const startedAt = clock();
|
|
1179
|
+
options.progress?.onJobStart?.({
|
|
1180
|
+
job: job.job,
|
|
1181
|
+
startedAt
|
|
1182
|
+
});
|
|
1183
|
+
settledOutcomes[index] = await executeRuleJob(job, {
|
|
1184
|
+
cache: cacheContext,
|
|
1185
|
+
cacheOnly: options.cacheOnly,
|
|
1186
|
+
clock,
|
|
1187
|
+
progress: options.progress,
|
|
1188
|
+
runSignal: options.signal,
|
|
1189
|
+
startedAt,
|
|
1190
|
+
timeoutMs
|
|
1191
|
+
});
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
if (!infrastructureFailed) {
|
|
1194
|
+
infrastructureError = error;
|
|
1195
|
+
infrastructureFailed = true;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, jobs.length) }, worker));
|
|
1601
1201
|
} finally {
|
|
1602
1202
|
if (!options.cacheOnly) await reconcileCache(filePlans, cacheContext);
|
|
1603
|
-
try {
|
|
1604
|
-
options.progress?.onRunEnd?.({
|
|
1605
|
-
...counters.snapshot(planned),
|
|
1606
|
-
diagnostics,
|
|
1607
|
-
endedAt: clock(),
|
|
1608
|
-
startedAt: runStartedAt ?? clock(),
|
|
1609
|
-
usage: usage.toJSON()
|
|
1610
|
-
});
|
|
1611
|
-
} catch (error) {
|
|
1612
|
-
runError ??= error;
|
|
1613
|
-
}
|
|
1614
1203
|
}
|
|
1204
|
+
const outcomes = Array.from({ length: jobs.length }, (_, index) => settledOutcomes[index] ?? {
|
|
1205
|
+
bucket: {
|
|
1206
|
+
diagnostics: [],
|
|
1207
|
+
usage: []
|
|
1208
|
+
},
|
|
1209
|
+
cache: "miss",
|
|
1210
|
+
job: jobs[index],
|
|
1211
|
+
state: "cancelled"
|
|
1212
|
+
});
|
|
1213
|
+
const failedOutcomes = outcomes.filter((outcome) => outcome.state === "failed");
|
|
1214
|
+
const failures = failedOutcomes.map((outcome) => outcome.failure);
|
|
1615
1215
|
const result = {
|
|
1616
|
-
diagnostics,
|
|
1617
|
-
execution:
|
|
1618
|
-
usage:
|
|
1216
|
+
diagnostics: outcomes.flatMap((outcome) => outcome.bucket.diagnostics),
|
|
1217
|
+
execution: executionCounts(outcomes),
|
|
1218
|
+
usage: runUsage(outcomes)
|
|
1619
1219
|
};
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
function addTokenCount(base, value) {
|
|
1627
|
-
return typeof value === "number" && Number.isFinite(value) ? base + value : base;
|
|
1628
|
-
}
|
|
1629
|
-
function calculatePlannedExecutions(filePlans) {
|
|
1630
|
-
return filePlans.reduce((total, filePlan) => total + filePlan.planned, 0);
|
|
1631
|
-
}
|
|
1632
|
-
function countEnabledRuleIds(files, directories, projectRuleRuntimes) {
|
|
1633
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1634
|
-
for (const file of files) for (const runtime of file.ruleRuntimes) ids.add(runtime.enabledRule.id);
|
|
1635
|
-
for (const directory of directories) for (const runtime of directory.ruleRuntimes) ids.add(runtime.enabledRule.id);
|
|
1636
|
-
for (const runtime of projectRuleRuntimes) ids.add(runtime.enabledRule.id);
|
|
1637
|
-
return ids.size;
|
|
1638
|
-
}
|
|
1639
|
-
function createAlintRunError(error, result) {
|
|
1640
|
-
if (error instanceof AlintRunError) return error;
|
|
1641
|
-
if (error instanceof AlintRuleExecutionError) return new AlintRunError(error.message, result, {
|
|
1642
|
-
cause: errorCauseFrom(error),
|
|
1643
|
-
failure: error.failure
|
|
1220
|
+
options.progress?.onRunEnd?.({
|
|
1221
|
+
diagnostics: result.diagnostics,
|
|
1222
|
+
endedAt: clock(),
|
|
1223
|
+
execution: result.execution,
|
|
1224
|
+
startedAt: runStartedAt,
|
|
1225
|
+
usage: result.usage
|
|
1644
1226
|
});
|
|
1645
|
-
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
return {
|
|
1653
|
-
cache() {
|
|
1654
|
-
cached += 1;
|
|
1655
|
-
},
|
|
1656
|
-
complete() {
|
|
1657
|
-
completed += 1;
|
|
1658
|
-
},
|
|
1659
|
-
error() {
|
|
1660
|
-
errored += 1;
|
|
1661
|
-
},
|
|
1662
|
-
skip() {
|
|
1663
|
-
skipped += 1;
|
|
1664
|
-
},
|
|
1665
|
-
snapshot(planned) {
|
|
1666
|
-
return {
|
|
1667
|
-
cached,
|
|
1668
|
-
completed,
|
|
1669
|
-
errored,
|
|
1670
|
-
planned,
|
|
1671
|
-
skipped
|
|
1672
|
-
};
|
|
1673
|
-
}
|
|
1674
|
-
};
|
|
1227
|
+
if (infrastructureFailed) throw infrastructureError;
|
|
1228
|
+
if (options.signal?.aborted) throw new AlintAbortError(result, { cause: options.signal.reason });
|
|
1229
|
+
if (failures.length > 0) throw new AlintRunError(`${failures.length} rule execution${failures.length === 1 ? "" : "s"} failed.`, result, {
|
|
1230
|
+
cause: new AggregateError(failedOutcomes.map((outcome) => outcome.cause), "Rule execution failures."),
|
|
1231
|
+
failures
|
|
1232
|
+
});
|
|
1233
|
+
return result;
|
|
1675
1234
|
}
|
|
1676
1235
|
function createRuleRuntimes(options) {
|
|
1677
|
-
const agent = options.effectiveAgent ? withAgentRetry(options.effectiveAgent, options.options.runner?.agentRetries) : void 0;
|
|
1678
1236
|
return options.registry.enabledRules.map((enabledRule) => {
|
|
1679
1237
|
const executionState = new AsyncLocalStorage();
|
|
1680
1238
|
const context = {
|
|
1681
|
-
agent
|
|
1239
|
+
agent: options.effectiveAgent ? withAgentRetry((request) => options.effectiveAgent({
|
|
1240
|
+
...request,
|
|
1241
|
+
signal: combineAbortSignals(executionState.getStore()?.signal, request.signal)
|
|
1242
|
+
}), options.options.runner?.agentRetries) : void 0,
|
|
1682
1243
|
cwd: options.cwd,
|
|
1683
1244
|
id: enabledRule.id,
|
|
1684
1245
|
localId: enabledRule.localId,
|
|
1685
1246
|
logger: { debug: () => {} },
|
|
1686
1247
|
metering: { recordUsage: (record) => {
|
|
1687
|
-
const
|
|
1248
|
+
const state = executionState.getStore();
|
|
1249
|
+
if (!state) throw new Error("Cannot record usage outside an active rule job.");
|
|
1250
|
+
const usageRecord = {
|
|
1688
1251
|
...record,
|
|
1689
1252
|
ruleId: record.ruleId ?? enabledRule.id
|
|
1690
|
-
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
})
|
|
1253
|
+
};
|
|
1254
|
+
state.bucket.usage.push(usageRecord);
|
|
1255
|
+
try {
|
|
1256
|
+
options.progress?.onUsage?.({
|
|
1257
|
+
job: state.job,
|
|
1258
|
+
record: usageRecord
|
|
1259
|
+
});
|
|
1260
|
+
} catch (cause) {
|
|
1261
|
+
if (!state.reporterFailed) {
|
|
1262
|
+
state.reporterCause = cause;
|
|
1263
|
+
state.reporterFailed = true;
|
|
1264
|
+
}
|
|
1265
|
+
throw cause;
|
|
1266
|
+
}
|
|
1698
1267
|
} },
|
|
1699
1268
|
model: async (selector) => {
|
|
1700
1269
|
const request = options.options.modelOverride ?? (typeof selector === "string" ? selector : void 0);
|
|
@@ -1711,10 +1280,11 @@ function createRuleRuntimes(options) {
|
|
|
1711
1280
|
outputLanguage: options.options.outputLanguage,
|
|
1712
1281
|
report: (descriptor) => {
|
|
1713
1282
|
const state = executionState.getStore();
|
|
1714
|
-
|
|
1283
|
+
if (!state) throw new Error("Cannot report a diagnostic outside an active rule job.");
|
|
1284
|
+
const filePath = descriptor.filePath ?? state.activeFilePath;
|
|
1715
1285
|
if (!filePath) throw new Error(`Diagnostic for rule "${enabledRule.id}" is missing filePath.`);
|
|
1716
|
-
const diagnosticModel = state
|
|
1717
|
-
|
|
1286
|
+
const diagnosticModel = state.currentModel ? { ...state.currentModel } : void 0;
|
|
1287
|
+
state.currentModel = void 0;
|
|
1718
1288
|
const diagnostic = {
|
|
1719
1289
|
evidence: descriptor.evidence,
|
|
1720
1290
|
filePath,
|
|
@@ -1724,16 +1294,24 @@ function createRuleRuntimes(options) {
|
|
|
1724
1294
|
ruleId: enabledRule.id,
|
|
1725
1295
|
severity: enabledRule.severity
|
|
1726
1296
|
};
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
})
|
|
1297
|
+
state.bucket.diagnostics.push(diagnostic);
|
|
1298
|
+
try {
|
|
1299
|
+
options.progress?.onDiagnostic?.({
|
|
1300
|
+
diagnostic,
|
|
1301
|
+
job: state.job
|
|
1302
|
+
});
|
|
1303
|
+
} catch (cause) {
|
|
1304
|
+
if (!state.reporterFailed) {
|
|
1305
|
+
state.reporterCause = cause;
|
|
1306
|
+
state.reporterFailed = true;
|
|
1307
|
+
}
|
|
1308
|
+
throw cause;
|
|
1309
|
+
}
|
|
1734
1310
|
},
|
|
1735
1311
|
settings: options.effectiveSettings,
|
|
1736
|
-
signal
|
|
1312
|
+
get signal() {
|
|
1313
|
+
return executionState.getStore()?.signal;
|
|
1314
|
+
},
|
|
1737
1315
|
src: options.src
|
|
1738
1316
|
};
|
|
1739
1317
|
return {
|
|
@@ -1753,47 +1331,19 @@ function createRuleRuntimes(options) {
|
|
|
1753
1331
|
};
|
|
1754
1332
|
});
|
|
1755
1333
|
}
|
|
1756
|
-
function
|
|
1757
|
-
const
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
toJSON() {
|
|
1767
|
-
const cachedUsage = cached.toJSON();
|
|
1768
|
-
return {
|
|
1769
|
-
...live.toJSON(),
|
|
1770
|
-
...cachedUsage.records.length > 0 ? { cached: cachedUsage } : {}
|
|
1771
|
-
};
|
|
1772
|
-
}
|
|
1773
|
-
};
|
|
1774
|
-
}
|
|
1775
|
-
function createUsageTotals() {
|
|
1776
|
-
const records = [];
|
|
1777
|
-
let inputTokens = 0;
|
|
1778
|
-
let outputTokens = 0;
|
|
1779
|
-
let totalTokens = 0;
|
|
1780
|
-
return {
|
|
1781
|
-
record(record) {
|
|
1782
|
-
records.push(record);
|
|
1783
|
-
inputTokens = addTokenCount(inputTokens, record.inputTokens);
|
|
1784
|
-
outputTokens = addTokenCount(outputTokens, record.outputTokens);
|
|
1785
|
-
totalTokens = addTokenCount(totalTokens, record.totalTokens);
|
|
1786
|
-
return record;
|
|
1787
|
-
},
|
|
1788
|
-
toJSON() {
|
|
1789
|
-
return {
|
|
1790
|
-
inputTokens,
|
|
1791
|
-
outputTokens,
|
|
1792
|
-
records,
|
|
1793
|
-
totalTokens
|
|
1794
|
-
};
|
|
1795
|
-
}
|
|
1334
|
+
function executionCounts(outcomes) {
|
|
1335
|
+
const counts = {
|
|
1336
|
+
cached: 0,
|
|
1337
|
+
cancelled: 0,
|
|
1338
|
+
completed: 0,
|
|
1339
|
+
failed: 0,
|
|
1340
|
+
planned: outcomes.length,
|
|
1341
|
+
queued: 0,
|
|
1342
|
+
running: 0,
|
|
1343
|
+
skipped: 0
|
|
1796
1344
|
};
|
|
1345
|
+
for (const outcome of outcomes) counts[outcome.state] += 1;
|
|
1346
|
+
return counts;
|
|
1797
1347
|
}
|
|
1798
1348
|
function mergeCapabilities(base, extra) {
|
|
1799
1349
|
if (!base && !extra) return;
|
|
@@ -1829,28 +1379,19 @@ async function reconcileCache(filePlans, cacheContext) {
|
|
|
1829
1379
|
await cacheContext.store.reconcile();
|
|
1830
1380
|
} catch {}
|
|
1831
1381
|
}
|
|
1832
|
-
function
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
const
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
await runItem(items[currentIndex]);
|
|
1846
|
-
} catch (error) {
|
|
1847
|
-
firstError ??= error;
|
|
1848
|
-
return;
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
}
|
|
1852
|
-
await Promise.all(Array.from({ length: workerCount }, () => runWorker()));
|
|
1853
|
-
if (firstError !== void 0) throw firstError;
|
|
1382
|
+
function resolveRuleConcurrency(ruleConcurrency) {
|
|
1383
|
+
if (ruleConcurrency === void 0) return 4;
|
|
1384
|
+
if (!Number.isFinite(ruleConcurrency) || !Number.isInteger(ruleConcurrency) || ruleConcurrency <= 0) throw new TypeError("Rule execution concurrency must be a finite positive integer.");
|
|
1385
|
+
return ruleConcurrency;
|
|
1386
|
+
}
|
|
1387
|
+
function runUsage(outcomes) {
|
|
1388
|
+
const live = [];
|
|
1389
|
+
const cached = [];
|
|
1390
|
+
for (const outcome of outcomes) (outcome.state === "cached" ? cached : live).push(...outcome.bucket.usage);
|
|
1391
|
+
return {
|
|
1392
|
+
...usageTotals(live),
|
|
1393
|
+
...cached.length > 0 ? { cached: usageTotals(cached) } : {}
|
|
1394
|
+
};
|
|
1854
1395
|
}
|
|
1855
1396
|
function toDiagnosticModel(model, request) {
|
|
1856
1397
|
return {
|
|
@@ -1859,12 +1400,20 @@ function toDiagnosticModel(model, request) {
|
|
|
1859
1400
|
resolvedId: model.id
|
|
1860
1401
|
};
|
|
1861
1402
|
}
|
|
1862
|
-
function
|
|
1403
|
+
function usageTotals(records) {
|
|
1404
|
+
let inputTokens = 0;
|
|
1405
|
+
let outputTokens = 0;
|
|
1406
|
+
let totalTokens = 0;
|
|
1407
|
+
for (const record of records) {
|
|
1408
|
+
if (record.inputTokens != null && Number.isFinite(record.inputTokens)) inputTokens += record.inputTokens;
|
|
1409
|
+
if (record.outputTokens != null && Number.isFinite(record.outputTokens)) outputTokens += record.outputTokens;
|
|
1410
|
+
if (record.totalTokens != null && Number.isFinite(record.totalTokens)) totalTokens += record.totalTokens;
|
|
1411
|
+
}
|
|
1863
1412
|
return {
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1413
|
+
inputTokens,
|
|
1414
|
+
outputTokens,
|
|
1415
|
+
records: [...records],
|
|
1416
|
+
totalTokens
|
|
1868
1417
|
};
|
|
1869
1418
|
}
|
|
1870
1419
|
//#endregion
|
|
@@ -1879,4 +1428,4 @@ function defineRule(rule) {
|
|
|
1879
1428
|
return rule;
|
|
1880
1429
|
}
|
|
1881
1430
|
//#endregion
|
|
1882
|
-
export { AlintRunError, buildRuleRegistry, createBuiltInLanguageRegistry, createSourceFile, createSourceRuntime, defineConfig, definePlugin, defineRule,
|
|
1431
|
+
export { AlintAbortError, AlintRunCancelledError, AlintRunError, buildRuleRegistry, createBuiltInLanguageRegistry, createSourceFile, createSourceRuntime, defineConfig, definePlugin, defineRule, hasDiscoveryFilePatterns, matchesDiscoveryFile, normalizeConfig, registerLanguage, resolveConfigForDirectory, resolveConfigForFile, resolveConfigForProject, resolveLanguage, resolveModel, runAlint, sliceLines, sliceRange };
|