truecourse 0.6.6 → 0.6.7-next.1
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/cli.mjs +1324 -288
- package/package.json +1 -1
- package/server.mjs +1343 -315
package/server.mjs
CHANGED
|
@@ -19092,13 +19092,13 @@ var require_broadcast_operator = __commonJS({
|
|
|
19092
19092
|
* @return a Promise that will be fulfilled when all clients have acknowledged the event
|
|
19093
19093
|
*/
|
|
19094
19094
|
emitWithAck(ev, ...args) {
|
|
19095
|
-
return new Promise((
|
|
19095
|
+
return new Promise((resolve9, reject) => {
|
|
19096
19096
|
args.push((err, responses) => {
|
|
19097
19097
|
if (err) {
|
|
19098
19098
|
err.responses = responses;
|
|
19099
19099
|
return reject(err);
|
|
19100
19100
|
} else {
|
|
19101
|
-
return
|
|
19101
|
+
return resolve9(responses);
|
|
19102
19102
|
}
|
|
19103
19103
|
});
|
|
19104
19104
|
this.emit(ev, ...args);
|
|
@@ -19452,12 +19452,12 @@ var require_socket2 = __commonJS({
|
|
|
19452
19452
|
*/
|
|
19453
19453
|
emitWithAck(ev, ...args) {
|
|
19454
19454
|
const withErr = this.flags.timeout !== void 0;
|
|
19455
|
-
return new Promise((
|
|
19455
|
+
return new Promise((resolve9, reject) => {
|
|
19456
19456
|
args.push((arg1, arg2) => {
|
|
19457
19457
|
if (withErr) {
|
|
19458
|
-
return arg1 ? reject(arg1) :
|
|
19458
|
+
return arg1 ? reject(arg1) : resolve9(arg2);
|
|
19459
19459
|
} else {
|
|
19460
|
-
return
|
|
19460
|
+
return resolve9(arg1);
|
|
19461
19461
|
}
|
|
19462
19462
|
});
|
|
19463
19463
|
this.emit(ev, ...args);
|
|
@@ -20527,13 +20527,13 @@ var require_namespace = __commonJS({
|
|
|
20527
20527
|
* @return a Promise that will be fulfilled when all servers have acknowledged the event
|
|
20528
20528
|
*/
|
|
20529
20529
|
serverSideEmitWithAck(ev, ...args) {
|
|
20530
|
-
return new Promise((
|
|
20530
|
+
return new Promise((resolve9, reject) => {
|
|
20531
20531
|
args.push((err, responses) => {
|
|
20532
20532
|
if (err) {
|
|
20533
20533
|
err.responses = responses;
|
|
20534
20534
|
return reject(err);
|
|
20535
20535
|
} else {
|
|
20536
|
-
return
|
|
20536
|
+
return resolve9(responses);
|
|
20537
20537
|
}
|
|
20538
20538
|
});
|
|
20539
20539
|
this.serverSideEmit(ev, ...args);
|
|
@@ -21494,7 +21494,7 @@ var require_cluster_adapter = __commonJS({
|
|
|
21494
21494
|
return localSockets;
|
|
21495
21495
|
}
|
|
21496
21496
|
const requestId = randomId();
|
|
21497
|
-
return new Promise((
|
|
21497
|
+
return new Promise((resolve9, reject) => {
|
|
21498
21498
|
const timeout = setTimeout(() => {
|
|
21499
21499
|
const storedRequest2 = this.requests.get(requestId);
|
|
21500
21500
|
if (storedRequest2) {
|
|
@@ -21504,7 +21504,7 @@ var require_cluster_adapter = __commonJS({
|
|
|
21504
21504
|
}, opts.flags.timeout || DEFAULT_TIMEOUT);
|
|
21505
21505
|
const storedRequest = {
|
|
21506
21506
|
type: MessageType.FETCH_SOCKETS,
|
|
21507
|
-
resolve:
|
|
21507
|
+
resolve: resolve9,
|
|
21508
21508
|
timeout,
|
|
21509
21509
|
current: 0,
|
|
21510
21510
|
expected: expectedResponseCount,
|
|
@@ -21715,7 +21715,7 @@ var require_cluster_adapter = __commonJS({
|
|
|
21715
21715
|
return localSockets;
|
|
21716
21716
|
}
|
|
21717
21717
|
const requestId = randomId();
|
|
21718
|
-
return new Promise((
|
|
21718
|
+
return new Promise((resolve9, reject) => {
|
|
21719
21719
|
const timeout = setTimeout(() => {
|
|
21720
21720
|
const storedRequest2 = this.customRequests.get(requestId);
|
|
21721
21721
|
if (storedRequest2) {
|
|
@@ -21725,7 +21725,7 @@ var require_cluster_adapter = __commonJS({
|
|
|
21725
21725
|
}, opts.flags.timeout || DEFAULT_TIMEOUT);
|
|
21726
21726
|
const storedRequest = {
|
|
21727
21727
|
type: MessageType.FETCH_SOCKETS,
|
|
21728
|
-
resolve:
|
|
21728
|
+
resolve: resolve9,
|
|
21729
21729
|
timeout,
|
|
21730
21730
|
missingUids: /* @__PURE__ */ new Set([...this.nodesMap.keys()]),
|
|
21731
21731
|
responses: localSockets
|
|
@@ -22552,13 +22552,13 @@ var require_dist2 = __commonJS({
|
|
|
22552
22552
|
this.engine.close();
|
|
22553
22553
|
(0, uws_1.restoreAdapter)();
|
|
22554
22554
|
if (this.httpServer) {
|
|
22555
|
-
return new Promise((
|
|
22555
|
+
return new Promise((resolve9) => {
|
|
22556
22556
|
this.httpServer.close((err) => {
|
|
22557
22557
|
fn && fn(err);
|
|
22558
22558
|
if (err) {
|
|
22559
22559
|
debug2("server was not running");
|
|
22560
22560
|
}
|
|
22561
|
-
|
|
22561
|
+
resolve9();
|
|
22562
22562
|
});
|
|
22563
22563
|
});
|
|
22564
22564
|
} else {
|
|
@@ -22914,7 +22914,7 @@ function popLogger() {
|
|
|
22914
22914
|
async function closeLogger() {
|
|
22915
22915
|
while (stack.length > 0) {
|
|
22916
22916
|
const sink = stack.pop();
|
|
22917
|
-
await new Promise((
|
|
22917
|
+
await new Promise((resolve9) => sink.stream.end(resolve9));
|
|
22918
22918
|
}
|
|
22919
22919
|
}
|
|
22920
22920
|
function currentSink() {
|
|
@@ -28154,6 +28154,12 @@ function loadTcIgnore(startDir) {
|
|
|
28154
28154
|
if (rel === "" || rel.startsWith(".."))
|
|
28155
28155
|
return false;
|
|
28156
28156
|
return ig.ignores(rel);
|
|
28157
|
+
},
|
|
28158
|
+
reincludes(absPath) {
|
|
28159
|
+
const rel = path3.relative(root, path3.resolve(absPath)).split(path3.sep).join("/");
|
|
28160
|
+
if (rel === "" || rel.startsWith(".."))
|
|
28161
|
+
return false;
|
|
28162
|
+
return ig.test(rel).unignored;
|
|
28157
28163
|
}
|
|
28158
28164
|
};
|
|
28159
28165
|
}
|
|
@@ -33100,10 +33106,10 @@ var require_raw_body = __commonJS({
|
|
|
33100
33106
|
if (done) {
|
|
33101
33107
|
return readStream(stream, encoding, length, limit, wrap(done));
|
|
33102
33108
|
}
|
|
33103
|
-
return new Promise(function executor(
|
|
33109
|
+
return new Promise(function executor(resolve9, reject) {
|
|
33104
33110
|
readStream(stream, encoding, length, limit, function onRead(err, buf) {
|
|
33105
33111
|
if (err) return reject(err);
|
|
33106
|
-
|
|
33112
|
+
resolve9(buf);
|
|
33107
33113
|
});
|
|
33108
33114
|
});
|
|
33109
33115
|
}
|
|
@@ -37941,7 +37947,7 @@ var require_view = __commonJS({
|
|
|
37941
37947
|
var basename2 = path52.basename;
|
|
37942
37948
|
var extname = path52.extname;
|
|
37943
37949
|
var join9 = path52.join;
|
|
37944
|
-
var
|
|
37950
|
+
var resolve9 = path52.resolve;
|
|
37945
37951
|
module.exports = View;
|
|
37946
37952
|
function View(name, options) {
|
|
37947
37953
|
var opts = options || {};
|
|
@@ -37975,7 +37981,7 @@ var require_view = __commonJS({
|
|
|
37975
37981
|
debug2('lookup "%s"', name);
|
|
37976
37982
|
for (var i = 0; i < roots.length && !path53; i++) {
|
|
37977
37983
|
var root = roots[i];
|
|
37978
|
-
var loc =
|
|
37984
|
+
var loc = resolve9(root, name);
|
|
37979
37985
|
var dir = dirname8(loc);
|
|
37980
37986
|
var file = basename2(loc);
|
|
37981
37987
|
path53 = this.resolve(dir, file);
|
|
@@ -37986,7 +37992,7 @@ var require_view = __commonJS({
|
|
|
37986
37992
|
debug2('render "%s"', this.path);
|
|
37987
37993
|
this.engine(this.path, options, callback);
|
|
37988
37994
|
};
|
|
37989
|
-
View.prototype.resolve = function
|
|
37995
|
+
View.prototype.resolve = function resolve10(dir, file) {
|
|
37990
37996
|
var ext2 = this.ext;
|
|
37991
37997
|
var path53 = join9(dir, file);
|
|
37992
37998
|
var stat = tryStat(path53);
|
|
@@ -38512,7 +38518,7 @@ var require_send = __commonJS({
|
|
|
38512
38518
|
var extname = path52.extname;
|
|
38513
38519
|
var join9 = path52.join;
|
|
38514
38520
|
var normalize2 = path52.normalize;
|
|
38515
|
-
var
|
|
38521
|
+
var resolve9 = path52.resolve;
|
|
38516
38522
|
var sep3 = path52.sep;
|
|
38517
38523
|
var BYTES_RANGE_REGEXP = /^ *bytes=/;
|
|
38518
38524
|
var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
|
|
@@ -38549,7 +38555,7 @@ var require_send = __commonJS({
|
|
|
38549
38555
|
this._maxage = opts.maxAge || opts.maxage;
|
|
38550
38556
|
this._maxage = typeof this._maxage === "string" ? ms(this._maxage) : Number(this._maxage);
|
|
38551
38557
|
this._maxage = !isNaN(this._maxage) ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) : 0;
|
|
38552
|
-
this._root = opts.root ?
|
|
38558
|
+
this._root = opts.root ? resolve9(opts.root) : null;
|
|
38553
38559
|
if (!this._root && opts.from) {
|
|
38554
38560
|
this.from(opts.from);
|
|
38555
38561
|
}
|
|
@@ -38573,7 +38579,7 @@ var require_send = __commonJS({
|
|
|
38573
38579
|
return this;
|
|
38574
38580
|
}, "send.index: pass index as option");
|
|
38575
38581
|
SendStream.prototype.root = function root(path53) {
|
|
38576
|
-
this._root =
|
|
38582
|
+
this._root = resolve9(String(path53));
|
|
38577
38583
|
debug2("root %s", this._root);
|
|
38578
38584
|
return this;
|
|
38579
38585
|
};
|
|
@@ -38737,7 +38743,7 @@ var require_send = __commonJS({
|
|
|
38737
38743
|
return res;
|
|
38738
38744
|
}
|
|
38739
38745
|
parts = normalize2(path53).split(sep3);
|
|
38740
|
-
path53 =
|
|
38746
|
+
path53 = resolve9(path53);
|
|
38741
38747
|
}
|
|
38742
38748
|
if (containsDotFile(parts)) {
|
|
38743
38749
|
var access = this._dotfiles;
|
|
@@ -40016,7 +40022,7 @@ var require_application = __commonJS({
|
|
|
40016
40022
|
var deprecate = require_depd()("express");
|
|
40017
40023
|
var flatten = require_array_flatten();
|
|
40018
40024
|
var merge = require_utils_merge();
|
|
40019
|
-
var
|
|
40025
|
+
var resolve9 = __require("path").resolve;
|
|
40020
40026
|
var setPrototypeOf = require_setprototypeof();
|
|
40021
40027
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
40022
40028
|
var slice3 = Array.prototype.slice;
|
|
@@ -40055,7 +40061,7 @@ var require_application = __commonJS({
|
|
|
40055
40061
|
this.mountpath = "/";
|
|
40056
40062
|
this.locals.settings = this.settings;
|
|
40057
40063
|
this.set("view", View);
|
|
40058
|
-
this.set("views",
|
|
40064
|
+
this.set("views", resolve9("views"));
|
|
40059
40065
|
this.set("jsonp callback name", "callback");
|
|
40060
40066
|
if (env === "production") {
|
|
40061
40067
|
this.enable("view cache");
|
|
@@ -40483,7 +40489,7 @@ var require_response = __commonJS({
|
|
|
40483
40489
|
var send = require_send();
|
|
40484
40490
|
var extname = path52.extname;
|
|
40485
40491
|
var mime = send.mime;
|
|
40486
|
-
var
|
|
40492
|
+
var resolve9 = path52.resolve;
|
|
40487
40493
|
var vary = require_vary();
|
|
40488
40494
|
var res = Object.create(http.ServerResponse.prototype);
|
|
40489
40495
|
module.exports = res;
|
|
@@ -40742,7 +40748,7 @@ var require_response = __commonJS({
|
|
|
40742
40748
|
}
|
|
40743
40749
|
opts = Object.create(opts);
|
|
40744
40750
|
opts.headers = headers;
|
|
40745
|
-
var fullPath = !opts.root ?
|
|
40751
|
+
var fullPath = !opts.root ? resolve9(path53) : path53;
|
|
40746
40752
|
return this.sendFile(fullPath, opts, done);
|
|
40747
40753
|
};
|
|
40748
40754
|
res.contentType = res.type = function contentType(type) {
|
|
@@ -41008,7 +41014,7 @@ var require_serve_static = __commonJS({
|
|
|
41008
41014
|
var encodeUrl = require_encodeurl();
|
|
41009
41015
|
var escapeHtml = require_escape_html();
|
|
41010
41016
|
var parseUrl = require_parseurl();
|
|
41011
|
-
var
|
|
41017
|
+
var resolve9 = __require("path").resolve;
|
|
41012
41018
|
var send = require_send();
|
|
41013
41019
|
var url = __require("url");
|
|
41014
41020
|
module.exports = serveStatic;
|
|
@@ -41028,7 +41034,7 @@ var require_serve_static = __commonJS({
|
|
|
41028
41034
|
throw new TypeError("option setHeaders must be function");
|
|
41029
41035
|
}
|
|
41030
41036
|
opts.maxage = opts.maxage || opts.maxAge || 0;
|
|
41031
|
-
opts.root =
|
|
41037
|
+
opts.root = resolve9(root);
|
|
41032
41038
|
var onDirectory = redirect ? createRedirectDirectoryListener() : createNotFoundDirectoryListener();
|
|
41033
41039
|
return function serveStatic2(req, res, next) {
|
|
41034
41040
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
@@ -41762,6 +41768,14 @@ function parseFile(filePath, code, language) {
|
|
|
41762
41768
|
throw new Error(`Failed to parse file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
41763
41769
|
}
|
|
41764
41770
|
}
|
|
41771
|
+
function withParsedTree(filePath, code, language, use) {
|
|
41772
|
+
const tree = parseFile(filePath, code, language);
|
|
41773
|
+
try {
|
|
41774
|
+
return use(tree);
|
|
41775
|
+
} finally {
|
|
41776
|
+
tree.delete();
|
|
41777
|
+
}
|
|
41778
|
+
}
|
|
41765
41779
|
var _require, BUNDLED_WASM_DIR, GRAMMAR_WASM, languageCache, parserCache, initPromise, initialized;
|
|
41766
41780
|
var init_parser = __esm({
|
|
41767
41781
|
"packages/analyzer/dist/parser.js"() {
|
|
@@ -44621,53 +44635,15 @@ async function analyzeFile(filePath) {
|
|
|
44621
44635
|
}
|
|
44622
44636
|
try {
|
|
44623
44637
|
const content = await readFile(filePath, "utf-8");
|
|
44624
|
-
|
|
44625
|
-
let functions, classes, imports, exports;
|
|
44626
|
-
switch (language) {
|
|
44627
|
-
case "typescript":
|
|
44628
|
-
case "tsx":
|
|
44629
|
-
functions = extractTypeScriptFunctions(tree, filePath, language);
|
|
44630
|
-
classes = extractTypeScriptClasses(tree, filePath, language);
|
|
44631
|
-
imports = extractTypeScriptImports(tree, filePath, language);
|
|
44632
|
-
exports = extractTypeScriptExports(tree, filePath, language);
|
|
44633
|
-
break;
|
|
44634
|
-
case "javascript":
|
|
44635
|
-
functions = extractJavaScriptFunctions(tree, filePath);
|
|
44636
|
-
classes = extractJavaScriptClasses(tree, filePath);
|
|
44637
|
-
imports = extractJavaScriptImports(tree, filePath);
|
|
44638
|
-
exports = extractJavaScriptExports(tree, filePath);
|
|
44639
|
-
break;
|
|
44640
|
-
case "python":
|
|
44641
|
-
functions = extractPythonFunctions(tree, filePath);
|
|
44642
|
-
classes = extractPythonClasses(tree, filePath);
|
|
44643
|
-
imports = extractPythonImports(tree, filePath);
|
|
44644
|
-
exports = extractPythonExports(tree, filePath);
|
|
44645
|
-
break;
|
|
44646
|
-
default:
|
|
44647
|
-
throw new Error(`Unsupported language: ${language}`);
|
|
44648
|
-
}
|
|
44649
|
-
const functionContext = buildFunctionContext(functions, classes);
|
|
44650
|
-
const calls = extractCalls(tree, filePath, language, functionContext);
|
|
44651
|
-
const httpCalls = extractHttpCalls(tree, filePath, language, functions, classes);
|
|
44652
|
-
const { routes: routeRegistrations, mounts: routerMounts } = extractRouteRegistrations(tree, filePath, language);
|
|
44653
|
-
return {
|
|
44654
|
-
filePath,
|
|
44655
|
-
language,
|
|
44656
|
-
functions,
|
|
44657
|
-
classes,
|
|
44658
|
-
imports,
|
|
44659
|
-
exports,
|
|
44660
|
-
calls,
|
|
44661
|
-
httpCalls,
|
|
44662
|
-
...routeRegistrations.length > 0 ? { routeRegistrations } : {},
|
|
44663
|
-
...routerMounts.length > 0 ? { routerMounts } : {}
|
|
44664
|
-
};
|
|
44638
|
+
return withParsedTree(filePath, content, language, (tree) => buildFileAnalysis(tree, filePath, language));
|
|
44665
44639
|
} catch (error) {
|
|
44666
44640
|
throw new Error(`Failed to analyze file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
44667
44641
|
}
|
|
44668
44642
|
}
|
|
44669
44643
|
function analyzeFileContent(filePath, content, language) {
|
|
44670
|
-
|
|
44644
|
+
return withParsedTree(filePath, content, language, (tree) => buildFileAnalysis(tree, filePath, language));
|
|
44645
|
+
}
|
|
44646
|
+
function buildFileAnalysis(tree, filePath, language) {
|
|
44671
44647
|
let functions, classes, imports, exports;
|
|
44672
44648
|
switch (language) {
|
|
44673
44649
|
case "typescript":
|
|
@@ -44683,6 +44659,12 @@ function analyzeFileContent(filePath, content, language) {
|
|
|
44683
44659
|
imports = extractJavaScriptImports(tree, filePath);
|
|
44684
44660
|
exports = extractJavaScriptExports(tree, filePath);
|
|
44685
44661
|
break;
|
|
44662
|
+
case "python":
|
|
44663
|
+
functions = extractPythonFunctions(tree, filePath);
|
|
44664
|
+
classes = extractPythonClasses(tree, filePath);
|
|
44665
|
+
imports = extractPythonImports(tree, filePath);
|
|
44666
|
+
exports = extractPythonExports(tree, filePath);
|
|
44667
|
+
break;
|
|
44686
44668
|
default:
|
|
44687
44669
|
throw new Error(`Unsupported language: ${language}`);
|
|
44688
44670
|
}
|
|
@@ -49398,11 +49380,6 @@ var init_entities = __esm({
|
|
|
49398
49380
|
init_patterns();
|
|
49399
49381
|
init_parser();
|
|
49400
49382
|
TypeScriptEntityDetector = class {
|
|
49401
|
-
// Lazy: do not call getParser() at construction time — callers may
|
|
49402
|
-
// instantiate this before initParsers() has completed.
|
|
49403
|
-
get parser() {
|
|
49404
|
-
return getParser("typescript");
|
|
49405
|
-
}
|
|
49406
49383
|
shouldScanFile(filePath) {
|
|
49407
49384
|
if (!/\.(ts|tsx|js|jsx)$/.test(filePath)) {
|
|
49408
49385
|
return false;
|
|
@@ -49417,25 +49394,24 @@ var init_entities = __esm({
|
|
|
49417
49394
|
return hasEntityDir || hasEntityPattern;
|
|
49418
49395
|
}
|
|
49419
49396
|
detectEntities(sourceCode, filePath, service) {
|
|
49420
|
-
|
|
49421
|
-
|
|
49422
|
-
|
|
49423
|
-
|
|
49424
|
-
|
|
49425
|
-
|
|
49426
|
-
|
|
49427
|
-
|
|
49428
|
-
entities.push(entity);
|
|
49397
|
+
return withParsedTree(filePath, sourceCode, "typescript", (tree) => {
|
|
49398
|
+
const entities = [];
|
|
49399
|
+
const classNodes = this.findClassDeclarations(tree.rootNode);
|
|
49400
|
+
for (const classNode of classNodes) {
|
|
49401
|
+
const entity = this.detectEntityFromClass(classNode, sourceCode, filePath, service);
|
|
49402
|
+
if (entity) {
|
|
49403
|
+
entities.push(entity);
|
|
49404
|
+
}
|
|
49429
49405
|
}
|
|
49430
|
-
|
|
49431
|
-
|
|
49432
|
-
|
|
49433
|
-
|
|
49434
|
-
|
|
49435
|
-
|
|
49406
|
+
const interfaceNodes = this.findInterfaceDeclarations(tree.rootNode);
|
|
49407
|
+
for (const interfaceNode of interfaceNodes) {
|
|
49408
|
+
const entity = this.detectEntityFromInterface(interfaceNode, sourceCode, filePath, service);
|
|
49409
|
+
if (entity) {
|
|
49410
|
+
entities.push(entity);
|
|
49411
|
+
}
|
|
49436
49412
|
}
|
|
49437
|
-
|
|
49438
|
-
|
|
49413
|
+
return entities;
|
|
49414
|
+
});
|
|
49439
49415
|
}
|
|
49440
49416
|
findClassDeclarations(node2) {
|
|
49441
49417
|
const classes = [];
|
|
@@ -49803,14 +49779,14 @@ var init_lsp_client = __esm({
|
|
|
49803
49779
|
this.sendNotification("exit", null);
|
|
49804
49780
|
} catch {
|
|
49805
49781
|
}
|
|
49806
|
-
await new Promise((
|
|
49782
|
+
await new Promise((resolve9) => {
|
|
49807
49783
|
const timeout = setTimeout(() => {
|
|
49808
49784
|
this.process?.kill("SIGKILL");
|
|
49809
|
-
|
|
49785
|
+
resolve9();
|
|
49810
49786
|
}, 2e3);
|
|
49811
49787
|
this.process.on("exit", () => {
|
|
49812
49788
|
clearTimeout(timeout);
|
|
49813
|
-
|
|
49789
|
+
resolve9();
|
|
49814
49790
|
});
|
|
49815
49791
|
});
|
|
49816
49792
|
this.process = null;
|
|
@@ -49953,9 +49929,9 @@ var init_lsp_client = __esm({
|
|
|
49953
49929
|
// Internal: JSON-RPC transport
|
|
49954
49930
|
// -------------------------------------------------------------------------
|
|
49955
49931
|
sendRequest(method, params) {
|
|
49956
|
-
return new Promise((
|
|
49932
|
+
return new Promise((resolve9, reject) => {
|
|
49957
49933
|
const id = ++this.requestId;
|
|
49958
|
-
this.pendingRequests.set(id, { resolve:
|
|
49934
|
+
this.pendingRequests.set(id, { resolve: resolve9, reject });
|
|
49959
49935
|
const msg = { jsonrpc: "2.0", id, method, params };
|
|
49960
49936
|
this.process.stdin.write(encodeMessage(msg));
|
|
49961
49937
|
});
|
|
@@ -50012,7 +49988,7 @@ var init_lsp_client = __esm({
|
|
|
50012
49988
|
*/
|
|
50013
49989
|
waitForDiagnostics(fileCount) {
|
|
50014
49990
|
const waitMs = Math.min(Math.max(fileCount * 100, 1e3), 1e4);
|
|
50015
|
-
return new Promise((
|
|
49991
|
+
return new Promise((resolve9) => setTimeout(resolve9, waitMs));
|
|
50016
49992
|
}
|
|
50017
49993
|
};
|
|
50018
49994
|
}
|
|
@@ -78018,6 +77994,9 @@ var init_no_self_compare = __esm({
|
|
|
78018
77994
|
});
|
|
78019
77995
|
|
|
78020
77996
|
// packages/analyzer/dist/rules/bugs/visitors/javascript/duplicate-class-members.js
|
|
77997
|
+
function reportDuplicate(ruleKey, child, filePath, sourceCode, name) {
|
|
77998
|
+
return makeViolation(ruleKey, child, filePath, "high", "Duplicate class member", `Member \`${name}\` is defined more than once \u2014 the later definition silently overwrites the earlier one.`, sourceCode, "Remove the duplicate member or rename one of them.");
|
|
77999
|
+
}
|
|
78021
78000
|
var duplicateClassMembersVisitor;
|
|
78022
78001
|
var init_duplicate_class_members = __esm({
|
|
78023
78002
|
"packages/analyzer/dist/rules/bugs/visitors/javascript/duplicate-class-members.js"() {
|
|
@@ -78031,18 +78010,37 @@ var init_duplicate_class_members = __esm({
|
|
|
78031
78010
|
visit(node2, filePath, sourceCode) {
|
|
78032
78011
|
const seen = /* @__PURE__ */ new Map();
|
|
78033
78012
|
for (const child of node2.namedChildren) {
|
|
78034
|
-
|
|
78035
|
-
|
|
78036
|
-
|
|
78037
|
-
|
|
78038
|
-
|
|
78013
|
+
if (child.type !== "method_definition" && child.type !== "public_field_definition" && child.type !== "field_definition")
|
|
78014
|
+
continue;
|
|
78015
|
+
const nameNode = child.childForFieldName("name");
|
|
78016
|
+
if (!nameNode)
|
|
78017
|
+
continue;
|
|
78018
|
+
const name = nameNode.text;
|
|
78019
|
+
let isStatic = false;
|
|
78020
|
+
let accessor = null;
|
|
78021
|
+
for (let i = 0; i < child.childCount; i++) {
|
|
78022
|
+
const c = child.child(i);
|
|
78023
|
+
if (!c)
|
|
78024
|
+
continue;
|
|
78025
|
+
if (c.type === "static")
|
|
78026
|
+
isStatic = true;
|
|
78027
|
+
else if (c.type === "get")
|
|
78028
|
+
accessor = "get";
|
|
78029
|
+
else if (c.type === "set")
|
|
78030
|
+
accessor = "set";
|
|
78031
|
+
}
|
|
78032
|
+
const kind = accessor ?? (child.type === "method_definition" ? "method" : "field");
|
|
78033
|
+
const key2 = `${isStatic ? "static" : "instance"}:${name}`;
|
|
78034
|
+
const existing = seen.get(key2);
|
|
78035
|
+
if (!existing) {
|
|
78036
|
+
seen.set(key2, { kinds: /* @__PURE__ */ new Set([kind]) });
|
|
78037
|
+
continue;
|
|
78039
78038
|
}
|
|
78040
|
-
|
|
78041
|
-
|
|
78042
|
-
|
|
78043
|
-
}
|
|
78044
|
-
seen.set(name, child);
|
|
78039
|
+
const isGetSetPair = existing.kinds.size === 1 && existing.kinds.has("get") && kind === "set" || existing.kinds.size === 1 && existing.kinds.has("set") && kind === "get";
|
|
78040
|
+
if (!isGetSetPair) {
|
|
78041
|
+
return reportDuplicate(this.ruleKey, child, filePath, sourceCode, name);
|
|
78045
78042
|
}
|
|
78043
|
+
existing.kinds.add(kind);
|
|
78046
78044
|
}
|
|
78047
78045
|
return null;
|
|
78048
78046
|
}
|
|
@@ -80389,7 +80387,9 @@ var init_element_overwrite = __esm({
|
|
|
80389
80387
|
hasAwait2 = true;
|
|
80390
80388
|
}
|
|
80391
80389
|
const isRefCurrent = left.type === "member_expression" && indexOrProp.text === "current";
|
|
80392
|
-
|
|
80390
|
+
const right = expr.childForFieldName("right");
|
|
80391
|
+
const readsSelfInRhs = right ? right.text.includes(left.text) : false;
|
|
80392
|
+
if (!wasRead && !readsSelfInRhs && !(isRefCurrent && hasAwait2)) {
|
|
80393
80393
|
return makeViolation(this.ruleKey, expr, filePath, "high", "Element overwritten before read", `\`${key2}\` is assigned again before being read \u2014 the first assignment has no effect.`, sourceCode, "Remove the first assignment or use the value before overwriting it.");
|
|
80394
80394
|
}
|
|
80395
80395
|
}
|
|
@@ -81753,6 +81753,17 @@ var init_promise_executor_return = __esm({
|
|
|
81753
81753
|
});
|
|
81754
81754
|
|
|
81755
81755
|
// packages/analyzer/dist/rules/bugs/visitors/javascript/empty-pattern.js
|
|
81756
|
+
function isFunctionParameter(node2) {
|
|
81757
|
+
const parent = node2.parent;
|
|
81758
|
+
if (!parent)
|
|
81759
|
+
return false;
|
|
81760
|
+
if (parent.type === "formal_parameters")
|
|
81761
|
+
return true;
|
|
81762
|
+
if (parent.type === "required_parameter" || parent.type === "optional_parameter") {
|
|
81763
|
+
return parent.parent?.type === "formal_parameters";
|
|
81764
|
+
}
|
|
81765
|
+
return false;
|
|
81766
|
+
}
|
|
81756
81767
|
var emptyPatternVisitor;
|
|
81757
81768
|
var init_empty_pattern = __esm({
|
|
81758
81769
|
"packages/analyzer/dist/rules/bugs/visitors/javascript/empty-pattern.js"() {
|
|
@@ -81766,6 +81777,8 @@ var init_empty_pattern = __esm({
|
|
|
81766
81777
|
visit(node2, filePath, sourceCode) {
|
|
81767
81778
|
const bindings = node2.namedChildren.filter((c) => c.type !== "comment");
|
|
81768
81779
|
if (bindings.length === 0) {
|
|
81780
|
+
if (node2.type === "object_pattern" && isFunctionParameter(node2))
|
|
81781
|
+
return null;
|
|
81769
81782
|
const kind = node2.type === "object_pattern" ? "{}" : "[]";
|
|
81770
81783
|
return makeViolation(this.ruleKey, node2, filePath, "medium", "Empty destructuring pattern", `Empty destructuring pattern \`${kind}\` does not bind any variables.`, sourceCode, "Add variable bindings to the destructuring pattern or remove it entirely.");
|
|
81771
81784
|
}
|
|
@@ -83317,6 +83330,15 @@ var init_contradictory_non_null_coalescing = __esm({
|
|
|
83317
83330
|
});
|
|
83318
83331
|
|
|
83319
83332
|
// packages/analyzer/dist/rules/bugs/visitors/javascript/empty-object-type.js
|
|
83333
|
+
function isReactPropsParameter(typeAnnotation, filePath) {
|
|
83334
|
+
if (!/\.(tsx|jsx)$/i.test(filePath))
|
|
83335
|
+
return false;
|
|
83336
|
+
const param = typeAnnotation.parent;
|
|
83337
|
+
if (param?.type !== "required_parameter" && param?.type !== "optional_parameter")
|
|
83338
|
+
return false;
|
|
83339
|
+
const pattern = param.childForFieldName("pattern");
|
|
83340
|
+
return pattern?.text === "props";
|
|
83341
|
+
}
|
|
83320
83342
|
var emptyObjectTypeVisitor;
|
|
83321
83343
|
var init_empty_object_type = __esm({
|
|
83322
83344
|
"packages/analyzer/dist/rules/bugs/visitors/javascript/empty-object-type.js"() {
|
|
@@ -83341,7 +83363,7 @@ var init_empty_object_type = __esm({
|
|
|
83341
83363
|
};
|
|
83342
83364
|
if (node2.type === "type_annotation") {
|
|
83343
83365
|
const emptyObj = checkForEmptyObject(node2);
|
|
83344
|
-
if (emptyObj) {
|
|
83366
|
+
if (emptyObj && !isReactPropsParameter(node2, filePath)) {
|
|
83345
83367
|
return makeViolation(this.ruleKey, emptyObj, filePath, "high", "Empty object type {}", "`{}` type matches everything except `null` and `undefined` \u2014 this is rarely intentional. Use `object` for non-primitive objects or `Record<string, unknown>` for generic objects.", sourceCode, "Replace `{}` with `object`, `Record<string, unknown>`, or a specific type.");
|
|
83346
83368
|
}
|
|
83347
83369
|
}
|
|
@@ -99934,6 +99956,12 @@ var init_prefer_immediate_return = __esm({
|
|
|
99934
99956
|
const nameNode = decl.childForFieldName("name");
|
|
99935
99957
|
if (nameNode?.text !== retName)
|
|
99936
99958
|
return null;
|
|
99959
|
+
const valueNode = decl.childForFieldName("value");
|
|
99960
|
+
if (valueNode) {
|
|
99961
|
+
const lineSpan = valueNode.endPosition.row - valueNode.startPosition.row + 1;
|
|
99962
|
+
if (lineSpan > 10)
|
|
99963
|
+
return null;
|
|
99964
|
+
}
|
|
99937
99965
|
let usageCount = 0;
|
|
99938
99966
|
function countUsages2(n) {
|
|
99939
99967
|
if (n.type === "identifier" && n.text === retName) {
|
|
@@ -102079,6 +102107,14 @@ function isDirectCallbackArg(fn) {
|
|
|
102079
102107
|
p = p.parent;
|
|
102080
102108
|
return p?.type === "arguments" ? p : null;
|
|
102081
102109
|
}
|
|
102110
|
+
function isTrivialCallback(fn) {
|
|
102111
|
+
const body = fn.childForFieldName("body");
|
|
102112
|
+
if (!body)
|
|
102113
|
+
return false;
|
|
102114
|
+
if (body.type !== "statement_block")
|
|
102115
|
+
return true;
|
|
102116
|
+
return body.namedChildren.length === 0;
|
|
102117
|
+
}
|
|
102082
102118
|
function findEnclosingFn(start) {
|
|
102083
102119
|
let n = start;
|
|
102084
102120
|
while (n) {
|
|
@@ -102100,6 +102136,8 @@ var init_deep_callback_nesting = __esm({
|
|
|
102100
102136
|
languages: ["typescript", "tsx", "javascript"],
|
|
102101
102137
|
nodeTypes: ["function_expression", "arrow_function"],
|
|
102102
102138
|
visit(node2, filePath, sourceCode) {
|
|
102139
|
+
if (isTrivialCallback(node2))
|
|
102140
|
+
return null;
|
|
102103
102141
|
let depth = 0;
|
|
102104
102142
|
let current = node2;
|
|
102105
102143
|
while (true) {
|
|
@@ -102218,6 +102256,10 @@ var init_default_parameter_position = __esm({
|
|
|
102218
102256
|
const isOptional = param.type === "optional_parameter" || param.text.includes("?");
|
|
102219
102257
|
if (isOptional)
|
|
102220
102258
|
continue;
|
|
102259
|
+
const patternNode = param.childForFieldName("pattern") ?? param.namedChildren[0];
|
|
102260
|
+
const isDestructured = param.type === "object_pattern" || param.type === "array_pattern" || patternNode?.type === "object_pattern" || patternNode?.type === "array_pattern";
|
|
102261
|
+
if (isDestructured)
|
|
102262
|
+
continue;
|
|
102221
102263
|
const nameNode = param.childForFieldName("pattern") ?? param.childForFieldName("name") ?? param.namedChildren[0];
|
|
102222
102264
|
const name = nameNode?.text ?? "parameter";
|
|
102223
102265
|
return makeViolation(this.ruleKey, param, filePath, "low", "Default parameter not last", `Required parameter \`${name}\` appears after a default parameter. Default parameters should come last.`, sourceCode, "Move default parameters to the end of the parameter list.");
|
|
@@ -102963,7 +103005,8 @@ var init_public_static_readonly = __esm({
|
|
|
102963
103005
|
const isStatic = member.children.some((c) => c.type === "static");
|
|
102964
103006
|
const isPublic = !member.children.some((c) => c.type === "accessibility_modifier" && (c.text === "private" || c.text === "protected"));
|
|
102965
103007
|
const isReadonly = member.children.some((c) => c.type === "readonly");
|
|
102966
|
-
|
|
103008
|
+
const hasInitializer = member.childForFieldName("value") != null;
|
|
103009
|
+
if (isStatic && isPublic && !isReadonly && hasInitializer) {
|
|
102967
103010
|
const nameNode = member.childForFieldName("name");
|
|
102968
103011
|
const name = nameNode?.text ?? "field";
|
|
102969
103012
|
return makeViolation(this.ruleKey, member, filePath, "medium", "Mutable public static field", `Public static field \`${name}\` is not \`readonly\`. Static public fields that are constants should be readonly.`, sourceCode, `Add the \`readonly\` modifier: \`public static readonly ${name}\`.`);
|
|
@@ -108414,11 +108457,18 @@ var init_confusing_void_expression = __esm({
|
|
|
108414
108457
|
}
|
|
108415
108458
|
parent = parent.parent;
|
|
108416
108459
|
}
|
|
108417
|
-
|
|
108460
|
+
const isContainingFnVoid = () => {
|
|
108461
|
+
if (!containingFn)
|
|
108462
|
+
return false;
|
|
108418
108463
|
const fnReturnType = typeQuery.getReturnType(filePath, containingFn.startPosition.row, containingFn.startPosition.column, containingFn.endPosition.row, containingFn.endPosition.column);
|
|
108419
|
-
|
|
108464
|
+
return !!fnReturnType && /^(void|undefined|Promise<\s*(void|undefined)\s*>)$/.test(fnReturnType);
|
|
108465
|
+
};
|
|
108466
|
+
if (containingFn?.type === "arrow_function") {
|
|
108467
|
+
if (isContainingFnVoid())
|
|
108468
|
+
return null;
|
|
108469
|
+
} else if (value.type === "await_expression" && (containingFn?.type === "function_declaration" || containingFn?.type === "function_expression" || containingFn?.type === "method_definition" || containingFn?.type === "function")) {
|
|
108470
|
+
if (isContainingFnVoid())
|
|
108420
108471
|
return null;
|
|
108421
|
-
}
|
|
108422
108472
|
}
|
|
108423
108473
|
return makeViolation(this.ruleKey, node2, filePath, "low", "Returning void expression", `Returning a void expression \u2014 \`${value.text.slice(0, 40)}\` returns \`undefined\`. This is confusing because it looks like the return value matters.`, sourceCode, "Put the expression on its own line and use a bare `return` statement.");
|
|
108424
108474
|
}
|
|
@@ -108604,6 +108654,32 @@ var init_unnecessary_type_parameter = __esm({
|
|
|
108604
108654
|
});
|
|
108605
108655
|
|
|
108606
108656
|
// packages/analyzer/dist/rules/code-quality/visitors/javascript/prefer-this-return-type.js
|
|
108657
|
+
function collectMethodReturns(body) {
|
|
108658
|
+
const returns = [];
|
|
108659
|
+
const NESTED_SCOPES = /* @__PURE__ */ new Set([
|
|
108660
|
+
"function_declaration",
|
|
108661
|
+
"function_expression",
|
|
108662
|
+
"function",
|
|
108663
|
+
"arrow_function",
|
|
108664
|
+
"generator_function",
|
|
108665
|
+
"generator_function_declaration",
|
|
108666
|
+
"method_definition",
|
|
108667
|
+
"class_declaration",
|
|
108668
|
+
"class"
|
|
108669
|
+
]);
|
|
108670
|
+
const walk11 = (n) => {
|
|
108671
|
+
for (const child of n.namedChildren) {
|
|
108672
|
+
if (child.type === "return_statement") {
|
|
108673
|
+
returns.push(child);
|
|
108674
|
+
}
|
|
108675
|
+
if (!NESTED_SCOPES.has(child.type)) {
|
|
108676
|
+
walk11(child);
|
|
108677
|
+
}
|
|
108678
|
+
}
|
|
108679
|
+
};
|
|
108680
|
+
walk11(body);
|
|
108681
|
+
return returns;
|
|
108682
|
+
}
|
|
108607
108683
|
function findEnclosingClass(node2) {
|
|
108608
108684
|
let current = node2.parent;
|
|
108609
108685
|
while (current) {
|
|
@@ -108656,6 +108732,23 @@ var init_prefer_this_return_type = __esm({
|
|
|
108656
108732
|
if (!typeText)
|
|
108657
108733
|
return null;
|
|
108658
108734
|
if (typeText === className) {
|
|
108735
|
+
const body = node2.childForFieldName("body");
|
|
108736
|
+
if (!body)
|
|
108737
|
+
return null;
|
|
108738
|
+
const returns = collectMethodReturns(body);
|
|
108739
|
+
if (returns.length === 0)
|
|
108740
|
+
return null;
|
|
108741
|
+
let returnsThis = false;
|
|
108742
|
+
for (const ret of returns) {
|
|
108743
|
+
const arg = ret.namedChildren[0];
|
|
108744
|
+
if (arg && arg.type === "this") {
|
|
108745
|
+
returnsThis = true;
|
|
108746
|
+
} else {
|
|
108747
|
+
return null;
|
|
108748
|
+
}
|
|
108749
|
+
}
|
|
108750
|
+
if (!returnsThis)
|
|
108751
|
+
return null;
|
|
108659
108752
|
return makeViolation(this.ruleKey, returnTypeNode, filePath, "low", "Method should return `this` instead of class name", `Method \`${methodName}\` returns \`${className}\` but should return \`this\` to support subclass chaining.`, sourceCode, `Change the return type from \`${className}\` to \`this\`.`);
|
|
108660
108753
|
}
|
|
108661
108754
|
return null;
|
|
@@ -122403,12 +122496,32 @@ var init_regex_in_loop = __esm({
|
|
|
122403
122496
|
});
|
|
122404
122497
|
|
|
122405
122498
|
// packages/analyzer/dist/rules/performance/visitors/javascript/spread-in-reduce.js
|
|
122406
|
-
function
|
|
122407
|
-
if (
|
|
122408
|
-
return
|
|
122499
|
+
function getAccumulatorName(callback) {
|
|
122500
|
+
if (callback.type !== "arrow_function" && callback.type !== "function_expression" && callback.type !== "function") {
|
|
122501
|
+
return null;
|
|
122502
|
+
}
|
|
122503
|
+
const params = callback.childForFieldName("parameters");
|
|
122504
|
+
if (!params)
|
|
122505
|
+
return null;
|
|
122506
|
+
const first2 = params.namedChildren.find((c) => c.type !== "comment");
|
|
122507
|
+
if (!first2)
|
|
122508
|
+
return null;
|
|
122509
|
+
if (first2.type === "identifier")
|
|
122510
|
+
return first2.text;
|
|
122511
|
+
const pattern = first2.childForFieldName("pattern");
|
|
122512
|
+
if (pattern && pattern.type === "identifier")
|
|
122513
|
+
return pattern.text;
|
|
122514
|
+
return null;
|
|
122515
|
+
}
|
|
122516
|
+
function spreadsIdentifier(node2, name) {
|
|
122517
|
+
if (node2.type === "spread_element") {
|
|
122518
|
+
const arg = node2.namedChildren[0];
|
|
122519
|
+
if (arg && arg.type === "identifier" && arg.text === name)
|
|
122520
|
+
return true;
|
|
122521
|
+
}
|
|
122409
122522
|
for (let i = 0; i < node2.childCount; i++) {
|
|
122410
122523
|
const child = node2.child(i);
|
|
122411
|
-
if (child &&
|
|
122524
|
+
if (child && spreadsIdentifier(child, name))
|
|
122412
122525
|
return true;
|
|
122413
122526
|
}
|
|
122414
122527
|
return false;
|
|
@@ -122435,7 +122548,10 @@ var init_spread_in_reduce = __esm({
|
|
|
122435
122548
|
const callback = args.namedChildren[0];
|
|
122436
122549
|
if (!callback)
|
|
122437
122550
|
return null;
|
|
122438
|
-
|
|
122551
|
+
const accName = getAccumulatorName(callback);
|
|
122552
|
+
if (!accName)
|
|
122553
|
+
return null;
|
|
122554
|
+
if (spreadsIdentifier(callback, accName)) {
|
|
122439
122555
|
return makeViolation(this.ruleKey, node2, filePath, "medium", "Spread operator in reduce callback", "Using spread in a reduce callback creates a new copy on every iteration, resulting in O(n^2) time complexity.", sourceCode, "Use Object.assign() or direct mutation of the accumulator instead of spread.");
|
|
122440
122556
|
}
|
|
122441
122557
|
return null;
|
|
@@ -122505,6 +122621,8 @@ var init_sync_fs_in_request_handler = __esm({
|
|
|
122505
122621
|
return null;
|
|
122506
122622
|
if (SEED_FILE_PATH_PATTERN2.test(filePath))
|
|
122507
122623
|
return null;
|
|
122624
|
+
if (sourceCode.startsWith("#!"))
|
|
122625
|
+
return null;
|
|
122508
122626
|
if (!isInsideAsyncFunctionOrHandler(node2))
|
|
122509
122627
|
return null;
|
|
122510
122628
|
const enclosingName = findEnclosingFunctionName(node2);
|
|
@@ -122685,6 +122803,100 @@ var init_large_bundle_import = __esm({
|
|
|
122685
122803
|
});
|
|
122686
122804
|
|
|
122687
122805
|
// packages/analyzer/dist/rules/performance/visitors/javascript/json-parse-in-loop.js
|
|
122806
|
+
function isDynamicPerIteration(arg, callNode) {
|
|
122807
|
+
switch (arg.type) {
|
|
122808
|
+
case "parenthesized_expression": {
|
|
122809
|
+
const inner = arg.namedChildren[0];
|
|
122810
|
+
return inner ? isDynamicPerIteration(inner, callNode) : false;
|
|
122811
|
+
}
|
|
122812
|
+
case "call_expression":
|
|
122813
|
+
case "subscript_expression":
|
|
122814
|
+
case "template_string":
|
|
122815
|
+
return true;
|
|
122816
|
+
case "ternary_expression": {
|
|
122817
|
+
const cons = arg.childForFieldName("consequence");
|
|
122818
|
+
const alt = arg.childForFieldName("alternative");
|
|
122819
|
+
return !!cons && isDynamicPerIteration(cons, callNode) || !!alt && isDynamicPerIteration(alt, callNode);
|
|
122820
|
+
}
|
|
122821
|
+
case "binary_expression": {
|
|
122822
|
+
const left = arg.childForFieldName("left");
|
|
122823
|
+
const right = arg.childForFieldName("right");
|
|
122824
|
+
return !!left && isDynamicPerIteration(left, callNode) || !!right && isDynamicPerIteration(right, callNode);
|
|
122825
|
+
}
|
|
122826
|
+
case "identifier":
|
|
122827
|
+
return isLoopBoundIdentifier(arg.text, callNode);
|
|
122828
|
+
case "member_expression": {
|
|
122829
|
+
const inner = arg.childForFieldName("object");
|
|
122830
|
+
if (!inner)
|
|
122831
|
+
return false;
|
|
122832
|
+
if (inner.type === "identifier")
|
|
122833
|
+
return isLoopBoundIdentifier(inner.text, callNode);
|
|
122834
|
+
return isDynamicPerIteration(inner, callNode);
|
|
122835
|
+
}
|
|
122836
|
+
default:
|
|
122837
|
+
return false;
|
|
122838
|
+
}
|
|
122839
|
+
}
|
|
122840
|
+
function isLoopBoundIdentifier(varName, callNode) {
|
|
122841
|
+
let current = callNode.parent;
|
|
122842
|
+
let innermostLoop = null;
|
|
122843
|
+
while (current) {
|
|
122844
|
+
if (current.type === "for_in_statement" || current.type === "for_of_statement") {
|
|
122845
|
+
const left = current.childForFieldName("left");
|
|
122846
|
+
if (left && containsIdentifierExact(left, varName))
|
|
122847
|
+
return true;
|
|
122848
|
+
if (!innermostLoop)
|
|
122849
|
+
innermostLoop = current;
|
|
122850
|
+
}
|
|
122851
|
+
if (current.type === "for_statement") {
|
|
122852
|
+
const init = current.childForFieldName("initializer");
|
|
122853
|
+
if (init && containsIdentifierExact(init, varName))
|
|
122854
|
+
return true;
|
|
122855
|
+
if (!innermostLoop)
|
|
122856
|
+
innermostLoop = current;
|
|
122857
|
+
}
|
|
122858
|
+
if (current.type === "while_statement" || current.type === "do_statement") {
|
|
122859
|
+
if (!innermostLoop)
|
|
122860
|
+
innermostLoop = current;
|
|
122861
|
+
}
|
|
122862
|
+
if (current.type === "arrow_function" || current.type === "function_expression" || current.type === "function") {
|
|
122863
|
+
const params = current.childForFieldName("parameters");
|
|
122864
|
+
if (params && containsIdentifierExact(params, varName)) {
|
|
122865
|
+
const callParent = current.parent?.parent;
|
|
122866
|
+
if (callParent?.type === "call_expression")
|
|
122867
|
+
return true;
|
|
122868
|
+
}
|
|
122869
|
+
}
|
|
122870
|
+
current = current.parent;
|
|
122871
|
+
}
|
|
122872
|
+
if (innermostLoop) {
|
|
122873
|
+
const body = innermostLoop.childForFieldName("body");
|
|
122874
|
+
if (body && containsBindingInBlock(body, varName))
|
|
122875
|
+
return true;
|
|
122876
|
+
}
|
|
122877
|
+
return false;
|
|
122878
|
+
}
|
|
122879
|
+
function containsBindingInBlock(node2, varName) {
|
|
122880
|
+
if (node2.type === "lexical_declaration" || node2.type === "variable_declaration") {
|
|
122881
|
+
for (const decl of node2.namedChildren) {
|
|
122882
|
+
if (decl.type === "variable_declarator") {
|
|
122883
|
+
const name = decl.childForFieldName("name");
|
|
122884
|
+
if (name && containsIdentifierExact(name, varName))
|
|
122885
|
+
return true;
|
|
122886
|
+
}
|
|
122887
|
+
}
|
|
122888
|
+
return false;
|
|
122889
|
+
}
|
|
122890
|
+
if (node2.type === "function_declaration" || node2.type === "arrow_function" || node2.type === "function" || node2.type === "function_expression" || node2.type === "method_definition" || node2.type === "class_declaration") {
|
|
122891
|
+
return false;
|
|
122892
|
+
}
|
|
122893
|
+
for (let i = 0; i < node2.childCount; i++) {
|
|
122894
|
+
const child = node2.child(i);
|
|
122895
|
+
if (child && containsBindingInBlock(child, varName))
|
|
122896
|
+
return true;
|
|
122897
|
+
}
|
|
122898
|
+
return false;
|
|
122899
|
+
}
|
|
122688
122900
|
var jsonParseInLoopVisitor;
|
|
122689
122901
|
var init_json_parse_in_loop = __esm({
|
|
122690
122902
|
"packages/analyzer/dist/rules/performance/visitors/javascript/json-parse-in-loop.js"() {
|
|
@@ -122709,64 +122921,9 @@ var init_json_parse_in_loop = __esm({
|
|
|
122709
122921
|
if (!isInsideLoop(node2))
|
|
122710
122922
|
return null;
|
|
122711
122923
|
const args = node2.childForFieldName("arguments");
|
|
122712
|
-
|
|
122713
|
-
|
|
122714
|
-
|
|
122715
|
-
if (firstArg.type === "call_expression")
|
|
122716
|
-
return null;
|
|
122717
|
-
if (firstArg.type === "subscript_expression")
|
|
122718
|
-
return null;
|
|
122719
|
-
if (firstArg.type === "template_string")
|
|
122720
|
-
return null;
|
|
122721
|
-
if (firstArg.type === "identifier") {
|
|
122722
|
-
const varName = firstArg.text;
|
|
122723
|
-
let current = node2.parent;
|
|
122724
|
-
while (current) {
|
|
122725
|
-
if (current.type === "for_in_statement" || current.type === "for_of_statement") {
|
|
122726
|
-
const left = current.childForFieldName("left");
|
|
122727
|
-
if (left && containsIdentifierExact(left, varName))
|
|
122728
|
-
return null;
|
|
122729
|
-
}
|
|
122730
|
-
if (current.type === "for_statement") {
|
|
122731
|
-
const init = current.childForFieldName("initializer");
|
|
122732
|
-
if (init && containsIdentifierExact(init, varName))
|
|
122733
|
-
return null;
|
|
122734
|
-
}
|
|
122735
|
-
if (current.type === "arrow_function" || current.type === "function_expression" || current.type === "function") {
|
|
122736
|
-
const params = current.childForFieldName("parameters");
|
|
122737
|
-
if (params && containsIdentifierExact(params, varName)) {
|
|
122738
|
-
const callParent = current.parent?.parent;
|
|
122739
|
-
if (callParent?.type === "call_expression")
|
|
122740
|
-
return null;
|
|
122741
|
-
}
|
|
122742
|
-
}
|
|
122743
|
-
current = current.parent;
|
|
122744
|
-
}
|
|
122745
|
-
}
|
|
122746
|
-
if (firstArg.type === "member_expression") {
|
|
122747
|
-
const innerObj = firstArg.childForFieldName("object");
|
|
122748
|
-
if (innerObj?.type === "identifier") {
|
|
122749
|
-
let current = node2.parent;
|
|
122750
|
-
while (current) {
|
|
122751
|
-
if (current.type === "for_in_statement" || current.type === "for_of_statement") {
|
|
122752
|
-
const left = current.childForFieldName("left");
|
|
122753
|
-
if (left && containsIdentifierExact(left, innerObj.text))
|
|
122754
|
-
return null;
|
|
122755
|
-
}
|
|
122756
|
-
if (current.type === "arrow_function" || current.type === "function_expression" || current.type === "function") {
|
|
122757
|
-
const params = current.childForFieldName("parameters");
|
|
122758
|
-
if (params && containsIdentifierExact(params, innerObj.text)) {
|
|
122759
|
-
const callParent = current.parent?.parent;
|
|
122760
|
-
if (callParent?.type === "call_expression")
|
|
122761
|
-
return null;
|
|
122762
|
-
}
|
|
122763
|
-
}
|
|
122764
|
-
current = current.parent;
|
|
122765
|
-
}
|
|
122766
|
-
}
|
|
122767
|
-
}
|
|
122768
|
-
}
|
|
122769
|
-
}
|
|
122924
|
+
const firstArg = args?.namedChildren[0];
|
|
122925
|
+
if (firstArg && isDynamicPerIteration(firstArg, node2))
|
|
122926
|
+
return null;
|
|
122770
122927
|
return makeViolation(this.ruleKey, node2, filePath, "medium", `JSON.${prop.text}() inside loop`, `JSON.${prop.text}() is expensive and calling it inside a loop degrades performance. Move it outside the loop if possible.`, sourceCode, `Cache the result of JSON.${prop.text}() outside the loop.`);
|
|
122771
122928
|
}
|
|
122772
122929
|
};
|
|
@@ -123099,6 +123256,19 @@ var init_missing_usememo_expensive = __esm({
|
|
|
123099
123256
|
return null;
|
|
123100
123257
|
}
|
|
123101
123258
|
}
|
|
123259
|
+
if (prop.text === "reduce") {
|
|
123260
|
+
const args = node2.childForFieldName("arguments");
|
|
123261
|
+
const callback = args?.namedChild(0);
|
|
123262
|
+
if (callback?.type === "arrow_function" || callback?.type === "function_expression" || callback?.type === "function") {
|
|
123263
|
+
const body = callback.childForFieldName("body");
|
|
123264
|
+
let inspect = body;
|
|
123265
|
+
if (inspect?.type === "parenthesized_expression") {
|
|
123266
|
+
inspect = inspect.namedChildren[0] ?? inspect;
|
|
123267
|
+
}
|
|
123268
|
+
if (inspect?.type === "binary_expression")
|
|
123269
|
+
return null;
|
|
123270
|
+
}
|
|
123271
|
+
}
|
|
123102
123272
|
const enclosingFn = findEnclosingFunctionNode(node2);
|
|
123103
123273
|
if (!enclosingFn)
|
|
123104
123274
|
return null;
|
|
@@ -124094,6 +124264,37 @@ var init_python9 = __esm({
|
|
|
124094
124264
|
});
|
|
124095
124265
|
|
|
124096
124266
|
// packages/analyzer/dist/rules/reliability/visitors/javascript/catch-without-error-type.js
|
|
124267
|
+
function narrowsViaTypeGuard(node2, paramName2) {
|
|
124268
|
+
if (node2.type === "call_expression") {
|
|
124269
|
+
const fn = node2.childForFieldName("function");
|
|
124270
|
+
let calleeName = null;
|
|
124271
|
+
if (fn?.type === "identifier")
|
|
124272
|
+
calleeName = fn.text;
|
|
124273
|
+
else if (fn?.type === "member_expression")
|
|
124274
|
+
calleeName = fn.childForFieldName("property")?.text ?? null;
|
|
124275
|
+
if (calleeName && TYPE_GUARD_NAME.test(calleeName)) {
|
|
124276
|
+
const args = node2.childForFieldName("arguments");
|
|
124277
|
+
if (args && referencesBinding(args, paramName2))
|
|
124278
|
+
return true;
|
|
124279
|
+
}
|
|
124280
|
+
}
|
|
124281
|
+
for (let i = 0; i < node2.childCount; i++) {
|
|
124282
|
+
const ch = node2.child(i);
|
|
124283
|
+
if (ch && narrowsViaTypeGuard(ch, paramName2))
|
|
124284
|
+
return true;
|
|
124285
|
+
}
|
|
124286
|
+
return false;
|
|
124287
|
+
}
|
|
124288
|
+
function referencesBinding(node2, name) {
|
|
124289
|
+
if (node2.type === "identifier" && node2.text === name)
|
|
124290
|
+
return true;
|
|
124291
|
+
for (let i = 0; i < node2.childCount; i++) {
|
|
124292
|
+
const ch = node2.child(i);
|
|
124293
|
+
if (ch && referencesBinding(ch, name))
|
|
124294
|
+
return true;
|
|
124295
|
+
}
|
|
124296
|
+
return false;
|
|
124297
|
+
}
|
|
124097
124298
|
function hasBranchingConstruct(node2) {
|
|
124098
124299
|
if (node2.type === "if_statement" || node2.type === "switch_statement" || node2.type === "ternary_expression")
|
|
124099
124300
|
return true;
|
|
@@ -124106,7 +124307,7 @@ function hasBranchingConstruct(node2) {
|
|
|
124106
124307
|
}
|
|
124107
124308
|
return false;
|
|
124108
124309
|
}
|
|
124109
|
-
var catchWithoutErrorTypeVisitor;
|
|
124310
|
+
var catchWithoutErrorTypeVisitor, TYPE_GUARD_NAME;
|
|
124110
124311
|
var init_catch_without_error_type = __esm({
|
|
124111
124312
|
"packages/analyzer/dist/rules/reliability/visitors/javascript/catch-without-error-type.js"() {
|
|
124112
124313
|
"use strict";
|
|
@@ -124134,9 +124335,13 @@ var init_catch_without_error_type = __esm({
|
|
|
124134
124335
|
return null;
|
|
124135
124336
|
if (!hasBranchingConstruct(body))
|
|
124136
124337
|
return null;
|
|
124338
|
+
const paramName2 = param.type === "identifier" ? param.text : null;
|
|
124339
|
+
if (paramName2 && narrowsViaTypeGuard(body, paramName2))
|
|
124340
|
+
return null;
|
|
124137
124341
|
return makeViolation(this.ruleKey, node2, filePath, "medium", "Catch without error type discrimination", "Catch block does not check or narrow the error type. Different error types may need different handling.", sourceCode, "Use instanceof checks or type guards in the catch block to handle specific error types.");
|
|
124138
124342
|
}
|
|
124139
124343
|
};
|
|
124344
|
+
TYPE_GUARD_NAME = /^(is|has|assert)[A-Z]/;
|
|
124140
124345
|
}
|
|
124141
124346
|
});
|
|
124142
124347
|
|
|
@@ -129378,7 +129583,8 @@ __export(dist_exports, {
|
|
|
129378
129583
|
shouldExtractEntities: () => shouldExtractEntities,
|
|
129379
129584
|
toLayerDetectionResults: () => toLayerDetectionResults,
|
|
129380
129585
|
traceFlows: () => traceFlows,
|
|
129381
|
-
walkAstWithVisitors: () => walkAstWithVisitors
|
|
129586
|
+
walkAstWithVisitors: () => walkAstWithVisitors,
|
|
129587
|
+
withParsedTree: () => withParsedTree
|
|
129382
129588
|
});
|
|
129383
129589
|
async function analyzeRepository(rootPath) {
|
|
129384
129590
|
await initParsers();
|
|
@@ -129558,12 +129764,12 @@ var require_isexe = __commonJS({
|
|
|
129558
129764
|
if (typeof Promise !== "function") {
|
|
129559
129765
|
throw new TypeError("callback not provided");
|
|
129560
129766
|
}
|
|
129561
|
-
return new Promise(function(
|
|
129767
|
+
return new Promise(function(resolve9, reject) {
|
|
129562
129768
|
isexe(path52, options || {}, function(er, is) {
|
|
129563
129769
|
if (er) {
|
|
129564
129770
|
reject(er);
|
|
129565
129771
|
} else {
|
|
129566
|
-
|
|
129772
|
+
resolve9(is);
|
|
129567
129773
|
}
|
|
129568
129774
|
});
|
|
129569
129775
|
});
|
|
@@ -129629,27 +129835,27 @@ var require_which = __commonJS({
|
|
|
129629
129835
|
opt = {};
|
|
129630
129836
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
129631
129837
|
const found = [];
|
|
129632
|
-
const step = (i) => new Promise((
|
|
129838
|
+
const step = (i) => new Promise((resolve9, reject) => {
|
|
129633
129839
|
if (i === pathEnv.length)
|
|
129634
|
-
return opt.all && found.length ?
|
|
129840
|
+
return opt.all && found.length ? resolve9(found) : reject(getNotFoundError(cmd));
|
|
129635
129841
|
const ppRaw = pathEnv[i];
|
|
129636
129842
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
129637
129843
|
const pCmd = path52.join(pathPart, cmd);
|
|
129638
129844
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
129639
|
-
|
|
129845
|
+
resolve9(subStep(p, i, 0));
|
|
129640
129846
|
});
|
|
129641
|
-
const subStep = (p, i, ii) => new Promise((
|
|
129847
|
+
const subStep = (p, i, ii) => new Promise((resolve9, reject) => {
|
|
129642
129848
|
if (ii === pathExt.length)
|
|
129643
|
-
return
|
|
129849
|
+
return resolve9(step(i + 1));
|
|
129644
129850
|
const ext2 = pathExt[ii];
|
|
129645
129851
|
isexe(p + ext2, { pathExt: pathExtExe }, (er, is) => {
|
|
129646
129852
|
if (!er && is) {
|
|
129647
129853
|
if (opt.all)
|
|
129648
129854
|
found.push(p + ext2);
|
|
129649
129855
|
else
|
|
129650
|
-
return
|
|
129856
|
+
return resolve9(p + ext2);
|
|
129651
129857
|
}
|
|
129652
|
-
return
|
|
129858
|
+
return resolve9(subStep(p, i, ii + 1));
|
|
129653
129859
|
});
|
|
129654
129860
|
});
|
|
129655
129861
|
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
@@ -130054,27 +130260,27 @@ function pLimit(concurrency) {
|
|
|
130054
130260
|
activeCount--;
|
|
130055
130261
|
resumeNext();
|
|
130056
130262
|
};
|
|
130057
|
-
const run = async (function_,
|
|
130263
|
+
const run = async (function_, resolve9, arguments_) => {
|
|
130058
130264
|
const result = (async () => function_(...arguments_))();
|
|
130059
|
-
|
|
130265
|
+
resolve9(result);
|
|
130060
130266
|
try {
|
|
130061
130267
|
await result;
|
|
130062
130268
|
} catch {
|
|
130063
130269
|
}
|
|
130064
130270
|
next();
|
|
130065
130271
|
};
|
|
130066
|
-
const enqueue = (function_,
|
|
130272
|
+
const enqueue = (function_, resolve9, reject, arguments_) => {
|
|
130067
130273
|
const queueItem = { reject };
|
|
130068
130274
|
new Promise((internalResolve) => {
|
|
130069
130275
|
queueItem.run = internalResolve;
|
|
130070
130276
|
queue.enqueue(queueItem);
|
|
130071
|
-
}).then(run.bind(void 0, function_,
|
|
130277
|
+
}).then(run.bind(void 0, function_, resolve9, arguments_));
|
|
130072
130278
|
if (activeCount < concurrency) {
|
|
130073
130279
|
resumeNext();
|
|
130074
130280
|
}
|
|
130075
130281
|
};
|
|
130076
|
-
const generator = (function_, ...arguments_) => new Promise((
|
|
130077
|
-
enqueue(function_,
|
|
130282
|
+
const generator = (function_, ...arguments_) => new Promise((resolve9, reject) => {
|
|
130283
|
+
enqueue(function_, resolve9, reject, arguments_);
|
|
130078
130284
|
});
|
|
130079
130285
|
Object.defineProperties(generator, {
|
|
130080
130286
|
activeCount: {
|
|
@@ -132572,7 +132778,7 @@ var init_cli_provider = __esm({
|
|
|
132572
132778
|
jsonSchemaStr,
|
|
132573
132779
|
...opts?.extraArgs ?? []
|
|
132574
132780
|
];
|
|
132575
|
-
return new Promise((
|
|
132781
|
+
return new Promise((resolve9, reject) => {
|
|
132576
132782
|
const child = (0, import_cross_spawn.default)(this.binaryName, args, {
|
|
132577
132783
|
env: this.getCleanEnv(),
|
|
132578
132784
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -132620,7 +132826,7 @@ var init_cli_provider = __esm({
|
|
|
132620
132826
|
reject(new Error(`[CLI] ${this.binaryName} exited with code ${code}: ${detail}`));
|
|
132621
132827
|
return;
|
|
132622
132828
|
}
|
|
132623
|
-
|
|
132829
|
+
resolve9(stdout);
|
|
132624
132830
|
});
|
|
132625
132831
|
child.on("error", (err) => {
|
|
132626
132832
|
clearTimeout(timer);
|
|
@@ -135815,10 +136021,10 @@ var require_axios = __commonJS({
|
|
|
135815
136021
|
this.__CANCEL__ = true;
|
|
135816
136022
|
}
|
|
135817
136023
|
};
|
|
135818
|
-
function settle(
|
|
136024
|
+
function settle(resolve9, reject, response) {
|
|
135819
136025
|
const validateStatus = response.config.validateStatus;
|
|
135820
136026
|
if (!response.status || !validateStatus || validateStatus(response.status)) {
|
|
135821
|
-
|
|
136027
|
+
resolve9(response);
|
|
135822
136028
|
} else {
|
|
135823
136029
|
reject(new AxiosError("Request failed with status code " + response.status, [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], response.config, response.request, response));
|
|
135824
136030
|
}
|
|
@@ -136461,7 +136667,7 @@ var require_axios = __commonJS({
|
|
|
136461
136667
|
}
|
|
136462
136668
|
var isHttpAdapterSupported = typeof process !== "undefined" && utils$1.kindOf(process) === "process";
|
|
136463
136669
|
var wrapAsync = (asyncExecutor) => {
|
|
136464
|
-
return new Promise((
|
|
136670
|
+
return new Promise((resolve9, reject) => {
|
|
136465
136671
|
let onDone;
|
|
136466
136672
|
let isDone;
|
|
136467
136673
|
const done = (value, isRejected) => {
|
|
@@ -136471,7 +136677,7 @@ var require_axios = __commonJS({
|
|
|
136471
136677
|
};
|
|
136472
136678
|
const _resolve = (value) => {
|
|
136473
136679
|
done(value);
|
|
136474
|
-
|
|
136680
|
+
resolve9(value);
|
|
136475
136681
|
};
|
|
136476
136682
|
const _reject = (reason) => {
|
|
136477
136683
|
done(reason, true);
|
|
@@ -136532,7 +136738,7 @@ var require_axios = __commonJS({
|
|
|
136532
136738
|
}
|
|
136533
136739
|
};
|
|
136534
136740
|
var httpAdapter = isHttpAdapterSupported && function httpAdapter2(config2) {
|
|
136535
|
-
return wrapAsync(async function dispatchHttpRequest(
|
|
136741
|
+
return wrapAsync(async function dispatchHttpRequest(resolve9, reject, onDone) {
|
|
136536
136742
|
let {
|
|
136537
136743
|
data,
|
|
136538
136744
|
lookup,
|
|
@@ -136624,7 +136830,7 @@ var require_axios = __commonJS({
|
|
|
136624
136830
|
}
|
|
136625
136831
|
let convertedData;
|
|
136626
136832
|
if (method !== "GET") {
|
|
136627
|
-
return settle(
|
|
136833
|
+
return settle(resolve9, reject, {
|
|
136628
136834
|
status: 405,
|
|
136629
136835
|
statusText: "method not allowed",
|
|
136630
136836
|
headers: {},
|
|
@@ -136646,7 +136852,7 @@ var require_axios = __commonJS({
|
|
|
136646
136852
|
} else if (responseType === "stream") {
|
|
136647
136853
|
convertedData = stream.Readable.from(convertedData);
|
|
136648
136854
|
}
|
|
136649
|
-
return settle(
|
|
136855
|
+
return settle(resolve9, reject, {
|
|
136650
136856
|
data: convertedData,
|
|
136651
136857
|
status: 200,
|
|
136652
136858
|
statusText: "OK",
|
|
@@ -136841,7 +137047,7 @@ var require_axios = __commonJS({
|
|
|
136841
137047
|
};
|
|
136842
137048
|
if (responseType === "stream") {
|
|
136843
137049
|
response.data = responseStream;
|
|
136844
|
-
settle(
|
|
137050
|
+
settle(resolve9, reject, response);
|
|
136845
137051
|
} else {
|
|
136846
137052
|
const responseBuffer = [];
|
|
136847
137053
|
let totalResponseBytes = 0;
|
|
@@ -136879,7 +137085,7 @@ var require_axios = __commonJS({
|
|
|
136879
137085
|
} catch (err) {
|
|
136880
137086
|
return reject(AxiosError.from(err, null, config2, response.request, response));
|
|
136881
137087
|
}
|
|
136882
|
-
settle(
|
|
137088
|
+
settle(resolve9, reject, response);
|
|
136883
137089
|
});
|
|
136884
137090
|
}
|
|
136885
137091
|
abortEmitter.once("abort", (err) => {
|
|
@@ -137117,7 +137323,7 @@ var require_axios = __commonJS({
|
|
|
137117
137323
|
};
|
|
137118
137324
|
var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined";
|
|
137119
137325
|
var xhrAdapter = isXHRAdapterSupported && function(config2) {
|
|
137120
|
-
return new Promise(function dispatchXhrRequest(
|
|
137326
|
+
return new Promise(function dispatchXhrRequest(resolve9, reject) {
|
|
137121
137327
|
const _config = resolveConfig(config2);
|
|
137122
137328
|
let requestData = _config.data;
|
|
137123
137329
|
const requestHeaders = AxiosHeaders.from(_config.headers).normalize();
|
|
@@ -137153,7 +137359,7 @@ var require_axios = __commonJS({
|
|
|
137153
137359
|
request
|
|
137154
137360
|
};
|
|
137155
137361
|
settle(function _resolve(value) {
|
|
137156
|
-
|
|
137362
|
+
resolve9(value);
|
|
137157
137363
|
done();
|
|
137158
137364
|
}, function _reject(err) {
|
|
137159
137365
|
reject(err);
|
|
@@ -137524,8 +137730,8 @@ var require_axios = __commonJS({
|
|
|
137524
137730
|
responseType = responseType || "text";
|
|
137525
137731
|
let responseData = await resolvers[utils$1.findKey(resolvers, responseType) || "text"](response, config2);
|
|
137526
137732
|
!isStreamResponse && unsubscribe && unsubscribe();
|
|
137527
|
-
return await new Promise((
|
|
137528
|
-
settle(
|
|
137733
|
+
return await new Promise((resolve9, reject) => {
|
|
137734
|
+
settle(resolve9, reject, {
|
|
137529
137735
|
data: responseData,
|
|
137530
137736
|
headers: AxiosHeaders.from(response.headers),
|
|
137531
137737
|
status: response.status,
|
|
@@ -137894,8 +138100,8 @@ var require_axios = __commonJS({
|
|
|
137894
138100
|
throw new TypeError("executor must be a function.");
|
|
137895
138101
|
}
|
|
137896
138102
|
let resolvePromise;
|
|
137897
|
-
this.promise = new Promise(function promiseExecutor(
|
|
137898
|
-
resolvePromise =
|
|
138103
|
+
this.promise = new Promise(function promiseExecutor(resolve9) {
|
|
138104
|
+
resolvePromise = resolve9;
|
|
137899
138105
|
});
|
|
137900
138106
|
const token = this;
|
|
137901
138107
|
this.promise.then((cancel) => {
|
|
@@ -137908,9 +138114,9 @@ var require_axios = __commonJS({
|
|
|
137908
138114
|
});
|
|
137909
138115
|
this.promise.then = (onfulfilled) => {
|
|
137910
138116
|
let _resolve;
|
|
137911
|
-
const promise = new Promise((
|
|
137912
|
-
token.subscribe(
|
|
137913
|
-
_resolve =
|
|
138117
|
+
const promise = new Promise((resolve9) => {
|
|
138118
|
+
token.subscribe(resolve9);
|
|
138119
|
+
_resolve = resolve9;
|
|
137914
138120
|
}).then(onfulfilled);
|
|
137915
138121
|
promise.cancel = function reject() {
|
|
137916
138122
|
token.unsubscribe(_resolve);
|
|
@@ -145925,7 +146131,7 @@ function emitAnalysisCanceled(repoId) {
|
|
|
145925
146131
|
io3.to(`repo:${repoId}`).emit("analysis:canceled", { repoId });
|
|
145926
146132
|
}
|
|
145927
146133
|
function createSocketLlmEstimateHandler(repoId) {
|
|
145928
|
-
return (estimate) => new Promise((
|
|
146134
|
+
return (estimate) => new Promise((resolve9) => {
|
|
145929
146135
|
const io3 = getIO();
|
|
145930
146136
|
const room = `repo:${repoId}`;
|
|
145931
146137
|
io3.to(room).emit("analysis:llm-estimate", {
|
|
@@ -145939,13 +146145,13 @@ function createSocketLlmEstimateHandler(repoId) {
|
|
|
145939
146145
|
});
|
|
145940
146146
|
const timeout = setTimeout(() => {
|
|
145941
146147
|
cleanup();
|
|
145942
|
-
|
|
146148
|
+
resolve9(true);
|
|
145943
146149
|
}, 6e4);
|
|
145944
146150
|
function onProceed(data) {
|
|
145945
146151
|
if (data.repoId !== repoId) return;
|
|
145946
146152
|
cleanup();
|
|
145947
146153
|
io3.to(room).emit("analysis:llm-resolved", { repoId, proceed: data.proceed });
|
|
145948
|
-
|
|
146154
|
+
resolve9(data.proceed);
|
|
145949
146155
|
}
|
|
145950
146156
|
function cleanup() {
|
|
145951
146157
|
clearTimeout(timeout);
|
|
@@ -145959,7 +146165,7 @@ function createSocketLlmEstimateHandler(repoId) {
|
|
|
145959
146165
|
});
|
|
145960
146166
|
}
|
|
145961
146167
|
function createSocketStashConfirmHandler(repoId) {
|
|
145962
|
-
return (info) => new Promise((
|
|
146168
|
+
return (info) => new Promise((resolve9) => {
|
|
145963
146169
|
const io3 = getIO();
|
|
145964
146170
|
const room = `repo:${repoId}`;
|
|
145965
146171
|
io3.to(room).emit("analysis:stash-confirm-request", {
|
|
@@ -145970,7 +146176,7 @@ function createSocketStashConfirmHandler(repoId) {
|
|
|
145970
146176
|
function onResponse(data) {
|
|
145971
146177
|
if (data.repoId !== repoId) return;
|
|
145972
146178
|
cleanup();
|
|
145973
|
-
|
|
146179
|
+
resolve9(data.choice);
|
|
145974
146180
|
}
|
|
145975
146181
|
function cleanup() {
|
|
145976
146182
|
for (const [, socket] of io3.sockets.sockets) {
|
|
@@ -152776,12 +152982,12 @@ async function runViolationPipeline(input) {
|
|
|
152776
152982
|
const fileContents = /* @__PURE__ */ new Map();
|
|
152777
152983
|
const totalToScan = filesToScan.length;
|
|
152778
152984
|
let scanned = 0;
|
|
152779
|
-
for (const { filePath, resolve:
|
|
152985
|
+
for (const { filePath, resolve: resolve9 } of filesToScan) {
|
|
152780
152986
|
try {
|
|
152781
152987
|
const lang = detectLanguage(filePath);
|
|
152782
152988
|
if (!lang)
|
|
152783
152989
|
continue;
|
|
152784
|
-
const absPath =
|
|
152990
|
+
const absPath = resolve9 ? path12.resolve(repoPath, filePath) : path12.isAbsolute(filePath) ? filePath : path12.join(repoPath, filePath);
|
|
152785
152991
|
if (!fs11.existsSync(absPath))
|
|
152786
152992
|
continue;
|
|
152787
152993
|
const content = fs11.readFileSync(absPath, "utf-8");
|
|
@@ -152886,18 +153092,17 @@ async function runViolationPipeline(input) {
|
|
|
152886
153092
|
const DETAIL_UPDATE_MS = 100;
|
|
152887
153093
|
let lastYieldMs = Date.now();
|
|
152888
153094
|
let lastDetailMs = lastYieldMs;
|
|
152889
|
-
for (const { filePath, resolve:
|
|
153095
|
+
for (const { filePath, resolve: resolve9 } of filesToScan) {
|
|
152890
153096
|
try {
|
|
152891
153097
|
const lang = detectLanguage(filePath);
|
|
152892
153098
|
if (!lang)
|
|
152893
153099
|
continue;
|
|
152894
|
-
const absPath =
|
|
153100
|
+
const absPath = resolve9 ? path12.resolve(repoPath, filePath) : path12.isAbsolute(filePath) ? filePath : path12.join(repoPath, filePath);
|
|
152895
153101
|
const key2 = changedFileSet ? absPath : filePath;
|
|
152896
153102
|
const fc = fileContents.get(key2);
|
|
152897
153103
|
if (!fc)
|
|
152898
153104
|
continue;
|
|
152899
|
-
const
|
|
152900
|
-
const codeRuleViolations = checkCodeRules(tree, changedFileSet ? absPath : filePath, fc.content, enabledCodeRules, lang, typeQuery, schemaIndex);
|
|
153105
|
+
const codeRuleViolations = withParsedTree(filePath, fc.content, lang, (tree) => checkCodeRules(tree, changedFileSet ? absPath : filePath, fc.content, enabledCodeRules, lang, typeQuery, schemaIndex));
|
|
152901
153106
|
allCodeViolations.push(...codeRuleViolations);
|
|
152902
153107
|
} catch {
|
|
152903
153108
|
}
|
|
@@ -155047,14 +155252,14 @@ async function addSourceContext(frames) {
|
|
|
155047
155252
|
return frames;
|
|
155048
155253
|
}
|
|
155049
155254
|
function getContextLinesFromFile(path52, ranges, output) {
|
|
155050
|
-
return new Promise((
|
|
155255
|
+
return new Promise((resolve9) => {
|
|
155051
155256
|
const stream = createReadStream(path52);
|
|
155052
155257
|
const lineReaded = createInterface({
|
|
155053
155258
|
input: stream
|
|
155054
155259
|
});
|
|
155055
155260
|
function destroyStreamAndResolve() {
|
|
155056
155261
|
stream.destroy();
|
|
155057
|
-
|
|
155262
|
+
resolve9();
|
|
155058
155263
|
}
|
|
155059
155264
|
let lineNumber = 0;
|
|
155060
155265
|
let currentRangeIndex = 0;
|
|
@@ -157652,15 +157857,15 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
157652
157857
|
if (this.featureFlagsPoller === void 0) {
|
|
157653
157858
|
return false;
|
|
157654
157859
|
}
|
|
157655
|
-
return new Promise((
|
|
157860
|
+
return new Promise((resolve9) => {
|
|
157656
157861
|
const timeout = setTimeout(() => {
|
|
157657
157862
|
cleanup();
|
|
157658
|
-
|
|
157863
|
+
resolve9(false);
|
|
157659
157864
|
}, timeoutMs);
|
|
157660
157865
|
const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
|
|
157661
157866
|
clearTimeout(timeout);
|
|
157662
157867
|
cleanup();
|
|
157663
|
-
|
|
157868
|
+
resolve9(count > 0);
|
|
157664
157869
|
});
|
|
157665
157870
|
});
|
|
157666
157871
|
}
|
|
@@ -158123,7 +158328,7 @@ function readToolVersion() {
|
|
|
158123
158328
|
if (cachedVersion)
|
|
158124
158329
|
return cachedVersion;
|
|
158125
158330
|
if (true) {
|
|
158126
|
-
cachedVersion = "0.6.
|
|
158331
|
+
cachedVersion = "0.6.7-next.1";
|
|
158127
158332
|
return cachedVersion;
|
|
158128
158333
|
}
|
|
158129
158334
|
try {
|
|
@@ -160312,6 +160517,7 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
160312
160517
|
".cache",
|
|
160313
160518
|
"coverage"
|
|
160314
160519
|
]);
|
|
160520
|
+
var SKIP_DIR_PROBE = "__tc_skipdir_probe__.md";
|
|
160315
160521
|
var PREVIEW_LINE_LIMIT = 200;
|
|
160316
160522
|
function discoverDocs(rootDir, opts = {}) {
|
|
160317
160523
|
const previewLines = opts.previewLines ?? PREVIEW_LINE_LIMIT;
|
|
@@ -160326,11 +160532,12 @@ function discoverDocs(rootDir, opts = {}) {
|
|
|
160326
160532
|
}
|
|
160327
160533
|
entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
160328
160534
|
for (const entry of entries) {
|
|
160329
|
-
|
|
160535
|
+
const full = path18.join(dir, entry.name);
|
|
160536
|
+
if (SKIP_DIRS.has(entry.name) && !(entry.isDirectory() && tcIgnore.reincludes(path18.join(full, SKIP_DIR_PROBE)))) {
|
|
160330
160537
|
continue;
|
|
160538
|
+
}
|
|
160331
160539
|
if (entry.name.startsWith(".") && entry.name !== ".")
|
|
160332
160540
|
continue;
|
|
160333
|
-
const full = path18.join(dir, entry.name);
|
|
160334
160541
|
if (tcIgnore.ignores(full))
|
|
160335
160542
|
continue;
|
|
160336
160543
|
if (entry.isDirectory()) {
|
|
@@ -160520,7 +160727,7 @@ function stripCodeFences(text) {
|
|
|
160520
160727
|
}
|
|
160521
160728
|
function cliTransport(opts = {}) {
|
|
160522
160729
|
const bin = opts.bin ?? resolveClaudeBinary();
|
|
160523
|
-
return (req) => new Promise((
|
|
160730
|
+
return (req) => new Promise((resolve9, reject) => {
|
|
160524
160731
|
const modelArgs = [];
|
|
160525
160732
|
if (req.model)
|
|
160526
160733
|
modelArgs.push("--model", req.model);
|
|
@@ -160565,7 +160772,7 @@ function cliTransport(opts = {}) {
|
|
|
160565
160772
|
reject(new Error("claude returned no text"));
|
|
160566
160773
|
return;
|
|
160567
160774
|
}
|
|
160568
|
-
|
|
160775
|
+
resolve9(text);
|
|
160569
160776
|
} catch (e) {
|
|
160570
160777
|
reject(e instanceof Error ? e : new Error(String(e)));
|
|
160571
160778
|
}
|
|
@@ -162315,14 +162522,14 @@ async function explainConflicts(repoRoot, conflicts2, opts = {}) {
|
|
|
162315
162522
|
opts.onStart?.(conflicts2.length);
|
|
162316
162523
|
let active = 0;
|
|
162317
162524
|
let cursor = 0;
|
|
162318
|
-
await new Promise((
|
|
162525
|
+
await new Promise((resolve9) => {
|
|
162319
162526
|
const launch = () => {
|
|
162320
162527
|
while (active < concurrency && cursor < conflicts2.length) {
|
|
162321
162528
|
const conflict = conflicts2[cursor++];
|
|
162322
162529
|
if (conflict.explanation) {
|
|
162323
162530
|
opts.onDone?.();
|
|
162324
162531
|
if (cursor >= conflicts2.length && active === 0)
|
|
162325
|
-
|
|
162532
|
+
resolve9();
|
|
162326
162533
|
continue;
|
|
162327
162534
|
}
|
|
162328
162535
|
active++;
|
|
@@ -162330,13 +162537,13 @@ async function explainConflicts(repoRoot, conflicts2, opts = {}) {
|
|
|
162330
162537
|
opts.onDone?.();
|
|
162331
162538
|
active--;
|
|
162332
162539
|
if (cursor >= conflicts2.length && active === 0)
|
|
162333
|
-
|
|
162540
|
+
resolve9();
|
|
162334
162541
|
else
|
|
162335
162542
|
launch();
|
|
162336
162543
|
});
|
|
162337
162544
|
}
|
|
162338
162545
|
if (cursor >= conflicts2.length && active === 0)
|
|
162339
|
-
|
|
162546
|
+
resolve9();
|
|
162340
162547
|
};
|
|
162341
162548
|
launch();
|
|
162342
162549
|
});
|
|
@@ -162569,7 +162776,7 @@ async function resolveConflicts(repoRoot, conflicts2, opts = {}) {
|
|
|
162569
162776
|
const out = [];
|
|
162570
162777
|
let cursor = 0;
|
|
162571
162778
|
let active = 0;
|
|
162572
|
-
await new Promise((
|
|
162779
|
+
await new Promise((resolve9) => {
|
|
162573
162780
|
const launch = () => {
|
|
162574
162781
|
while (active < concurrency && cursor < conflicts2.length) {
|
|
162575
162782
|
const conflict = conflicts2[cursor++];
|
|
@@ -162588,13 +162795,13 @@ async function resolveConflicts(repoRoot, conflicts2, opts = {}) {
|
|
|
162588
162795
|
}).finally(() => {
|
|
162589
162796
|
active--;
|
|
162590
162797
|
if (cursor >= conflicts2.length && active === 0)
|
|
162591
|
-
|
|
162798
|
+
resolve9();
|
|
162592
162799
|
else
|
|
162593
162800
|
launch();
|
|
162594
162801
|
});
|
|
162595
162802
|
}
|
|
162596
162803
|
if (cursor >= conflicts2.length && active === 0)
|
|
162597
|
-
|
|
162804
|
+
resolve9();
|
|
162598
162805
|
};
|
|
162599
162806
|
launch();
|
|
162600
162807
|
});
|
|
@@ -162814,7 +163021,7 @@ async function filterByRelevance(repoRoot, docs, opts = {}) {
|
|
|
162814
163021
|
const verdicts = /* @__PURE__ */ new Map();
|
|
162815
163022
|
let cursor = 0;
|
|
162816
163023
|
let active = 0;
|
|
162817
|
-
await new Promise((
|
|
163024
|
+
await new Promise((resolve9) => {
|
|
162818
163025
|
const launch = () => {
|
|
162819
163026
|
while (active < concurrency && cursor < docs.length) {
|
|
162820
163027
|
const doc = docs[cursor++];
|
|
@@ -162822,7 +163029,7 @@ async function filterByRelevance(repoRoot, docs, opts = {}) {
|
|
|
162822
163029
|
verdicts.set(doc.path, { path: doc.path, include: true, reason: "manual include" });
|
|
162823
163030
|
markDone();
|
|
162824
163031
|
if (cursor >= docs.length && active === 0)
|
|
162825
|
-
|
|
163032
|
+
resolve9();
|
|
162826
163033
|
continue;
|
|
162827
163034
|
}
|
|
162828
163035
|
active++;
|
|
@@ -162838,13 +163045,13 @@ async function filterByRelevance(repoRoot, docs, opts = {}) {
|
|
|
162838
163045
|
markDone();
|
|
162839
163046
|
active--;
|
|
162840
163047
|
if (cursor >= docs.length && active === 0)
|
|
162841
|
-
|
|
163048
|
+
resolve9();
|
|
162842
163049
|
else
|
|
162843
163050
|
launch();
|
|
162844
163051
|
});
|
|
162845
163052
|
}
|
|
162846
163053
|
if (cursor >= docs.length && active === 0)
|
|
162847
|
-
|
|
163054
|
+
resolve9();
|
|
162848
163055
|
};
|
|
162849
163056
|
launch();
|
|
162850
163057
|
});
|
|
@@ -164292,6 +164499,27 @@ not narrow the set.
|
|
|
164292
164499
|
substitute for \`immutable\`. If a derived/server-computed field is also frozen
|
|
164293
164500
|
after creation, emit BOTH \`computed-at\` AND \`immutable\`.
|
|
164294
164501
|
|
|
164502
|
+
**NEVER infer \`immutable\` from what a field IS \u2014 only from what the spec SAYS
|
|
164503
|
+
about changing it.** The following do NOT imply immutability, alone or combined:
|
|
164504
|
+
|
|
164505
|
+
- The field is required (\`Required? yes\` in a field table).
|
|
164506
|
+
- The field is an identifier (\`id\`, \`uuid\`, "identifier of this X").
|
|
164507
|
+
- The field is a timestamp ("when the event happened", \`occurred\`, \`createdAt\`).
|
|
164508
|
+
- The field is client-provided or server-assigned (provenance is not mutability).
|
|
164509
|
+
|
|
164510
|
+
Counter-example \u2014 a field table like:
|
|
164511
|
+
|
|
164512
|
+
| Name | Type | Required? | Description |
|
|
164513
|
+
| -------- | ------ | --------- | ---------------------------------------- |
|
|
164514
|
+
| occurred | String | yes | When the event happened |
|
|
164515
|
+
| id | String | yes | Client-provided identifier of this event |
|
|
164516
|
+
|
|
164517
|
+
asserts NOTHING about mutability. Both fields get plain \`field occurred: string {}\`
|
|
164518
|
+
/ \`field id: string {}\` \u2014 no \`immutable\`, even though an id "sounds" immutable.
|
|
164519
|
+
Emitting un-stated \`immutable\` creates a false drift against every codebase whose
|
|
164520
|
+
model simply doesn't freeze the field. If the spec is silent on mutability, the
|
|
164521
|
+
contract is silent on mutability.
|
|
164522
|
+
|
|
164295
164523
|
# Enum extraction \u2014 required whenever spec defines an enum
|
|
164296
164524
|
|
|
164297
164525
|
Whenever the spec text contains any of:
|
|
@@ -164314,6 +164542,27 @@ data document. If \`Entity:Customer\` references \`Enum:LoyaltyTier\` and the sa
|
|
|
164314
164542
|
slice contains "LoyaltyTier values: standard, silver, gold", emit BOTH the entity
|
|
164315
164543
|
fragment AND the enum fragment.
|
|
164316
164544
|
|
|
164545
|
+
**An enum is a closed set of DATA VALUES the code compares against** (the
|
|
164546
|
+
string/number literals a field is set to or checked against) \u2014 NOT a catalog of
|
|
164547
|
+
code symbols a caller picks between. Before emitting, check what the listed items
|
|
164548
|
+
ARE. Emit nothing when the list is:
|
|
164549
|
+
|
|
164550
|
+
- **Implementation / plugin classes** \u2014 e.g. "run launchers: \`DefaultRunLauncher\`,
|
|
164551
|
+
\`DockerRunLauncher\`, \`K8sRunLauncher\`", storage backends, compute-log managers.
|
|
164552
|
+
These are swappable extension points (a user can add their own); the items are
|
|
164553
|
+
class names, not a closed value set.
|
|
164554
|
+
- **API functions, decorators, or methods** \u2014 e.g. "asset decorators: \`asset\`,
|
|
164555
|
+
\`multi_asset\`, \`graph_asset\`". These are symbols a user calls, not values.
|
|
164556
|
+
- **An incidental excerpt** \u2014 a few items quoted inside a troubleshooting,
|
|
164557
|
+
example, or how-to passage ("relevant event types: \u2026") rather than a
|
|
164558
|
+
definitional "the valid values of X are \u2026". A subset mentioned in passing is
|
|
164559
|
+
not an enum definition.
|
|
164560
|
+
|
|
164561
|
+
Discriminator: if the items are **names of code symbols** (classes / functions a
|
|
164562
|
+
caller selects), do NOT emit an enum. Only emit when the items are **literal data
|
|
164563
|
+
values** the code stores or compares against (config keys, status strings, tag
|
|
164564
|
+
keys, numeric codes).
|
|
164565
|
+
|
|
164317
164566
|
**Never reference an enum without defining it.** Every \`Enum:X\` identifier you
|
|
164318
164567
|
emit (in \`field: Enum:X\` or \`states Enum:X\`) MUST have a matching \`enum X { \u2026 }\`
|
|
164319
164568
|
artifact somewhere in the same slice (or you must assume another slice provides
|
|
@@ -164643,6 +164892,42 @@ Don't emit constants whose value is a function call, expression, or
|
|
|
164643
164892
|
external reference \u2014 only literal values (strings, numbers, booleans,
|
|
164644
164893
|
arrays of literals, flat object literals of literals).
|
|
164645
164894
|
|
|
164895
|
+
**Don't extract constants from customization examples.** A constant asserts
|
|
164896
|
+
"the code MUST hold this value". A doc that shows users how to CUSTOMIZE or
|
|
164897
|
+
OVERRIDE something is asserting the opposite \u2014 "you can put whatever value
|
|
164898
|
+
you want here" \u2014 and its example values are illustrations, not obligations.
|
|
164899
|
+
Skip a candidate value when EITHER signal is present:
|
|
164900
|
+
|
|
164901
|
+
1. **Context signal**: the page title or enclosing section heading describes
|
|
164902
|
+
a customization/override mechanism \u2014 "Customize \u2026", "Override \u2026",
|
|
164903
|
+
"\u2026 template", "\u2026 variables", "Configure your own \u2026", "Example
|
|
164904
|
+
configuration".
|
|
164905
|
+
2. **Shape signal**: the value sits inside a JSON-schema-style variables
|
|
164906
|
+
block, i.e. an object of the form
|
|
164907
|
+
\`"<name>": { "title": \u2026, "description": \u2026, "default": <value>, "type": \u2026 }\`.
|
|
164908
|
+
That quadruple is a schema DECLARING an overridable variable; the
|
|
164909
|
+
\`"default"\` there is a starting point the user is expected to change.
|
|
164910
|
+
|
|
164911
|
+
Counter-example \u2014 a page titled "Customize Base Job Templates" containing:
|
|
164912
|
+
|
|
164913
|
+
\`\`\`json
|
|
164914
|
+
"cpu_request": {
|
|
164915
|
+
"title": "CPU Request",
|
|
164916
|
+
"description": "CPU allocation to request for this pod",
|
|
164917
|
+
"default": "100m",
|
|
164918
|
+
"type": "string"
|
|
164919
|
+
}
|
|
164920
|
+
\`\`\`
|
|
164921
|
+
|
|
164922
|
+
emits NO constant. Both signals fire: the page is a customization guide, and
|
|
164923
|
+
the value is a variables-schema \`default\`. Extracting
|
|
164924
|
+
\`constant cpu_request { expected-value "100m" }\` would demand every codebase
|
|
164925
|
+
hard-code the example \u2014 a guaranteed false drift.
|
|
164926
|
+
|
|
164927
|
+
By contrast, prose like "the scheduler polls every 15 seconds" or "the API
|
|
164928
|
+
version is \`v2\`" in a behavioral spec section IS an assertion about the
|
|
164929
|
+
system \u2014 extract those normally.
|
|
164930
|
+
|
|
164646
164931
|
# ArchitectureDecision \u2014 extract when the spec/ADR fixes a platform choice
|
|
164647
164932
|
|
|
164648
164933
|
A spec or ADR that records a system-wide technology choice \u2014 "we use
|
|
@@ -168850,6 +169135,77 @@ function extractPluginStyleRoutesFromFile(filePath, source, tree) {
|
|
|
168850
169135
|
|
|
168851
169136
|
// packages/contract-verifier/dist/extractor/operation-fastapi.js
|
|
168852
169137
|
var HTTP_METHODS4 = /* @__PURE__ */ new Set(["get", "post", "put", "delete", "patch"]);
|
|
169138
|
+
function extractStarletteRoutesFromFile(filePath, source, tree) {
|
|
169139
|
+
const out = [];
|
|
169140
|
+
walk(tree.rootNode, (node2) => {
|
|
169141
|
+
if (node2.type !== "call")
|
|
169142
|
+
return;
|
|
169143
|
+
const fn = node2.childForFieldName("function");
|
|
169144
|
+
if (fn?.type !== "identifier" || source.slice(fn.startIndex, fn.endIndex) !== "Route")
|
|
169145
|
+
return;
|
|
169146
|
+
const args = node2.childForFieldName("arguments");
|
|
169147
|
+
if (!args)
|
|
169148
|
+
return;
|
|
169149
|
+
const first2 = args.namedChild(0);
|
|
169150
|
+
if (first2?.type !== "string")
|
|
169151
|
+
return;
|
|
169152
|
+
const rawPath = pyStr(first2, source);
|
|
169153
|
+
if (!rawPath.startsWith("/"))
|
|
169154
|
+
return;
|
|
169155
|
+
const second = args.namedChild(1);
|
|
169156
|
+
if (!second || second.type === "keyword_argument")
|
|
169157
|
+
return;
|
|
169158
|
+
const methods = readStarletteMethods(args, source);
|
|
169159
|
+
const identities = starletteIdentitiesForPath(rawPath);
|
|
169160
|
+
const line = node2.startPosition.row + 1;
|
|
169161
|
+
for (const method of methods) {
|
|
169162
|
+
for (const path52 of identities) {
|
|
169163
|
+
out.push({
|
|
169164
|
+
identity: `${method} ${path52}`,
|
|
169165
|
+
contract: {
|
|
169166
|
+
protocol: "http",
|
|
169167
|
+
method,
|
|
169168
|
+
path: path52,
|
|
169169
|
+
responses: [],
|
|
169170
|
+
tags: []
|
|
169171
|
+
},
|
|
169172
|
+
filePath,
|
|
169173
|
+
declarationLine: line,
|
|
169174
|
+
observed: { queryParams: [], numericClamps: [], hasClampCall: false }
|
|
169175
|
+
});
|
|
169176
|
+
}
|
|
169177
|
+
}
|
|
169178
|
+
});
|
|
169179
|
+
return out;
|
|
169180
|
+
}
|
|
169181
|
+
function readStarletteMethods(args, source) {
|
|
169182
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
169183
|
+
const a = args.namedChild(i);
|
|
169184
|
+
if (a?.type !== "keyword_argument")
|
|
169185
|
+
continue;
|
|
169186
|
+
const name = a.childForFieldName("name");
|
|
169187
|
+
if (!name || source.slice(name.startIndex, name.endIndex) !== "methods")
|
|
169188
|
+
continue;
|
|
169189
|
+
const value = a.childForFieldName("value");
|
|
169190
|
+
if (value?.type !== "list")
|
|
169191
|
+
return ["GET"];
|
|
169192
|
+
const methods = [];
|
|
169193
|
+
for (let j = 0; j < value.namedChildCount; j++) {
|
|
169194
|
+
const el = value.namedChild(j);
|
|
169195
|
+
if (el?.type === "string")
|
|
169196
|
+
methods.push(pyStr(el, source).toUpperCase());
|
|
169197
|
+
}
|
|
169198
|
+
return methods.length > 0 ? methods : ["GET"];
|
|
169199
|
+
}
|
|
169200
|
+
return ["GET"];
|
|
169201
|
+
}
|
|
169202
|
+
function starletteIdentitiesForPath(rawPath) {
|
|
169203
|
+
const catchAll = rawPath.match(/^(\/.*\/)\{\w+:path\}$/);
|
|
169204
|
+
if (catchAll) {
|
|
169205
|
+
return [catchAll[1].replace(/\{(\w+):[^}]+\}/g, "{$1}")];
|
|
169206
|
+
}
|
|
169207
|
+
return [rawPath.replace(/\{(\w+):[^}]+\}/g, "{$1}")];
|
|
169208
|
+
}
|
|
168853
169209
|
function extractFastApiOperationsFromFile(filePath, source, tree) {
|
|
168854
169210
|
const routers = collectRouters(tree.rootNode, source);
|
|
168855
169211
|
const stringVars = collectStringVars(tree.rootNode, source);
|
|
@@ -172359,11 +172715,81 @@ function extractIdProperty(obj) {
|
|
|
172359
172715
|
return null;
|
|
172360
172716
|
}
|
|
172361
172717
|
|
|
172718
|
+
// packages/contract-verifier/dist/extractor/py-string-resolver.js
|
|
172719
|
+
var MAX_DEPTH3 = 4;
|
|
172720
|
+
function collectStringConstantTable(rootNode, source) {
|
|
172721
|
+
const table = /* @__PURE__ */ new Map();
|
|
172722
|
+
for (let i = 0; i < rootNode.namedChildCount; i++) {
|
|
172723
|
+
const stmt = rootNode.namedChild(i);
|
|
172724
|
+
if (stmt?.type !== "expression_statement")
|
|
172725
|
+
continue;
|
|
172726
|
+
const assign = stmt.namedChild(0);
|
|
172727
|
+
if (assign?.type !== "assignment")
|
|
172728
|
+
continue;
|
|
172729
|
+
const left = assign.childForFieldName("left");
|
|
172730
|
+
if (left?.type !== "identifier")
|
|
172731
|
+
continue;
|
|
172732
|
+
const right = assign.childForFieldName("right");
|
|
172733
|
+
if (right?.type !== "string")
|
|
172734
|
+
continue;
|
|
172735
|
+
const name = source.slice(left.startIndex, left.endIndex);
|
|
172736
|
+
if (table.has(name))
|
|
172737
|
+
continue;
|
|
172738
|
+
table.set(name, right);
|
|
172739
|
+
}
|
|
172740
|
+
return table;
|
|
172741
|
+
}
|
|
172742
|
+
function stringValue(node2, source, table) {
|
|
172743
|
+
return resolve8(node2, source, table, 0);
|
|
172744
|
+
}
|
|
172745
|
+
function resolve8(node2, source, table, depth) {
|
|
172746
|
+
if (node2.type !== "string")
|
|
172747
|
+
return null;
|
|
172748
|
+
if (depth > MAX_DEPTH3)
|
|
172749
|
+
return null;
|
|
172750
|
+
let content = "";
|
|
172751
|
+
let sawContent = false;
|
|
172752
|
+
for (let i = 0; i < node2.namedChildCount; i++) {
|
|
172753
|
+
const c = node2.namedChild(i);
|
|
172754
|
+
if (!c)
|
|
172755
|
+
continue;
|
|
172756
|
+
if (c.type === "string_content") {
|
|
172757
|
+
content += source.slice(c.startIndex, c.endIndex);
|
|
172758
|
+
sawContent = true;
|
|
172759
|
+
continue;
|
|
172760
|
+
}
|
|
172761
|
+
if (c.type === "interpolation") {
|
|
172762
|
+
if (c.namedChildren.some((g) => g?.type === "format_specifier"))
|
|
172763
|
+
return null;
|
|
172764
|
+
const expr = c.namedChild(0);
|
|
172765
|
+
if (expr?.type !== "identifier" || !table)
|
|
172766
|
+
return null;
|
|
172767
|
+
const referent = table.get(source.slice(expr.startIndex, expr.endIndex));
|
|
172768
|
+
if (!referent)
|
|
172769
|
+
return null;
|
|
172770
|
+
const resolved = resolve8(referent, source, table, depth + 1);
|
|
172771
|
+
if (resolved === null)
|
|
172772
|
+
return null;
|
|
172773
|
+
content += resolved;
|
|
172774
|
+
sawContent = true;
|
|
172775
|
+
continue;
|
|
172776
|
+
}
|
|
172777
|
+
if (c.type === "format_specifier")
|
|
172778
|
+
return null;
|
|
172779
|
+
}
|
|
172780
|
+
if (sawContent)
|
|
172781
|
+
return content;
|
|
172782
|
+
const raw = source.slice(node2.startIndex, node2.endIndex);
|
|
172783
|
+
const m = raw.match(/^[a-zA-Z]*('''|"""|'|")([\s\S]*)\1$/);
|
|
172784
|
+
return m ? m[2] : null;
|
|
172785
|
+
}
|
|
172786
|
+
|
|
172362
172787
|
// packages/contract-verifier/dist/extractor/enum/py-enums.js
|
|
172363
172788
|
var ENUM_CONVENTION_NAME2 = /^(?:VALID|ALLOWED|KNOWN|ENUM)_/i;
|
|
172364
172789
|
var ENUM_CONVENTION_SUFFIX2 = /_(?:VALUES|SET|CLASSIFICATIONS|STATUSES|KINDS|TYPES|OPTIONS|CHOICES)$/i;
|
|
172365
172790
|
function extractPyEnumsFromFile(filePath, source, tree) {
|
|
172366
172791
|
const out = [];
|
|
172792
|
+
const stringTable = collectStringConstantTable(tree.rootNode, source);
|
|
172367
172793
|
walk7(tree.rootNode, (node2) => {
|
|
172368
172794
|
if (node2.type === "class_definition") {
|
|
172369
172795
|
const decl = extractEnumClass(node2, filePath, source);
|
|
@@ -172379,6 +172805,305 @@ function extractPyEnumsFromFile(filePath, source, tree) {
|
|
|
172379
172805
|
}
|
|
172380
172806
|
return true;
|
|
172381
172807
|
});
|
|
172808
|
+
out.push(...synthesizeInstanceRegistryEnum(tree.rootNode, filePath, source));
|
|
172809
|
+
out.push(...synthesizeDiscriminatedUnionEnum(tree.rootNode, filePath, source));
|
|
172810
|
+
out.push(...synthesizeConstantClusterEnums(tree.rootNode, filePath, source, stringTable));
|
|
172811
|
+
return out;
|
|
172812
|
+
}
|
|
172813
|
+
function synthesizeDiscriminatedUnionEnum(root, filePath, source) {
|
|
172814
|
+
const discriminatorOf = /* @__PURE__ */ new Map();
|
|
172815
|
+
walk7(root, (node2) => {
|
|
172816
|
+
if (node2.type !== "class_definition")
|
|
172817
|
+
return true;
|
|
172818
|
+
const className = textOfField(node2, "name", source);
|
|
172819
|
+
const body = node2.childForFieldName("body");
|
|
172820
|
+
if (!className || !body)
|
|
172821
|
+
return true;
|
|
172822
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
172823
|
+
const stmt = body.namedChild(i);
|
|
172824
|
+
if (stmt?.type !== "expression_statement")
|
|
172825
|
+
continue;
|
|
172826
|
+
const assign = stmt.namedChild(0);
|
|
172827
|
+
if (assign?.type !== "assignment")
|
|
172828
|
+
continue;
|
|
172829
|
+
const left = assign.childForFieldName("left");
|
|
172830
|
+
const typeAnn = assign.childForFieldName("type");
|
|
172831
|
+
if (left?.type !== "identifier" || !typeAnn)
|
|
172832
|
+
continue;
|
|
172833
|
+
if (source.slice(left.startIndex, left.endIndex) !== "type")
|
|
172834
|
+
continue;
|
|
172835
|
+
const lit = literalStringOfAnnotation(typeAnn, source);
|
|
172836
|
+
if (lit !== null)
|
|
172837
|
+
discriminatorOf.set(className, lit);
|
|
172838
|
+
}
|
|
172839
|
+
return true;
|
|
172840
|
+
});
|
|
172841
|
+
if (discriminatorOf.size === 0)
|
|
172842
|
+
return [];
|
|
172843
|
+
const out = [];
|
|
172844
|
+
for (let i = 0; i < root.namedChildCount; i++) {
|
|
172845
|
+
const stmt = root.namedChild(i);
|
|
172846
|
+
if (stmt?.type !== "expression_statement")
|
|
172847
|
+
continue;
|
|
172848
|
+
const assign = stmt.namedChild(0);
|
|
172849
|
+
if (assign?.type !== "assignment")
|
|
172850
|
+
continue;
|
|
172851
|
+
const left = assign.childForFieldName("left");
|
|
172852
|
+
if (left?.type !== "identifier")
|
|
172853
|
+
continue;
|
|
172854
|
+
const aliasName = source.slice(left.startIndex, left.endIndex);
|
|
172855
|
+
const right = assign.childForFieldName("right");
|
|
172856
|
+
if (!right)
|
|
172857
|
+
continue;
|
|
172858
|
+
const memberClasses = unionMemberIdentifiers(right, source);
|
|
172859
|
+
if (memberClasses.length === 0)
|
|
172860
|
+
continue;
|
|
172861
|
+
const values = memberClasses.map((m) => discriminatorOf.get(m)).filter((v) => v !== void 0);
|
|
172862
|
+
if (values.length < 3)
|
|
172863
|
+
continue;
|
|
172864
|
+
out.push(mkEnum2(aliasName, values, "py-discriminated-union", root, filePath));
|
|
172865
|
+
}
|
|
172866
|
+
return out;
|
|
172867
|
+
}
|
|
172868
|
+
function literalStringOfAnnotation(ann, source) {
|
|
172869
|
+
let node2 = ann;
|
|
172870
|
+
if (node2.type === "type")
|
|
172871
|
+
node2 = node2.namedChild(0);
|
|
172872
|
+
if (!node2 || node2.type !== "generic_type" && node2.type !== "subscript")
|
|
172873
|
+
return null;
|
|
172874
|
+
const base = node2.namedChild(0);
|
|
172875
|
+
if (!base || !source.slice(base.startIndex, base.endIndex).endsWith("Literal"))
|
|
172876
|
+
return null;
|
|
172877
|
+
const strings = collectStringsDeep(node2, source);
|
|
172878
|
+
return strings.length === 1 ? strings[0] : null;
|
|
172879
|
+
}
|
|
172880
|
+
function collectStringsDeep(node2, source) {
|
|
172881
|
+
const out = [];
|
|
172882
|
+
const visit = (n) => {
|
|
172883
|
+
if (n.type === "string") {
|
|
172884
|
+
const v = stringValue(n, source);
|
|
172885
|
+
if (v !== null)
|
|
172886
|
+
out.push(v);
|
|
172887
|
+
return;
|
|
172888
|
+
}
|
|
172889
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
172890
|
+
const c = n.namedChild(i);
|
|
172891
|
+
if (c)
|
|
172892
|
+
visit(c);
|
|
172893
|
+
}
|
|
172894
|
+
};
|
|
172895
|
+
visit(node2);
|
|
172896
|
+
return out;
|
|
172897
|
+
}
|
|
172898
|
+
function unionMemberIdentifiers(node2, source) {
|
|
172899
|
+
if (node2.type === "subscript") {
|
|
172900
|
+
const value = node2.childForFieldName("value");
|
|
172901
|
+
if (value && source.slice(value.startIndex, value.endIndex).endsWith("Union")) {
|
|
172902
|
+
const out = [];
|
|
172903
|
+
for (let i = 0; i < node2.namedChildCount; i++) {
|
|
172904
|
+
const c = node2.namedChild(i);
|
|
172905
|
+
if (c && c !== value)
|
|
172906
|
+
collectTypeIdentifiers(c, out, source);
|
|
172907
|
+
}
|
|
172908
|
+
return out;
|
|
172909
|
+
}
|
|
172910
|
+
return [];
|
|
172911
|
+
}
|
|
172912
|
+
if (node2.type === "binary_operator") {
|
|
172913
|
+
const text = source.slice(node2.startIndex, node2.endIndex);
|
|
172914
|
+
if (text.includes("|")) {
|
|
172915
|
+
const out = [];
|
|
172916
|
+
collectTypeIdentifiers(node2, out, source);
|
|
172917
|
+
return out;
|
|
172918
|
+
}
|
|
172919
|
+
}
|
|
172920
|
+
return [];
|
|
172921
|
+
}
|
|
172922
|
+
function collectTypeIdentifiers(node2, out, source) {
|
|
172923
|
+
if (node2.type === "identifier") {
|
|
172924
|
+
out.push(source.slice(node2.startIndex, node2.endIndex));
|
|
172925
|
+
return;
|
|
172926
|
+
}
|
|
172927
|
+
for (let i = 0; i < node2.namedChildCount; i++) {
|
|
172928
|
+
const c = node2.namedChild(i);
|
|
172929
|
+
if (c)
|
|
172930
|
+
collectTypeIdentifiers(c, out, source);
|
|
172931
|
+
}
|
|
172932
|
+
}
|
|
172933
|
+
var MIN_PREFIX = 6;
|
|
172934
|
+
var MIN_CLUSTER_MEMBERS = 3;
|
|
172935
|
+
var MAX_CLUSTER_MEMBERS = 200;
|
|
172936
|
+
function synthesizeConstantClusterEnums(root, filePath, source, stringTable) {
|
|
172937
|
+
const named = [];
|
|
172938
|
+
for (const [name, node2] of stringTable) {
|
|
172939
|
+
const v = stringValue(node2, source, stringTable);
|
|
172940
|
+
if (v === null)
|
|
172941
|
+
continue;
|
|
172942
|
+
named.push({ name, value: v });
|
|
172943
|
+
}
|
|
172944
|
+
if (named.length < MIN_CLUSTER_MEMBERS)
|
|
172945
|
+
return [];
|
|
172946
|
+
named.sort((a, b) => a.value < b.value ? -1 : a.value > b.value ? 1 : 0);
|
|
172947
|
+
const clusters = [];
|
|
172948
|
+
let i = 0;
|
|
172949
|
+
while (i < named.length) {
|
|
172950
|
+
let j = i + 1;
|
|
172951
|
+
let prefix = named[i].value;
|
|
172952
|
+
while (j < named.length) {
|
|
172953
|
+
const next = commonPrefix(prefix, named[j].value);
|
|
172954
|
+
if (next.length < MIN_PREFIX)
|
|
172955
|
+
break;
|
|
172956
|
+
prefix = next;
|
|
172957
|
+
j++;
|
|
172958
|
+
}
|
|
172959
|
+
if (j - i >= MIN_CLUSTER_MEMBERS && j - i <= MAX_CLUSTER_MEMBERS && prefix.length >= MIN_PREFIX) {
|
|
172960
|
+
clusters.push({ prefix, members: named.slice(i, j) });
|
|
172961
|
+
}
|
|
172962
|
+
i = j === i + 1 ? i + 1 : j;
|
|
172963
|
+
}
|
|
172964
|
+
const out = [];
|
|
172965
|
+
for (const cluster of clusters) {
|
|
172966
|
+
const realMembers = cluster.members.filter((m) => m.value.length > cluster.prefix.length);
|
|
172967
|
+
if (realMembers.length < MIN_CLUSTER_MEMBERS)
|
|
172968
|
+
continue;
|
|
172969
|
+
let prefix = realMembers[0].value;
|
|
172970
|
+
for (let k = 1; k < realMembers.length; k++) {
|
|
172971
|
+
prefix = commonPrefix(prefix, realMembers[k].value);
|
|
172972
|
+
if (prefix.length < MIN_PREFIX)
|
|
172973
|
+
break;
|
|
172974
|
+
}
|
|
172975
|
+
if (prefix.length < MIN_PREFIX)
|
|
172976
|
+
continue;
|
|
172977
|
+
const trailingDelim = /[/\-_.:]$/.test(prefix);
|
|
172978
|
+
const allCleanTails = trailingDelim || realMembers.every((m) => /^[A-Za-z0-9_\-./:]+$/.test(m.value.slice(prefix.length)));
|
|
172979
|
+
if (!allCleanTails)
|
|
172980
|
+
continue;
|
|
172981
|
+
const trimmedName = prefix.replace(/[^A-Za-z0-9]+$/, "") || prefix;
|
|
172982
|
+
const firstNode = stringTable.get(realMembers[0].name);
|
|
172983
|
+
const lastNode = stringTable.get(realMembers[realMembers.length - 1].name);
|
|
172984
|
+
out.push({
|
|
172985
|
+
name: trimmedName,
|
|
172986
|
+
values: [...new Set(realMembers.map((m) => m.value))].sort(),
|
|
172987
|
+
shape: "py-constant-cluster",
|
|
172988
|
+
source: {
|
|
172989
|
+
filePath,
|
|
172990
|
+
lineStart: firstNode ? firstNode.startPosition.row + 1 : 1,
|
|
172991
|
+
lineEnd: lastNode ? lastNode.endPosition.row + 1 : 1
|
|
172992
|
+
}
|
|
172993
|
+
});
|
|
172994
|
+
}
|
|
172995
|
+
return out;
|
|
172996
|
+
}
|
|
172997
|
+
function commonPrefix(a, b) {
|
|
172998
|
+
const len = Math.min(a.length, b.length);
|
|
172999
|
+
let i = 0;
|
|
173000
|
+
while (i < len && a.charCodeAt(i) === b.charCodeAt(i))
|
|
173001
|
+
i++;
|
|
173002
|
+
return a.slice(0, i);
|
|
173003
|
+
}
|
|
173004
|
+
function synthesizeInstanceRegistryEnum(root, filePath, source) {
|
|
173005
|
+
const baseOf = /* @__PURE__ */ new Map();
|
|
173006
|
+
for (let i = 0; i < root.namedChildCount; i++) {
|
|
173007
|
+
const child = root.namedChild(i);
|
|
173008
|
+
const node2 = child?.type === "class_definition" ? child : child?.type === "decorated_definition" ? child.childForFieldName("definition") : null;
|
|
173009
|
+
if (node2?.type !== "class_definition")
|
|
173010
|
+
continue;
|
|
173011
|
+
const name = textOfField(node2, "name", source);
|
|
173012
|
+
const supers = node2.childForFieldName("superclasses");
|
|
173013
|
+
if (!name || !supers)
|
|
173014
|
+
continue;
|
|
173015
|
+
const first2 = supers.namedChild(0);
|
|
173016
|
+
if (first2?.type === "identifier")
|
|
173017
|
+
baseOf.set(name, source.slice(first2.startIndex, first2.endIndex));
|
|
173018
|
+
}
|
|
173019
|
+
const subclassCount = /* @__PURE__ */ new Map();
|
|
173020
|
+
for (const base of baseOf.values())
|
|
173021
|
+
subclassCount.set(base, (subclassCount.get(base) ?? 0) + 1);
|
|
173022
|
+
const categoricalBases = new Set([...subclassCount].filter(([, n]) => n >= 2).map(([b]) => b));
|
|
173023
|
+
if (categoricalBases.size === 0)
|
|
173024
|
+
return [];
|
|
173025
|
+
const resolveBase = (cls) => {
|
|
173026
|
+
let cur = cls;
|
|
173027
|
+
for (let hops = 0; hops < 8; hops++) {
|
|
173028
|
+
if (categoricalBases.has(cur))
|
|
173029
|
+
return cur;
|
|
173030
|
+
const next = baseOf.get(cur);
|
|
173031
|
+
if (!next)
|
|
173032
|
+
return null;
|
|
173033
|
+
cur = next;
|
|
173034
|
+
}
|
|
173035
|
+
return null;
|
|
173036
|
+
};
|
|
173037
|
+
const group = /* @__PURE__ */ new Map();
|
|
173038
|
+
const memberBase = /* @__PURE__ */ new Map();
|
|
173039
|
+
const deferred2 = [];
|
|
173040
|
+
for (let i = 0; i < root.namedChildCount; i++) {
|
|
173041
|
+
const stmt = root.namedChild(i);
|
|
173042
|
+
if (stmt?.type !== "expression_statement")
|
|
173043
|
+
continue;
|
|
173044
|
+
const assign = stmt.namedChild(0);
|
|
173045
|
+
if (assign?.type !== "assignment")
|
|
173046
|
+
continue;
|
|
173047
|
+
if (assign.childForFieldName("type"))
|
|
173048
|
+
continue;
|
|
173049
|
+
const left = assign.childForFieldName("left");
|
|
173050
|
+
if (left?.type !== "identifier")
|
|
173051
|
+
continue;
|
|
173052
|
+
const name = source.slice(left.startIndex, left.endIndex);
|
|
173053
|
+
if (!/^[A-Z][A-Z0-9_]*$/.test(name))
|
|
173054
|
+
continue;
|
|
173055
|
+
const right = assign.childForFieldName("right");
|
|
173056
|
+
if (!right)
|
|
173057
|
+
continue;
|
|
173058
|
+
if (right.type === "call") {
|
|
173059
|
+
const fn = right.childForFieldName("function");
|
|
173060
|
+
if (fn?.type !== "identifier")
|
|
173061
|
+
continue;
|
|
173062
|
+
const ctor = source.slice(fn.startIndex, fn.endIndex);
|
|
173063
|
+
const base = resolveBase(ctor);
|
|
173064
|
+
if (base) {
|
|
173065
|
+
if (!group.has(base))
|
|
173066
|
+
group.set(base, []);
|
|
173067
|
+
group.get(base).push(name);
|
|
173068
|
+
memberBase.set(name, base);
|
|
173069
|
+
}
|
|
173070
|
+
} else {
|
|
173071
|
+
deferred2.push({ name, rhs: right });
|
|
173072
|
+
}
|
|
173073
|
+
}
|
|
173074
|
+
for (const { name, rhs } of deferred2) {
|
|
173075
|
+
const ids = collectIdentifiers3(rhs, source);
|
|
173076
|
+
if (ids.length === 0)
|
|
173077
|
+
continue;
|
|
173078
|
+
const bases = new Set(ids.map((id) => memberBase.get(id)).filter((b) => !!b));
|
|
173079
|
+
if (bases.size === 1) {
|
|
173080
|
+
const base = [...bases][0];
|
|
173081
|
+
group.get(base).push(name);
|
|
173082
|
+
memberBase.set(name, base);
|
|
173083
|
+
}
|
|
173084
|
+
}
|
|
173085
|
+
const out = [];
|
|
173086
|
+
for (const [base, members] of group) {
|
|
173087
|
+
if (members.length < 3)
|
|
173088
|
+
continue;
|
|
173089
|
+
out.push(mkEnum2(base, members, "py-instance-registry", root, filePath));
|
|
173090
|
+
}
|
|
173091
|
+
return out;
|
|
173092
|
+
}
|
|
173093
|
+
function collectIdentifiers3(node2, source) {
|
|
173094
|
+
const out = [];
|
|
173095
|
+
const visit = (n) => {
|
|
173096
|
+
if (n.type === "identifier") {
|
|
173097
|
+
out.push(source.slice(n.startIndex, n.endIndex));
|
|
173098
|
+
return;
|
|
173099
|
+
}
|
|
173100
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
173101
|
+
const c = n.namedChild(i);
|
|
173102
|
+
if (c)
|
|
173103
|
+
visit(c);
|
|
173104
|
+
}
|
|
173105
|
+
};
|
|
173106
|
+
visit(node2);
|
|
172382
173107
|
return out;
|
|
172383
173108
|
}
|
|
172384
173109
|
function extractEnumClass(node2, filePath, source) {
|
|
@@ -172455,6 +173180,22 @@ function extractAssignmentEnum(node2, filePath, source) {
|
|
|
172455
173180
|
}
|
|
172456
173181
|
return null;
|
|
172457
173182
|
}
|
|
173183
|
+
if (right.type === "set" || right.type === "list") {
|
|
173184
|
+
const attrs = attributeSetValues(right, source);
|
|
173185
|
+
if (attrs) {
|
|
173186
|
+
return mkEnum2(name, attrs, right.type === "set" ? "py-set" : "py-list", node2, filePath);
|
|
173187
|
+
}
|
|
173188
|
+
}
|
|
173189
|
+
const diff = parseSetDifference(right, source);
|
|
173190
|
+
if (diff) {
|
|
173191
|
+
return {
|
|
173192
|
+
name,
|
|
173193
|
+
values: [],
|
|
173194
|
+
shape: "py-set-difference",
|
|
173195
|
+
source: { filePath, lineStart: node2.startPosition.row + 1, lineEnd: node2.endPosition.row + 1 },
|
|
173196
|
+
unresolved: diff
|
|
173197
|
+
};
|
|
173198
|
+
}
|
|
172458
173199
|
if (!nameLooksLikeEnumConst2(name))
|
|
172459
173200
|
return null;
|
|
172460
173201
|
if (right.type === "set" || right.type === "list") {
|
|
@@ -172481,6 +173222,60 @@ function extractAssignmentEnum(node2, filePath, source) {
|
|
|
172481
173222
|
function nameLooksLikeEnumConst2(name) {
|
|
172482
173223
|
return ENUM_CONVENTION_NAME2.test(name) || ENUM_CONVENTION_SUFFIX2.test(name);
|
|
172483
173224
|
}
|
|
173225
|
+
function attributeSetValues(node2, source) {
|
|
173226
|
+
const out = [];
|
|
173227
|
+
for (let i = 0; i < node2.namedChildCount; i++) {
|
|
173228
|
+
const c = node2.namedChild(i);
|
|
173229
|
+
if (!c)
|
|
173230
|
+
continue;
|
|
173231
|
+
if (c.type !== "attribute")
|
|
173232
|
+
return null;
|
|
173233
|
+
const attr = c.childForFieldName("attribute");
|
|
173234
|
+
if (!attr)
|
|
173235
|
+
return null;
|
|
173236
|
+
out.push(source.slice(attr.startIndex, attr.endIndex));
|
|
173237
|
+
}
|
|
173238
|
+
return out.length >= 2 ? out : null;
|
|
173239
|
+
}
|
|
173240
|
+
function parseSetDifference(node2, source) {
|
|
173241
|
+
let n = node2;
|
|
173242
|
+
if (n.type === "call") {
|
|
173243
|
+
const fn = n.childForFieldName("function");
|
|
173244
|
+
const fnName = fn ? source.slice(fn.startIndex, fn.endIndex) : "";
|
|
173245
|
+
if (/^(list|set|frozenset|tuple)$/.test(fnName)) {
|
|
173246
|
+
const inner = n.childForFieldName("arguments")?.namedChild(0);
|
|
173247
|
+
if (inner)
|
|
173248
|
+
n = inner;
|
|
173249
|
+
}
|
|
173250
|
+
}
|
|
173251
|
+
if (n.type !== "binary_operator")
|
|
173252
|
+
return null;
|
|
173253
|
+
if (!source.slice(n.startIndex, n.endIndex).includes("-"))
|
|
173254
|
+
return null;
|
|
173255
|
+
const left = n.childForFieldName("left");
|
|
173256
|
+
const right = n.childForFieldName("right");
|
|
173257
|
+
if (!left || !right)
|
|
173258
|
+
return null;
|
|
173259
|
+
const base = enumOperandName(left, source);
|
|
173260
|
+
const minus = enumOperandName(right, source);
|
|
173261
|
+
return base && minus ? { base, minus } : null;
|
|
173262
|
+
}
|
|
173263
|
+
function enumOperandName(node2, source) {
|
|
173264
|
+
let n = node2;
|
|
173265
|
+
if (n.type === "call") {
|
|
173266
|
+
const inner = n.childForFieldName("arguments")?.namedChild(0);
|
|
173267
|
+
if (inner)
|
|
173268
|
+
n = inner;
|
|
173269
|
+
}
|
|
173270
|
+
if (n.type === "identifier")
|
|
173271
|
+
return source.slice(n.startIndex, n.endIndex);
|
|
173272
|
+
if (n.type === "attribute") {
|
|
173273
|
+
const a = n.childForFieldName("attribute");
|
|
173274
|
+
if (a)
|
|
173275
|
+
return source.slice(a.startIndex, a.endIndex);
|
|
173276
|
+
}
|
|
173277
|
+
return null;
|
|
173278
|
+
}
|
|
172484
173279
|
function collectStringChildren(node2, source) {
|
|
172485
173280
|
const out = [];
|
|
172486
173281
|
for (let i = 0; i < node2.namedChildCount; i++) {
|
|
@@ -172493,24 +173288,6 @@ function collectStringChildren(node2, source) {
|
|
|
172493
173288
|
}
|
|
172494
173289
|
return out;
|
|
172495
173290
|
}
|
|
172496
|
-
function stringValue(node2, source) {
|
|
172497
|
-
let content = "";
|
|
172498
|
-
let sawContent = false;
|
|
172499
|
-
for (let i = 0; i < node2.namedChildCount; i++) {
|
|
172500
|
-
const c = node2.namedChild(i);
|
|
172501
|
-
if (c?.type === "string_content") {
|
|
172502
|
-
content += source.slice(c.startIndex, c.endIndex);
|
|
172503
|
-
sawContent = true;
|
|
172504
|
-
} else if (c?.type === "interpolation" || c?.type === "format_specifier") {
|
|
172505
|
-
return null;
|
|
172506
|
-
}
|
|
172507
|
-
}
|
|
172508
|
-
if (sawContent)
|
|
172509
|
-
return content;
|
|
172510
|
-
const raw = source.slice(node2.startIndex, node2.endIndex);
|
|
172511
|
-
const m = raw.match(/^[a-zA-Z]*('''|"""|'|")([\s\S]*)\1$/);
|
|
172512
|
-
return m ? m[2] : null;
|
|
172513
|
-
}
|
|
172514
173291
|
function textOfField(node2, field, source) {
|
|
172515
173292
|
const c = node2.childForFieldName(field);
|
|
172516
173293
|
return c ? source.slice(c.startIndex, c.endIndex) : "";
|
|
@@ -172567,8 +173344,27 @@ async function extractEnumsFromDir(rootDir) {
|
|
|
172567
173344
|
source: { filePath: entries[0].filePath, lineStart: 1, lineEnd: 1 }
|
|
172568
173345
|
});
|
|
172569
173346
|
}
|
|
172570
|
-
const
|
|
173347
|
+
const norm = (s) => s.replace(/[^A-Za-z0-9]/g, "").toLowerCase();
|
|
173348
|
+
const valuesByName = /* @__PURE__ */ new Map();
|
|
173349
|
+
for (const e of raw) {
|
|
173350
|
+
if (e.shape !== "py-set-difference")
|
|
173351
|
+
valuesByName.set(norm(e.name), e.values);
|
|
173352
|
+
}
|
|
172571
173353
|
for (const e of raw) {
|
|
173354
|
+
if (e.shape !== "py-set-difference" || !e.unresolved)
|
|
173355
|
+
continue;
|
|
173356
|
+
const baseVals = valuesByName.get(norm(e.unresolved.base));
|
|
173357
|
+
const minusVals = valuesByName.get(norm(e.unresolved.minus));
|
|
173358
|
+
if (baseVals && minusVals) {
|
|
173359
|
+
const minusSet = new Set(minusVals.map((v) => v.replace(/[^A-Za-z0-9]/g, "").toLowerCase()));
|
|
173360
|
+
e.values = [...new Set(baseVals.filter((v) => !minusSet.has(v.replace(/[^A-Za-z0-9]/g, "").toLowerCase())))].sort();
|
|
173361
|
+
e.shape = "py-set";
|
|
173362
|
+
delete e.unresolved;
|
|
173363
|
+
}
|
|
173364
|
+
}
|
|
173365
|
+
const resolved = raw.filter((e) => e.shape !== "py-set-difference");
|
|
173366
|
+
const seen = /* @__PURE__ */ new Map();
|
|
173367
|
+
for (const e of resolved) {
|
|
172572
173368
|
const key2 = `${e.name}|${e.values.join(",")}`;
|
|
172573
173369
|
if (!seen.has(key2))
|
|
172574
173370
|
seen.set(key2, e);
|
|
@@ -173226,6 +174022,13 @@ function walk9(node2, visit) {
|
|
|
173226
174022
|
var UNPARSEABLE2 = Symbol("unparseable");
|
|
173227
174023
|
function extractPyConstantsFromFile(filePath, source, tree) {
|
|
173228
174024
|
const out = [];
|
|
174025
|
+
const stringTable = collectStringConstantTable(tree.rootNode, source);
|
|
174026
|
+
walk10(tree.rootNode, (node2) => {
|
|
174027
|
+
if (node2.type === "class_definition") {
|
|
174028
|
+
out.push(...extractSettingsFields(node2, source, filePath, stringTable));
|
|
174029
|
+
}
|
|
174030
|
+
return true;
|
|
174031
|
+
});
|
|
173229
174032
|
walk10(tree.rootNode, (node2) => {
|
|
173230
174033
|
if (node2.type !== "assignment")
|
|
173231
174034
|
return true;
|
|
@@ -173235,23 +174038,169 @@ function extractPyConstantsFromFile(filePath, source, tree) {
|
|
|
173235
174038
|
const right = node2.childForFieldName("right");
|
|
173236
174039
|
if (!right)
|
|
173237
174040
|
return true;
|
|
173238
|
-
const
|
|
173239
|
-
|
|
174041
|
+
const name = source.slice(left.startIndex, left.endIndex);
|
|
174042
|
+
const pos = { filePath, lineStart: node2.startPosition.row + 1, lineEnd: node2.endPosition.row + 1 };
|
|
174043
|
+
const value = parseLiteral(right, source, stringTable);
|
|
174044
|
+
if (value !== UNPARSEABLE2) {
|
|
174045
|
+
out.push({ name, value, shape: "const-literal", source: pos });
|
|
174046
|
+
return true;
|
|
174047
|
+
}
|
|
174048
|
+
if (!node2.childForFieldName("type"))
|
|
174049
|
+
return true;
|
|
174050
|
+
if (right.type !== "call")
|
|
174051
|
+
return true;
|
|
174052
|
+
const fn = right.childForFieldName("function");
|
|
174053
|
+
if (!fn)
|
|
173240
174054
|
return true;
|
|
174055
|
+
if (!source.slice(fn.startIndex, fn.endIndex).endsWith("Field"))
|
|
174056
|
+
return true;
|
|
174057
|
+
const callArgs = right.childForFieldName("arguments");
|
|
174058
|
+
if (!callArgs)
|
|
174059
|
+
return true;
|
|
174060
|
+
let defaultVal = UNPARSEABLE2;
|
|
174061
|
+
const aliasStrings = [];
|
|
174062
|
+
for (let i = 0; i < callArgs.namedChildCount; i++) {
|
|
174063
|
+
const arg = callArgs.namedChild(i);
|
|
174064
|
+
if (arg?.type !== "keyword_argument")
|
|
174065
|
+
continue;
|
|
174066
|
+
const kwName = arg.childForFieldName("name");
|
|
174067
|
+
const kwVal = arg.childForFieldName("value");
|
|
174068
|
+
if (!kwName || !kwVal)
|
|
174069
|
+
continue;
|
|
174070
|
+
const kw = source.slice(kwName.startIndex, kwName.endIndex);
|
|
174071
|
+
if (kw === "default" && defaultVal === UNPARSEABLE2) {
|
|
174072
|
+
defaultVal = parseLiteral(kwVal, source, stringTable);
|
|
174073
|
+
} else if (kw === "validation_alias") {
|
|
174074
|
+
aliasStrings.push(...extractAliasChoiceStrings(kwVal, source, stringTable));
|
|
174075
|
+
}
|
|
174076
|
+
}
|
|
174077
|
+
if (defaultVal === UNPARSEABLE2)
|
|
174078
|
+
return true;
|
|
174079
|
+
out.push({ name, value: defaultVal, shape: "const-literal", source: pos });
|
|
174080
|
+
for (const alias of aliasStrings) {
|
|
174081
|
+
out.push({ name: alias, value: defaultVal, shape: "const-literal", source: pos });
|
|
174082
|
+
}
|
|
174083
|
+
return true;
|
|
174084
|
+
});
|
|
174085
|
+
return out;
|
|
174086
|
+
}
|
|
174087
|
+
function extractSettingsFields(classNode, source, filePath, stringTable) {
|
|
174088
|
+
const body = classNode.childForFieldName("body");
|
|
174089
|
+
if (!body)
|
|
174090
|
+
return [];
|
|
174091
|
+
const scope = deriveSettingsScope(body, source, stringTable);
|
|
174092
|
+
if (scope === null)
|
|
174093
|
+
return [];
|
|
174094
|
+
const out = [];
|
|
174095
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
174096
|
+
const stmt = body.namedChild(i);
|
|
174097
|
+
if (stmt?.type !== "expression_statement")
|
|
174098
|
+
continue;
|
|
174099
|
+
const assign = stmt.namedChild(0);
|
|
174100
|
+
if (assign?.type !== "assignment")
|
|
174101
|
+
continue;
|
|
174102
|
+
if (!assign.childForFieldName("type"))
|
|
174103
|
+
continue;
|
|
174104
|
+
const left = assign.childForFieldName("left");
|
|
174105
|
+
if (left?.type !== "identifier")
|
|
174106
|
+
continue;
|
|
174107
|
+
const fieldName = source.slice(left.startIndex, left.endIndex);
|
|
174108
|
+
if (fieldName === "model_config")
|
|
174109
|
+
continue;
|
|
174110
|
+
const right = assign.childForFieldName("right");
|
|
174111
|
+
if (!right)
|
|
174112
|
+
continue;
|
|
174113
|
+
const value = fieldDefaultValue(right, source, stringTable);
|
|
174114
|
+
if (value === UNPARSEABLE2)
|
|
174115
|
+
continue;
|
|
174116
|
+
const name = `${scope}_${fieldName}`.toUpperCase();
|
|
173241
174117
|
out.push({
|
|
173242
|
-
name
|
|
174118
|
+
name,
|
|
173243
174119
|
value,
|
|
173244
|
-
shape: "
|
|
173245
|
-
source: { filePath, lineStart:
|
|
174120
|
+
shape: "settings-field",
|
|
174121
|
+
source: { filePath, lineStart: assign.startPosition.row + 1, lineEnd: assign.endPosition.row + 1 }
|
|
173246
174122
|
});
|
|
173247
|
-
|
|
173248
|
-
});
|
|
174123
|
+
}
|
|
173249
174124
|
return out;
|
|
173250
174125
|
}
|
|
173251
|
-
function
|
|
174126
|
+
function deriveSettingsScope(body, source, stringTable) {
|
|
174127
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
174128
|
+
const stmt = body.namedChild(i);
|
|
174129
|
+
if (stmt?.type !== "expression_statement")
|
|
174130
|
+
continue;
|
|
174131
|
+
const assign = stmt.namedChild(0);
|
|
174132
|
+
if (assign?.type !== "assignment")
|
|
174133
|
+
continue;
|
|
174134
|
+
const left = assign.childForFieldName("left");
|
|
174135
|
+
if (left?.type !== "identifier")
|
|
174136
|
+
continue;
|
|
174137
|
+
if (source.slice(left.startIndex, left.endIndex) !== "model_config")
|
|
174138
|
+
continue;
|
|
174139
|
+
const right = assign.childForFieldName("right");
|
|
174140
|
+
if (right?.type !== "call")
|
|
174141
|
+
continue;
|
|
174142
|
+
const args = right.childForFieldName("arguments");
|
|
174143
|
+
if (!args)
|
|
174144
|
+
continue;
|
|
174145
|
+
for (let j = 0; j < args.namedChildCount; j++) {
|
|
174146
|
+
const arg = args.namedChild(j);
|
|
174147
|
+
if (arg?.type !== "keyword_argument")
|
|
174148
|
+
continue;
|
|
174149
|
+
const kw = arg.childForFieldName("name");
|
|
174150
|
+
const val = arg.childForFieldName("value");
|
|
174151
|
+
if (kw && val && source.slice(kw.startIndex, kw.endIndex) === "env_prefix" && val.type === "string") {
|
|
174152
|
+
const prefix = stringValue(val, source, stringTable);
|
|
174153
|
+
if (prefix)
|
|
174154
|
+
return prefix.replace(/_+$/, "").toLowerCase();
|
|
174155
|
+
}
|
|
174156
|
+
}
|
|
174157
|
+
for (let j = 0; j < args.namedChildCount; j++) {
|
|
174158
|
+
const arg = args.namedChild(j);
|
|
174159
|
+
if (arg?.type !== "tuple")
|
|
174160
|
+
continue;
|
|
174161
|
+
const parts = [];
|
|
174162
|
+
for (let k = 0; k < arg.namedChildCount; k++) {
|
|
174163
|
+
const el = arg.namedChild(k);
|
|
174164
|
+
if (el?.type === "string") {
|
|
174165
|
+
const v = stringValue(el, source, stringTable);
|
|
174166
|
+
if (v)
|
|
174167
|
+
parts.push(v);
|
|
174168
|
+
}
|
|
174169
|
+
}
|
|
174170
|
+
if (parts.length > 0)
|
|
174171
|
+
return parts.join("_").toLowerCase();
|
|
174172
|
+
}
|
|
174173
|
+
}
|
|
174174
|
+
return null;
|
|
174175
|
+
}
|
|
174176
|
+
function fieldDefaultValue(right, source, stringTable) {
|
|
174177
|
+
const direct = parseLiteral(right, source, stringTable);
|
|
174178
|
+
if (direct !== UNPARSEABLE2)
|
|
174179
|
+
return direct;
|
|
174180
|
+
if (right.type !== "call")
|
|
174181
|
+
return UNPARSEABLE2;
|
|
174182
|
+
const fn = right.childForFieldName("function");
|
|
174183
|
+
if (!fn || !source.slice(fn.startIndex, fn.endIndex).endsWith("Field"))
|
|
174184
|
+
return UNPARSEABLE2;
|
|
174185
|
+
const args = right.childForFieldName("arguments");
|
|
174186
|
+
if (!args)
|
|
174187
|
+
return UNPARSEABLE2;
|
|
174188
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
174189
|
+
const arg = args.namedChild(i);
|
|
174190
|
+
if (arg?.type !== "keyword_argument")
|
|
174191
|
+
continue;
|
|
174192
|
+
const kw = arg.childForFieldName("name");
|
|
174193
|
+
const val = arg.childForFieldName("value");
|
|
174194
|
+
if (kw && val && source.slice(kw.startIndex, kw.endIndex) === "default") {
|
|
174195
|
+
return parseLiteral(val, source, stringTable);
|
|
174196
|
+
}
|
|
174197
|
+
}
|
|
174198
|
+
return UNPARSEABLE2;
|
|
174199
|
+
}
|
|
174200
|
+
function parseLiteral(node2, source, stringTable) {
|
|
173252
174201
|
switch (node2.type) {
|
|
173253
174202
|
case "string": {
|
|
173254
|
-
const v =
|
|
174203
|
+
const v = stringValue(node2, source, stringTable);
|
|
173255
174204
|
return v === null ? UNPARSEABLE2 : v;
|
|
173256
174205
|
}
|
|
173257
174206
|
case "integer":
|
|
@@ -173275,7 +174224,7 @@ function parseLiteral(node2, source) {
|
|
|
173275
174224
|
const c = node2.namedChild(i);
|
|
173276
174225
|
if (!c)
|
|
173277
174226
|
continue;
|
|
173278
|
-
const v = parseLiteral(c, source);
|
|
174227
|
+
const v = parseLiteral(c, source, stringTable);
|
|
173279
174228
|
if (v === UNPARSEABLE2)
|
|
173280
174229
|
return UNPARSEABLE2;
|
|
173281
174230
|
items.push(v);
|
|
@@ -173294,12 +174243,12 @@ function parseLiteral(node2, source) {
|
|
|
173294
174243
|
continue;
|
|
173295
174244
|
let key2 = null;
|
|
173296
174245
|
if (keyNode.type === "string")
|
|
173297
|
-
key2 =
|
|
174246
|
+
key2 = stringValue(keyNode, source, stringTable);
|
|
173298
174247
|
else if (keyNode.type === "identifier")
|
|
173299
174248
|
key2 = source.slice(keyNode.startIndex, keyNode.endIndex);
|
|
173300
174249
|
if (key2 === null)
|
|
173301
174250
|
return UNPARSEABLE2;
|
|
173302
|
-
const v = parseLiteral(valNode, source);
|
|
174251
|
+
const v = parseLiteral(valNode, source, stringTable);
|
|
173303
174252
|
if (v === UNPARSEABLE2)
|
|
173304
174253
|
return UNPARSEABLE2;
|
|
173305
174254
|
obj[key2] = v;
|
|
@@ -173310,23 +174259,28 @@ function parseLiteral(node2, source) {
|
|
|
173310
174259
|
return UNPARSEABLE2;
|
|
173311
174260
|
}
|
|
173312
174261
|
}
|
|
173313
|
-
function
|
|
173314
|
-
|
|
173315
|
-
|
|
173316
|
-
|
|
173317
|
-
|
|
173318
|
-
|
|
173319
|
-
|
|
173320
|
-
|
|
173321
|
-
|
|
173322
|
-
|
|
174262
|
+
function extractAliasChoiceStrings(node2, source, stringTable) {
|
|
174263
|
+
if (node2.type !== "call")
|
|
174264
|
+
return [];
|
|
174265
|
+
const fn = node2.childForFieldName("function");
|
|
174266
|
+
if (!fn)
|
|
174267
|
+
return [];
|
|
174268
|
+
const fnText = source.slice(fn.startIndex, fn.endIndex);
|
|
174269
|
+
if (!fnText.endsWith("AliasChoices"))
|
|
174270
|
+
return [];
|
|
174271
|
+
const args = node2.childForFieldName("arguments");
|
|
174272
|
+
if (!args)
|
|
174273
|
+
return [];
|
|
174274
|
+
const result = [];
|
|
174275
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
174276
|
+
const c = args.namedChild(i);
|
|
174277
|
+
if (c?.type === "string") {
|
|
174278
|
+
const v = stringValue(c, source, stringTable);
|
|
174279
|
+
if (v !== null)
|
|
174280
|
+
result.push(v);
|
|
173323
174281
|
}
|
|
173324
174282
|
}
|
|
173325
|
-
|
|
173326
|
-
return content;
|
|
173327
|
-
const raw = source.slice(node2.startIndex, node2.endIndex);
|
|
173328
|
-
const m = raw.match(/^[a-zA-Z]*('''|"""|'|")([\s\S]*)\1$/);
|
|
173329
|
-
return m ? m[2] : null;
|
|
174283
|
+
return result;
|
|
173330
174284
|
}
|
|
173331
174285
|
function walk10(node2, visit) {
|
|
173332
174286
|
const recurse = visit(node2);
|
|
@@ -173779,7 +174733,7 @@ function readTransitionMap(node2, s) {
|
|
|
173779
174733
|
for (const elem of v.namedChildren) {
|
|
173780
174734
|
if (elem.type !== "string")
|
|
173781
174735
|
return null;
|
|
173782
|
-
const text =
|
|
174736
|
+
const text = stringValue2(elem, s);
|
|
173783
174737
|
if (text === null)
|
|
173784
174738
|
return null;
|
|
173785
174739
|
tos.push(text);
|
|
@@ -173818,7 +174772,7 @@ function readFieldAssignment(node2, s) {
|
|
|
173818
174772
|
return null;
|
|
173819
174773
|
if (rhs.type !== "string")
|
|
173820
174774
|
return null;
|
|
173821
|
-
const value =
|
|
174775
|
+
const value = stringValue2(rhs, s);
|
|
173822
174776
|
if (value === null)
|
|
173823
174777
|
return null;
|
|
173824
174778
|
return {
|
|
@@ -173925,13 +174879,13 @@ function matchPair(member, literal, s) {
|
|
|
173925
174879
|
return [{
|
|
173926
174880
|
receiver: s.source.slice(obj.startIndex, obj.endIndex),
|
|
173927
174881
|
field: s.source.slice(prop.startIndex, prop.endIndex),
|
|
173928
|
-
value:
|
|
174882
|
+
value: stringValue2(literal, s) ?? ""
|
|
173929
174883
|
}];
|
|
173930
174884
|
}
|
|
173931
174885
|
function stripQuotes(str) {
|
|
173932
174886
|
return str.replace(/^['"]|['"]$/g, "");
|
|
173933
174887
|
}
|
|
173934
|
-
function
|
|
174888
|
+
function stringValue2(node2, s) {
|
|
173935
174889
|
if (node2.type !== "string")
|
|
173936
174890
|
return null;
|
|
173937
174891
|
const childType = s.lang === "python" ? "string_content" : "string_fragment";
|
|
@@ -174928,7 +175882,11 @@ async function extractOperationsFromDir(rootDir) {
|
|
|
174928
175882
|
await eachParsedSource(rootDir, (s) => {
|
|
174929
175883
|
if (s.lang !== "python")
|
|
174930
175884
|
return;
|
|
174931
|
-
|
|
175885
|
+
const pythonOps = [
|
|
175886
|
+
...extractFastApiOperationsFromFile(s.filePath, s.source, s.tree),
|
|
175887
|
+
...extractStarletteRoutesFromFile(s.filePath, s.source, s.tree)
|
|
175888
|
+
];
|
|
175889
|
+
for (const op of pythonOps) {
|
|
174932
175890
|
if (!seen.has(op.identity)) {
|
|
174933
175891
|
expressOps.push(op);
|
|
174934
175892
|
seen.add(op.identity);
|
|
@@ -176071,7 +177029,9 @@ import { randomUUID as randomUUID19 } from "node:crypto";
|
|
|
176071
177029
|
function compareEnum(input) {
|
|
176072
177030
|
const { ref, contract, codeEnums } = input;
|
|
176073
177031
|
const drifts = [];
|
|
176074
|
-
const
|
|
177032
|
+
const matched = matchByName(contract, codeEnums, ref.identity);
|
|
177033
|
+
const valueOnlyMatch = matched.byName.length === 0;
|
|
177034
|
+
const nameMatches = matched.byName.length > 0 ? matched.byName : bestValueMatch(contract, matched.byValue);
|
|
176075
177035
|
if (nameMatches.length === 0) {
|
|
176076
177036
|
drifts.push({
|
|
176077
177037
|
id: randomUUID19(),
|
|
@@ -176087,21 +177047,37 @@ function compareEnum(input) {
|
|
|
176087
177047
|
codeSide: "<no match>"
|
|
176088
177048
|
});
|
|
176089
177049
|
} else {
|
|
177050
|
+
const specNorm = new Map(contract.values.map((v) => [normalizeValue(v), v]));
|
|
177051
|
+
const cloudOnlyValues = new Set((contract.triggerSubsets ?? []).filter((s) => isEnvironmentGatedSubset(s.name)).flatMap((s) => s.values.map(normalizeValue)));
|
|
177052
|
+
const byName = /* @__PURE__ */ new Map();
|
|
176090
177053
|
for (const m of nameMatches) {
|
|
176091
|
-
const
|
|
176092
|
-
|
|
176093
|
-
|
|
176094
|
-
const
|
|
177054
|
+
const key2 = normalizeName(m.name);
|
|
177055
|
+
if (!byName.has(key2))
|
|
177056
|
+
byName.set(key2, { values: /* @__PURE__ */ new Set(), repr: m });
|
|
177057
|
+
const g = byName.get(key2);
|
|
177058
|
+
for (const v of m.values)
|
|
177059
|
+
g.values.add(normalizeValue(v));
|
|
177060
|
+
}
|
|
177061
|
+
const specNormSet = new Set(contract.values.map(normalizeValue));
|
|
177062
|
+
for (const g of byName.values()) {
|
|
177063
|
+
if (valueOnlyMatch && isStrictSubset(g.values, specNormSet))
|
|
177064
|
+
continue;
|
|
177065
|
+
const missing = contract.values.filter((v) => !g.values.has(normalizeValue(v)) && !cloudOnlyValues.has(normalizeValue(v)));
|
|
176095
177066
|
for (const v of missing) {
|
|
176096
|
-
drifts.push(mkValueDrift(ref, "missing-value", v,
|
|
177067
|
+
drifts.push(mkValueDrift(ref, "missing-value", v, g.repr, contract.values));
|
|
176097
177068
|
}
|
|
177069
|
+
}
|
|
177070
|
+
for (const m of nameMatches) {
|
|
177071
|
+
if (isSynthesizedEnumShape(m.shape))
|
|
177072
|
+
continue;
|
|
177073
|
+
const extra = m.values.filter((v) => !specNorm.has(normalizeValue(v)));
|
|
176098
177074
|
for (const v of extra) {
|
|
176099
177075
|
drifts.push(mkValueDrift(ref, "extra-value", v, m, contract.values));
|
|
176100
177076
|
}
|
|
176101
177077
|
}
|
|
176102
177078
|
}
|
|
176103
177079
|
for (const subset of contract.triggerSubsets ?? []) {
|
|
176104
|
-
const subsetMatches = matchSubsetByName(subset.name, codeEnums);
|
|
177080
|
+
const subsetMatches = matchSubsetByName(subset.name, subset.values, codeEnums);
|
|
176105
177081
|
if (subsetMatches.length === 0) {
|
|
176106
177082
|
drifts.push({
|
|
176107
177083
|
id: randomUUID19(),
|
|
@@ -176142,13 +177118,17 @@ function normalizeName(s) {
|
|
|
176142
177118
|
}
|
|
176143
177119
|
return n;
|
|
176144
177120
|
}
|
|
177121
|
+
function isEnvironmentGatedSubset(name) {
|
|
177122
|
+
return normalizeName(name) === "cloudonly";
|
|
177123
|
+
}
|
|
176145
177124
|
function matchByName(contract, codeEnums, specName) {
|
|
176146
177125
|
const target = normalizeName(specName);
|
|
176147
|
-
const
|
|
177126
|
+
const byName = [];
|
|
177127
|
+
const byValue = [];
|
|
176148
177128
|
for (const e of codeEnums) {
|
|
176149
177129
|
const codeName = normalizeName(e.name);
|
|
176150
177130
|
if (codeName === target) {
|
|
176151
|
-
|
|
177131
|
+
byName.push(e);
|
|
176152
177132
|
continue;
|
|
176153
177133
|
}
|
|
176154
177134
|
if (codeName.includes(target) || target.includes(codeName)) {
|
|
@@ -176159,7 +177139,7 @@ function matchByName(contract, codeEnums, specName) {
|
|
|
176159
177139
|
}
|
|
176160
177140
|
}
|
|
176161
177141
|
if (valueSetOverlap(contract.values, e.values) >= 0.5) {
|
|
176162
|
-
|
|
177142
|
+
byName.push(e);
|
|
176163
177143
|
continue;
|
|
176164
177144
|
}
|
|
176165
177145
|
}
|
|
@@ -176168,21 +177148,40 @@ function matchByName(contract, codeEnums, specName) {
|
|
|
176168
177148
|
const overlap = valueSetOverlap(contract.values, e.values);
|
|
176169
177149
|
const sizeDiff = Math.abs(contract.values.length - e.values.length);
|
|
176170
177150
|
if (overlap >= 0.6 && sizeDiff <= 2) {
|
|
176171
|
-
|
|
177151
|
+
byValue.push(e);
|
|
176172
177152
|
}
|
|
176173
177153
|
} else if (minLen >= 2) {
|
|
176174
177154
|
const overlap = valueSetOverlap(contract.values, e.values);
|
|
176175
177155
|
const sizeDiff = Math.abs(contract.values.length - e.values.length);
|
|
176176
177156
|
if (overlap === 1 && sizeDiff === 0) {
|
|
176177
|
-
|
|
177157
|
+
byValue.push(e);
|
|
176178
177158
|
}
|
|
176179
177159
|
}
|
|
176180
177160
|
}
|
|
176181
|
-
return
|
|
177161
|
+
return { byName, byValue };
|
|
177162
|
+
}
|
|
177163
|
+
function bestValueMatch(contract, byValue) {
|
|
177164
|
+
if (byValue.length <= 1)
|
|
177165
|
+
return byValue;
|
|
177166
|
+
let best = -1;
|
|
177167
|
+
for (const e of byValue)
|
|
177168
|
+
best = Math.max(best, valueSetOverlap(contract.values, e.values));
|
|
177169
|
+
return byValue.filter((e) => valueSetOverlap(contract.values, e.values) === best);
|
|
177170
|
+
}
|
|
177171
|
+
function isSynthesizedEnumShape(shape) {
|
|
177172
|
+
return shape === "sibling-id-literal" || shape === "py-instance-registry" || shape === "py-discriminated-union" || shape === "py-constant-cluster";
|
|
176182
177173
|
}
|
|
176183
177174
|
function normalizeValue(v) {
|
|
176184
177175
|
return v.replace(/[^A-Za-z0-9]/g, "").toLowerCase();
|
|
176185
177176
|
}
|
|
177177
|
+
function isStrictSubset(codeValues, specNorm) {
|
|
177178
|
+
if (codeValues.size === 0 || codeValues.size >= specNorm.size)
|
|
177179
|
+
return false;
|
|
177180
|
+
for (const v of codeValues)
|
|
177181
|
+
if (!specNorm.has(v))
|
|
177182
|
+
return false;
|
|
177183
|
+
return true;
|
|
177184
|
+
}
|
|
176186
177185
|
function valueSetOverlap(a, b) {
|
|
176187
177186
|
const aSet = new Set(a.map(normalizeValue));
|
|
176188
177187
|
const bSet = new Set(b.map(normalizeValue));
|
|
@@ -176190,9 +177189,21 @@ function valueSetOverlap(a, b) {
|
|
|
176190
177189
|
const union = (/* @__PURE__ */ new Set([...aSet, ...bSet])).size;
|
|
176191
177190
|
return union === 0 ? 0 : intersection / union;
|
|
176192
177191
|
}
|
|
176193
|
-
function matchSubsetByName(subsetName, codeEnums) {
|
|
177192
|
+
function matchSubsetByName(subsetName, subsetValues, codeEnums) {
|
|
176194
177193
|
const target = normalizeName(subsetName);
|
|
176195
|
-
|
|
177194
|
+
const out = [];
|
|
177195
|
+
for (const e of codeEnums) {
|
|
177196
|
+
const codeName = normalizeName(e.name);
|
|
177197
|
+
if (codeName === target) {
|
|
177198
|
+
out.push(e);
|
|
177199
|
+
continue;
|
|
177200
|
+
}
|
|
177201
|
+
if (codeName.includes(target) || target.includes(codeName)) {
|
|
177202
|
+
if (valueSetOverlap(subsetValues, e.values) >= 0.5)
|
|
177203
|
+
out.push(e);
|
|
177204
|
+
}
|
|
177205
|
+
}
|
|
177206
|
+
return out;
|
|
176196
177207
|
}
|
|
176197
177208
|
function mkValueDrift(ref, kind, value, codeEnum, specValues) {
|
|
176198
177209
|
const severity = kind === "missing-value" ? "high" : "medium";
|
|
@@ -176306,6 +177317,21 @@ function compareNamedConstant(input) {
|
|
|
176306
177317
|
return false;
|
|
176307
177318
|
});
|
|
176308
177319
|
}
|
|
177320
|
+
if (matches.length === 0) {
|
|
177321
|
+
matches = codeConstants.filter((c) => {
|
|
177322
|
+
if (c.shape !== "settings-field")
|
|
177323
|
+
return false;
|
|
177324
|
+
const codeName = normalizeName2(c.name);
|
|
177325
|
+
if (codeName.length < 8 || !target.endsWith(codeName))
|
|
177326
|
+
return false;
|
|
177327
|
+
return contract.expectedValue === void 0 || deepEqual(
|
|
177328
|
+
contract.expectedValue,
|
|
177329
|
+
c.value,
|
|
177330
|
+
/*allowExtraCodeKeys*/
|
|
177331
|
+
true
|
|
177332
|
+
);
|
|
177333
|
+
});
|
|
177334
|
+
}
|
|
176309
177335
|
if (matches.length === 0) {
|
|
176310
177336
|
return [{
|
|
176311
177337
|
id: randomUUID21(),
|
|
@@ -176491,6 +177517,8 @@ async function verify(opts) {
|
|
|
176491
177517
|
if (!code2) {
|
|
176492
177518
|
if (st === "planned" || st === "deferred" || st === "out-of-scope")
|
|
176493
177519
|
continue;
|
|
177520
|
+
if (/^[A-Z]+ https?:\/\//.test(artifact.ref.identity))
|
|
177521
|
+
continue;
|
|
176494
177522
|
drifts.push({
|
|
176495
177523
|
id: cryptoRandomId(),
|
|
176496
177524
|
type: "contract-drift",
|
|
@@ -178887,7 +179915,7 @@ async function main() {
|
|
|
178887
179915
|
const app = createApp();
|
|
178888
179916
|
const httpServer = createServer(app);
|
|
178889
179917
|
setupSocket(httpServer);
|
|
178890
|
-
await new Promise((
|
|
179918
|
+
await new Promise((resolve9, reject) => {
|
|
178891
179919
|
httpServer.on("error", (err) => {
|
|
178892
179920
|
if (err.code === "EADDRINUSE") {
|
|
178893
179921
|
reject(new Error(
|
|
@@ -178918,7 +179946,7 @@ Stop it first, or set PORT to use a different port.`
|
|
|
178918
179946
|
""
|
|
178919
179947
|
]);
|
|
178920
179948
|
log.info(`[Server] Listening on port ${port}`);
|
|
178921
|
-
|
|
179949
|
+
resolve9();
|
|
178922
179950
|
});
|
|
178923
179951
|
});
|
|
178924
179952
|
async function shutdown() {
|