deslop-js 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entries-worker.mjs +12 -3
- package/dist/index.cjs +249 -17
- package/dist/index.mjs +249 -17
- package/dist/{parse-xkrZfjHl.mjs → parse-CDdo_Ppt.mjs} +151 -1
- package/dist/parse-worker.mjs +2 -1
- package/package.json +1 -1
package/dist/entries-worker.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as OUTPUT_DIRECTORIES, c as SCRIPT_ENTRY_PATTERNS, d as SOURCE_EXTENSIONS$3, f as STANDALONE_PROJECT_LOCKFILES, i as MONOREPO_ROOT_MARKERS, l as SCRIPT_EXTENSIONLESS_FILE_PATTERN, o as RESOLVER_EXTENSIONS, r as LOCKFILE_MARKERS, s as SCRIPT_CONFIG_FILE_PATTERN, t as extractReactRouterRouteModuleEntries, u as SCRIPT_FILE_PATTERN } from "./parse-
|
|
1
|
+
import { a as OUTPUT_DIRECTORIES, c as SCRIPT_ENTRY_PATTERNS, d as SOURCE_EXTENSIONS$3, f as STANDALONE_PROJECT_LOCKFILES, i as MONOREPO_ROOT_MARKERS, l as SCRIPT_EXTENSIONLESS_FILE_PATTERN, o as RESOLVER_EXTENSIONS, r as LOCKFILE_MARKERS, s as SCRIPT_CONFIG_FILE_PATTERN, t as extractReactRouterRouteModuleEntries, u as SCRIPT_FILE_PATTERN } from "./parse-CDdo_Ppt.mjs";
|
|
2
2
|
import { parentPort } from "node:worker_threads";
|
|
3
3
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
4
4
|
import fg from "fast-glob";
|
|
@@ -1916,6 +1916,13 @@ const extractCiWorkflowEntries = (rootDir) => {
|
|
|
1916
1916
|
const entries = [];
|
|
1917
1917
|
const workflowsDir = join(rootDir, ".github", "workflows");
|
|
1918
1918
|
if (!existsSync(workflowsDir)) return entries;
|
|
1919
|
+
const nestedToolPackageJsonPaths = fg.sync("**/package.json", {
|
|
1920
|
+
cwd: join(rootDir, ".github"),
|
|
1921
|
+
absolute: true,
|
|
1922
|
+
onlyFiles: true,
|
|
1923
|
+
ignore: ["**/node_modules/**"]
|
|
1924
|
+
});
|
|
1925
|
+
for (const nestedPackageJsonPath of nestedToolPackageJsonPaths) entries.push(...extractScriptEntries(dirname(nestedPackageJsonPath)));
|
|
1919
1926
|
const workflowFiles = fg.sync("*.{yml,yaml}", {
|
|
1920
1927
|
cwd: workflowsDir,
|
|
1921
1928
|
absolute: true,
|
|
@@ -3518,8 +3525,10 @@ const discoverTestRunnerEntryPoints = (rootDir, workspacePackages) => {
|
|
|
3518
3525
|
customPatterns = extractJestTestMatchPatterns(directory);
|
|
3519
3526
|
if (customPatterns.length === 0 && monorepoRoot) customPatterns = extractJestTestMatchPatterns(monorepoRoot);
|
|
3520
3527
|
}
|
|
3521
|
-
if (customPatterns.length > 0)
|
|
3522
|
-
|
|
3528
|
+
if (customPatterns.length > 0) {
|
|
3529
|
+
activatedPatterns.push(...customPatterns);
|
|
3530
|
+
if (isJestRunner) activatedPatterns.push("**/__mocks__/**/*.{ts,tsx,js,jsx,mjs,cjs}");
|
|
3531
|
+
} else activatedPatterns.push(...runner.entryPatterns);
|
|
3523
3532
|
activatedFixturePatterns.push(...runner.fixturePatterns);
|
|
3524
3533
|
activatedAlwaysUsed.push(...runner.alwaysUsed);
|
|
3525
3534
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1355,6 +1355,7 @@ const parseCssImports = (filePath) => {
|
|
|
1355
1355
|
memberAccesses: [],
|
|
1356
1356
|
wholeObjectUses: [],
|
|
1357
1357
|
localIdentifierReferences: [],
|
|
1358
|
+
topLevelImportReferences: [],
|
|
1358
1359
|
referencedFilenames: [],
|
|
1359
1360
|
redundantTypePatterns: [],
|
|
1360
1361
|
identityWrappers: [],
|
|
@@ -1383,18 +1384,142 @@ const collectLocalIdentifierReferences = (statements) => {
|
|
|
1383
1384
|
for (const value of Object.values(record)) if (Array.isArray(value)) for (const innerValue of value) visitNode(innerValue);
|
|
1384
1385
|
else if (value && typeof value === "object") visitNode(value);
|
|
1385
1386
|
};
|
|
1387
|
+
const visitExportedDeclarationValues = (declaration) => {
|
|
1388
|
+
if (!declaration || typeof declaration !== "object") return;
|
|
1389
|
+
const record = declaration;
|
|
1390
|
+
if (record.type === "VariableDeclaration" && Array.isArray(record.declarations)) {
|
|
1391
|
+
for (const declarator of record.declarations) if (declarator && typeof declarator === "object") visitNode(declarator.init);
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
if (record.type === "FunctionDeclaration" || record.type === "ClassDeclaration") {
|
|
1395
|
+
visitNode(record.params);
|
|
1396
|
+
visitNode(record.superClass);
|
|
1397
|
+
visitNode(record.body);
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
if (typeof record.type === "string" && !record.type.startsWith("TS")) visitNode(declaration);
|
|
1401
|
+
};
|
|
1386
1402
|
for (const statement of statements) {
|
|
1387
|
-
if (statement.type === "ImportDeclaration" || statement.type === "
|
|
1403
|
+
if (statement.type === "ImportDeclaration" || statement.type === "ExportAllDeclaration") continue;
|
|
1404
|
+
if (statement.type === "ExportNamedDeclaration") {
|
|
1405
|
+
visitExportedDeclarationValues(statement.declaration);
|
|
1406
|
+
continue;
|
|
1407
|
+
}
|
|
1408
|
+
if (statement.type === "ExportDefaultDeclaration") {
|
|
1409
|
+
visitExportedDeclarationValues(statement.declaration);
|
|
1410
|
+
continue;
|
|
1411
|
+
}
|
|
1388
1412
|
visitNode(statement);
|
|
1389
1413
|
}
|
|
1390
1414
|
return references;
|
|
1391
1415
|
};
|
|
1416
|
+
const TS_VALUE_WRAPPER_NODE_TYPES = new Set([
|
|
1417
|
+
"TSAsExpression",
|
|
1418
|
+
"TSSatisfiesExpression",
|
|
1419
|
+
"TSNonNullExpression",
|
|
1420
|
+
"TSInstantiationExpression",
|
|
1421
|
+
"TSTypeAssertion"
|
|
1422
|
+
]);
|
|
1423
|
+
const TS_RUNTIME_DECLARATION_NODE_TYPES = new Set([
|
|
1424
|
+
"TSEnumDeclaration",
|
|
1425
|
+
"TSModuleDeclaration",
|
|
1426
|
+
"TSExportAssignment"
|
|
1427
|
+
]);
|
|
1428
|
+
const FUNCTION_NODE_TYPES = new Set([
|
|
1429
|
+
"FunctionDeclaration",
|
|
1430
|
+
"FunctionExpression",
|
|
1431
|
+
"ArrowFunctionExpression"
|
|
1432
|
+
]);
|
|
1433
|
+
const collectStaticImportLocalNames = (imports) => {
|
|
1434
|
+
const localNames = /* @__PURE__ */ new Set();
|
|
1435
|
+
for (const importInfo of imports) {
|
|
1436
|
+
if (importInfo.isDynamic || importInfo.isTypeOnly) continue;
|
|
1437
|
+
for (const binding of importInfo.importedNames) {
|
|
1438
|
+
if (binding.isTypeOnly) continue;
|
|
1439
|
+
const localName = binding.alias ?? binding.name;
|
|
1440
|
+
if (localName && localName !== "*") localNames.add(localName);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
return localNames;
|
|
1444
|
+
};
|
|
1445
|
+
const collectTopLevelImportReferences = (bodyNodes, importLocalNames) => {
|
|
1446
|
+
const referencedNames = /* @__PURE__ */ new Set();
|
|
1447
|
+
if (importLocalNames.size === 0) return [];
|
|
1448
|
+
const visitClassBody = (classBody) => {
|
|
1449
|
+
const bodyElements = classBody.body ?? [];
|
|
1450
|
+
for (const element of bodyElements) {
|
|
1451
|
+
if (element.type === "StaticBlock") {
|
|
1452
|
+
visitValueNode(element.body);
|
|
1453
|
+
continue;
|
|
1454
|
+
}
|
|
1455
|
+
if (Boolean(element.computed)) visitValueNode(element.key);
|
|
1456
|
+
const isStatic = Boolean(element.static);
|
|
1457
|
+
if (element.type === "PropertyDefinition" && isStatic) visitValueNode(element.value);
|
|
1458
|
+
visitValueNode(element.decorators);
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
const visitValueNode = (node) => {
|
|
1462
|
+
if (Array.isArray(node)) {
|
|
1463
|
+
for (const element of node) visitValueNode(element);
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
if (!isWalkableNode(node)) return;
|
|
1467
|
+
if (node.type === "Identifier" || node.type === "JSXIdentifier") {
|
|
1468
|
+
const identifierName = node.name;
|
|
1469
|
+
if (identifierName && importLocalNames.has(identifierName)) referencedNames.add(identifierName);
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
if (node.type.startsWith("TS")) {
|
|
1473
|
+
if (TS_VALUE_WRAPPER_NODE_TYPES.has(node.type)) {
|
|
1474
|
+
visitValueNode(node.expression);
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
if (!TS_RUNTIME_DECLARATION_NODE_TYPES.has(node.type)) return;
|
|
1478
|
+
}
|
|
1479
|
+
if (FUNCTION_NODE_TYPES.has(node.type)) return;
|
|
1480
|
+
if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
|
|
1481
|
+
visitValueNode(node.superClass);
|
|
1482
|
+
visitValueNode(node.decorators);
|
|
1483
|
+
const classBody = node.body;
|
|
1484
|
+
if (classBody) visitClassBody(classBody);
|
|
1485
|
+
return;
|
|
1486
|
+
}
|
|
1487
|
+
if (node.type === "CallExpression" || node.type === "NewExpression") {
|
|
1488
|
+
const callee = node.callee;
|
|
1489
|
+
if (callee && FUNCTION_NODE_TYPES.has(callee.type)) visitValueNode(callee.body);
|
|
1490
|
+
}
|
|
1491
|
+
if (node.type === "MemberExpression" || node.type === "JSXMemberExpression") {
|
|
1492
|
+
const memberNode = node;
|
|
1493
|
+
visitValueNode(memberNode.object);
|
|
1494
|
+
if (node.computed) visitValueNode(memberNode.property);
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
if (node.type === "Property") {
|
|
1498
|
+
const propertyNode = node;
|
|
1499
|
+
if (node.computed) visitValueNode(propertyNode.key);
|
|
1500
|
+
visitValueNode(propertyNode.value);
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1503
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) for (const element of value) visitValueNode(element);
|
|
1504
|
+
else if (value && typeof value === "object") visitValueNode(value);
|
|
1505
|
+
};
|
|
1506
|
+
for (const statement of bodyNodes) {
|
|
1507
|
+
if (statement.type === "ImportDeclaration" || statement.type === "ExportAllDeclaration") continue;
|
|
1508
|
+
if (statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration") {
|
|
1509
|
+
visitValueNode(statement.declaration);
|
|
1510
|
+
continue;
|
|
1511
|
+
}
|
|
1512
|
+
visitValueNode(statement);
|
|
1513
|
+
}
|
|
1514
|
+
return [...referencedNames];
|
|
1515
|
+
};
|
|
1392
1516
|
const createEmptyParsedSource = () => ({
|
|
1393
1517
|
imports: [],
|
|
1394
1518
|
exports: [],
|
|
1395
1519
|
memberAccesses: [],
|
|
1396
1520
|
wholeObjectUses: [],
|
|
1397
1521
|
localIdentifierReferences: [],
|
|
1522
|
+
topLevelImportReferences: [],
|
|
1398
1523
|
referencedFilenames: [],
|
|
1399
1524
|
redundantTypePatterns: [],
|
|
1400
1525
|
identityWrappers: [],
|
|
@@ -1606,6 +1731,7 @@ const parseSourceFile = (filePath) => {
|
|
|
1606
1731
|
collectMemberAccesses(program.body, namespaceLocalNames, memberAccesses, wholeObjectUses);
|
|
1607
1732
|
}, void 0);
|
|
1608
1733
|
const localIdentifierReferences = safeWalk("collectLocalIdentifierReferences", () => collectLocalIdentifierReferences(program.body), []);
|
|
1734
|
+
const topLevelImportReferences = safeWalk("collectTopLevelImportReferences", () => collectTopLevelImportReferences(program.body, collectStaticImportLocalNames(imports)), []);
|
|
1609
1735
|
const redundantTypePatterns = [];
|
|
1610
1736
|
const identityWrappers = [];
|
|
1611
1737
|
const typeDefinitionHashes = [];
|
|
@@ -1650,6 +1776,7 @@ const parseSourceFile = (filePath) => {
|
|
|
1650
1776
|
memberAccesses,
|
|
1651
1777
|
wholeObjectUses,
|
|
1652
1778
|
localIdentifierReferences,
|
|
1779
|
+
topLevelImportReferences,
|
|
1653
1780
|
referencedFilenames: extractReferencedFilenames(sourceText),
|
|
1654
1781
|
redundantTypePatterns,
|
|
1655
1782
|
identityWrappers,
|
|
@@ -1790,6 +1917,29 @@ const collectMemberAccesses = (bodyNodes, namespaceLocalNames, memberAccesses, w
|
|
|
1790
1917
|
const spreadArgument = node.argument;
|
|
1791
1918
|
if (spreadArgument?.type === "Identifier" && namespaceLocalNames.has(spreadArgument.name)) wholeObjectUses.push(spreadArgument.name);
|
|
1792
1919
|
}
|
|
1920
|
+
if (node.type === "VariableDeclarator") {
|
|
1921
|
+
const declarator = node;
|
|
1922
|
+
if (declarator.init?.type === "Identifier" && namespaceLocalNames.has(declarator.init.name) && declarator.id?.type === "ObjectPattern") {
|
|
1923
|
+
const namespaceName = declarator.init.name;
|
|
1924
|
+
const patternProperties = declarator.id.properties;
|
|
1925
|
+
for (const property of patternProperties) {
|
|
1926
|
+
if (property.type === "RestElement") {
|
|
1927
|
+
wholeObjectUses.push(namespaceName);
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
const propertyKey = property.key;
|
|
1931
|
+
if (Boolean(property.computed)) wholeObjectUses.push(namespaceName);
|
|
1932
|
+
else if (propertyKey?.type === "Identifier" && propertyKey.name) memberAccesses.push({
|
|
1933
|
+
objectName: namespaceName,
|
|
1934
|
+
memberName: propertyKey.name
|
|
1935
|
+
});
|
|
1936
|
+
else if (propertyKey?.type === "Literal" && typeof propertyKey.value === "string") memberAccesses.push({
|
|
1937
|
+
objectName: namespaceName,
|
|
1938
|
+
memberName: propertyKey.value
|
|
1939
|
+
});
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1793
1943
|
if (node.type === "ForInStatement") {
|
|
1794
1944
|
const forInRight = node.right;
|
|
1795
1945
|
if (forInRight?.type === "Identifier" && namespaceLocalNames.has(forInRight.name)) wholeObjectUses.push(forInRight.name);
|
|
@@ -5123,6 +5273,13 @@ const extractCiWorkflowEntries = (rootDir) => {
|
|
|
5123
5273
|
const entries = [];
|
|
5124
5274
|
const workflowsDir = (0, node_path.join)(rootDir, ".github", "workflows");
|
|
5125
5275
|
if (!(0, node_fs.existsSync)(workflowsDir)) return entries;
|
|
5276
|
+
const nestedToolPackageJsonPaths = fast_glob.default.sync("**/package.json", {
|
|
5277
|
+
cwd: (0, node_path.join)(rootDir, ".github"),
|
|
5278
|
+
absolute: true,
|
|
5279
|
+
onlyFiles: true,
|
|
5280
|
+
ignore: ["**/node_modules/**"]
|
|
5281
|
+
});
|
|
5282
|
+
for (const nestedPackageJsonPath of nestedToolPackageJsonPaths) entries.push(...extractScriptEntries((0, node_path.dirname)(nestedPackageJsonPath)));
|
|
5126
5283
|
const workflowFiles = fast_glob.default.sync("*.{yml,yaml}", {
|
|
5127
5284
|
cwd: workflowsDir,
|
|
5128
5285
|
absolute: true,
|
|
@@ -6725,8 +6882,10 @@ const discoverTestRunnerEntryPoints = (rootDir, workspacePackages) => {
|
|
|
6725
6882
|
customPatterns = extractJestTestMatchPatterns(directory);
|
|
6726
6883
|
if (customPatterns.length === 0 && monorepoRoot) customPatterns = extractJestTestMatchPatterns(monorepoRoot);
|
|
6727
6884
|
}
|
|
6728
|
-
if (customPatterns.length > 0)
|
|
6729
|
-
|
|
6885
|
+
if (customPatterns.length > 0) {
|
|
6886
|
+
activatedPatterns.push(...customPatterns);
|
|
6887
|
+
if (isJestRunner) activatedPatterns.push("**/__mocks__/**/*.{ts,tsx,js,jsx,mjs,cjs}");
|
|
6888
|
+
} else activatedPatterns.push(...runner.entryPatterns);
|
|
6730
6889
|
activatedFixturePatterns.push(...runner.fixturePatterns);
|
|
6731
6890
|
activatedAlwaysUsed.push(...runner.alwaysUsed);
|
|
6732
6891
|
}
|
|
@@ -6957,6 +7116,7 @@ const deserializeParsedSource = (serialized) => ({
|
|
|
6957
7116
|
memberAccesses: serialized.memberAccesses,
|
|
6958
7117
|
wholeObjectUses: serialized.wholeObjectUses,
|
|
6959
7118
|
localIdentifierReferences: serialized.localIdentifierReferences,
|
|
7119
|
+
topLevelImportReferences: serialized.topLevelImportReferences,
|
|
6960
7120
|
referencedFilenames: serialized.referencedFilenames,
|
|
6961
7121
|
redundantTypePatterns: serialized.redundantTypePatterns,
|
|
6962
7122
|
identityWrappers: serialized.identityWrappers,
|
|
@@ -7021,6 +7181,7 @@ const parseFilesWithWorkerPool = async (files, workerCount) => {
|
|
|
7021
7181
|
memberAccesses: [],
|
|
7022
7182
|
wholeObjectUses: [],
|
|
7023
7183
|
localIdentifierReferences: [],
|
|
7184
|
+
topLevelImportReferences: [],
|
|
7024
7185
|
referencedFilenames: [],
|
|
7025
7186
|
redundantTypePatterns: [],
|
|
7026
7187
|
identityWrappers: [],
|
|
@@ -7095,6 +7256,7 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7095
7256
|
memberAccesses: input.parsed.memberAccesses,
|
|
7096
7257
|
wholeObjectUses: input.parsed.wholeObjectUses,
|
|
7097
7258
|
localIdentifierReferences: input.parsed.localIdentifierReferences,
|
|
7259
|
+
topLevelImportReferences: input.parsed.topLevelImportReferences,
|
|
7098
7260
|
referencedFilenames: input.parsed.referencedFilenames,
|
|
7099
7261
|
redundantTypePatterns: input.parsed.redundantTypePatterns,
|
|
7100
7262
|
identityWrappers: input.parsed.identityWrappers,
|
|
@@ -7113,12 +7275,13 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7113
7275
|
}));
|
|
7114
7276
|
const edges = [];
|
|
7115
7277
|
const reverseEdges = /* @__PURE__ */ new Map();
|
|
7116
|
-
const addEdge = (sourceIndex, targetIndex, symbols, isReExportEdge = false, reExportedNames = [], reExportMappings = []) => {
|
|
7278
|
+
const addEdge = (sourceIndex, targetIndex, symbols, isReExportEdge = false, reExportedNames = [], reExportMappings = [], isDynamic = false) => {
|
|
7117
7279
|
edges.push({
|
|
7118
7280
|
source: sourceIndex,
|
|
7119
7281
|
target: targetIndex,
|
|
7120
7282
|
importedSymbols: symbols,
|
|
7121
7283
|
isReExportEdge,
|
|
7284
|
+
isDynamic,
|
|
7122
7285
|
reExportedNames,
|
|
7123
7286
|
reExportMappings
|
|
7124
7287
|
});
|
|
@@ -7137,7 +7300,7 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7137
7300
|
const relativePath = toPosixPath(node_path.default.relative(sourceDir, filePath));
|
|
7138
7301
|
if ((0, minimatch.minimatch)(relativePath.startsWith(".") ? relativePath : `./${relativePath}`, globPattern)) {
|
|
7139
7302
|
const targetIndex = fileIdMap.get(filePath);
|
|
7140
|
-
if (targetIndex !== void 0) addEdge(sourceIndex, targetIndex, []);
|
|
7303
|
+
if (targetIndex !== void 0) addEdge(sourceIndex, targetIndex, [], false, [], [], true);
|
|
7141
7304
|
}
|
|
7142
7305
|
}
|
|
7143
7306
|
continue;
|
|
@@ -7152,7 +7315,7 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7152
7315
|
isTypeOnly: importedName.isTypeOnly,
|
|
7153
7316
|
isNamespace: importedName.isNamespace,
|
|
7154
7317
|
isDefault: importedName.isDefault
|
|
7155
|
-
})));
|
|
7318
|
+
})), false, [], [], importInfo.isDynamic);
|
|
7156
7319
|
}
|
|
7157
7320
|
const reExportsByTarget = /* @__PURE__ */ new Map();
|
|
7158
7321
|
for (const exportInfo of input.parsed.exports) {
|
|
@@ -7415,9 +7578,9 @@ const EXCLUDED_EXTENSIONS = new Set([
|
|
|
7415
7578
|
".graphql",
|
|
7416
7579
|
".gql"
|
|
7417
7580
|
]);
|
|
7418
|
-
const TEST_FILE_PATTERN = /(?:\.(?:test|spec|stories|story|cy)\.|(?:^|\/)__tests__\/)/;
|
|
7419
|
-
const EXCLUDED_DIRECTORY_PATTERN = /(?:^|\/)(?:e2e|cypress|playwright|__fixtures__|__snapshots__|scripts)\/(?!.*node_modules)/;
|
|
7420
|
-
const CONFIG_FILE_PATTERN = /(?:^|\/)(?:[^/]+\.config\.[tj]sx?$|[^/]+\.setup\.[tj]sx?$|setupTests\.[tj]sx?$|jest\.setup\.[tj]sx?$|vitest\.setup\.[tj]sx?$)/;
|
|
7581
|
+
const TEST_FILE_PATTERN = /(?:\.(?:test|spec|stories|story|cy|test-d)\.|(?:^|\/)__tests__\/)/;
|
|
7582
|
+
const EXCLUDED_DIRECTORY_PATTERN = /(?:^|\/)(?:e2e|cypress|playwright|__fixtures__|__snapshots__|public|scripts)\/(?!.*node_modules)/;
|
|
7583
|
+
const CONFIG_FILE_PATTERN = /(?:^|\/)(?:[^/]+\.config\.[tj]sx?$|[^/]+\.config\.[^/]+\.[tj]sx?$|[^/]+\.setup\.[tj]sx?$|setupTests\.[tj]sx?$|jest\.setup\.[tj]sx?$|vitest\.setup\.[tj]sx?$)/;
|
|
7421
7584
|
const hasExcludedExtension = (filePath) => {
|
|
7422
7585
|
const lastDot = filePath.lastIndexOf(".");
|
|
7423
7586
|
if (lastDot === -1) return false;
|
|
@@ -7493,6 +7656,7 @@ const detectDeadExports = (graph, config) => {
|
|
|
7493
7656
|
if (usageMap.has(usageKey)) continue;
|
|
7494
7657
|
if (module.localIdentifierReferences.includes(exportInfo.name)) continue;
|
|
7495
7658
|
if (!exportInfo.isDefault && defaultExportLinkedNames.has(exportInfo.name)) continue;
|
|
7659
|
+
if (exportInfo.isDefault && exportInfo.defaultExportLocalName && usageMap.has(`${module.fileId.path}::${exportInfo.defaultExportLocalName}`)) continue;
|
|
7496
7660
|
unusedExports.push({
|
|
7497
7661
|
path: module.fileId.path,
|
|
7498
7662
|
name: exportInfo.name,
|
|
@@ -7527,6 +7691,10 @@ const buildUsageMap = (graph) => {
|
|
|
7527
7691
|
const targetModule = graph.modules[edge.target];
|
|
7528
7692
|
if (!targetModule) continue;
|
|
7529
7693
|
const sourceModule = graph.modules[edge.source];
|
|
7694
|
+
if (edge.isDynamic && edge.importedSymbols.length === 0) {
|
|
7695
|
+
markAllExportsUsedRecursive(targetModule, graph, sourceToTargetMap, usedExportKeys, /* @__PURE__ */ new Set());
|
|
7696
|
+
continue;
|
|
7697
|
+
}
|
|
7530
7698
|
for (const symbol of edge.importedSymbols) if (symbol.isNamespace) handleNamespaceImport(sourceModule, targetModule, symbol.localName, graph, sourceToTargetMap, usedExportKeys);
|
|
7531
7699
|
else {
|
|
7532
7700
|
const importName = symbol.isDefault ? "default" : symbol.importedName;
|
|
@@ -7916,10 +8084,12 @@ const hasJsxFiles = (graph) => graph.modules.some((module) => {
|
|
|
7916
8084
|
const filePath = module.fileId.path;
|
|
7917
8085
|
return filePath.endsWith(".tsx") || filePath.endsWith(".jsx");
|
|
7918
8086
|
});
|
|
8087
|
+
const KNOWN_PEER_DEPENDENCY_NAMES = new Map([["vitest-axe", ["axe-core"]], ["jest-axe", ["axe-core"]]]);
|
|
7919
8088
|
const collectPeerSatisfiedPackages = (nodeModulesSearchRoots, declaredNames, confirmedUsedNames) => {
|
|
7920
8089
|
const peerSatisfied = /* @__PURE__ */ new Set();
|
|
7921
8090
|
for (const installedName of declaredNames) {
|
|
7922
8091
|
if (!confirmedUsedNames.has(installedName)) continue;
|
|
8092
|
+
for (const knownPeerName of KNOWN_PEER_DEPENDENCY_NAMES.get(installedName) ?? []) if (declaredNames.has(knownPeerName)) peerSatisfied.add(knownPeerName);
|
|
7923
8093
|
const installedPackageJsonPath = findInstalledPackageJsonPath(installedName, nodeModulesSearchRoots);
|
|
7924
8094
|
if (!installedPackageJsonPath) continue;
|
|
7925
8095
|
try {
|
|
@@ -7942,22 +8112,41 @@ const findInstalledPackageJsonPath = (packageName, nodeModulesSearchRoots) => {
|
|
|
7942
8112
|
};
|
|
7943
8113
|
const SHELL_SPLIT_PATTERN = /\s*(?:&&|\|\||[;&|])\s*/;
|
|
7944
8114
|
const INLINE_ENV_VAR_PATTERN = /^[A-Z_][A-Z0-9_]*=/;
|
|
8115
|
+
const KNOWN_PACKAGE_BIN_NAMES = new Map([
|
|
8116
|
+
["@tauri-apps/cli", ["tauri"]],
|
|
8117
|
+
["@typescript/native-preview", ["tsgo"]],
|
|
8118
|
+
["playwright-chromium", ["playwright"]],
|
|
8119
|
+
["playwright-firefox", ["playwright"]],
|
|
8120
|
+
["playwright-webkit", ["playwright"]]
|
|
8121
|
+
]);
|
|
8122
|
+
const staticBinNamesForPackage = (packageName) => {
|
|
8123
|
+
const binNames = [...KNOWN_PACKAGE_BIN_NAMES.get(packageName) ?? []];
|
|
8124
|
+
const unscopedName = packageName.split("/").pop();
|
|
8125
|
+
if (unscopedName.endsWith("-cli") && unscopedName.length > 4) binNames.push(unscopedName.slice(0, -4));
|
|
8126
|
+
return binNames;
|
|
8127
|
+
};
|
|
7945
8128
|
const buildBinaryPackageIndex = (nodeModulesSearchRoots, declaredNames) => {
|
|
7946
8129
|
const binToPackage = /* @__PURE__ */ new Map();
|
|
7947
8130
|
const packagesProvidingBinary = /* @__PURE__ */ new Set();
|
|
8131
|
+
const addBinMapping = (binaryName, packageName) => {
|
|
8132
|
+
const mappedPackages = binToPackage.get(binaryName) ?? /* @__PURE__ */ new Set();
|
|
8133
|
+
mappedPackages.add(packageName);
|
|
8134
|
+
binToPackage.set(binaryName, mappedPackages);
|
|
8135
|
+
};
|
|
7948
8136
|
for (const packageName of declaredNames) {
|
|
8137
|
+
for (const staticBinName of staticBinNamesForPackage(packageName)) addBinMapping(staticBinName, packageName);
|
|
7949
8138
|
const packageBinJsonPath = findInstalledPackageJsonPath(packageName, nodeModulesSearchRoots);
|
|
7950
8139
|
if (!packageBinJsonPath) continue;
|
|
7951
8140
|
try {
|
|
7952
8141
|
const binContent = (0, node_fs.readFileSync)(packageBinJsonPath, "utf-8");
|
|
7953
8142
|
const binField = JSON.parse(binContent).bin;
|
|
7954
8143
|
if (typeof binField === "string" && binField.length > 0) {
|
|
7955
|
-
|
|
8144
|
+
addBinMapping(packageName.split("/").pop(), packageName);
|
|
7956
8145
|
packagesProvidingBinary.add(packageName);
|
|
7957
8146
|
} else if (typeof binField === "object" && binField !== null) {
|
|
7958
8147
|
const binaryNames = Object.keys(binField);
|
|
7959
8148
|
if (binaryNames.length === 0) continue;
|
|
7960
|
-
for (const binaryName of binaryNames)
|
|
8149
|
+
for (const binaryName of binaryNames) addBinMapping(binaryName, packageName);
|
|
7961
8150
|
packagesProvidingBinary.add(packageName);
|
|
7962
8151
|
}
|
|
7963
8152
|
} catch {
|
|
@@ -8002,8 +8191,7 @@ const collectCommandReferencedPackages = (command, declaredNames, binToPackage)
|
|
|
8002
8191
|
const effectiveBinary = binaryToken === "npx" || binaryToken === "pnpx" || binaryToken === "bunx" ? tokens[binaryIndex + 1]?.replace(/^.*\//, "") ?? "" : binaryToken;
|
|
8003
8192
|
for (const candidateBinary of [binaryToken, effectiveBinary]) {
|
|
8004
8193
|
if (!candidateBinary) continue;
|
|
8005
|
-
const mappedPackage
|
|
8006
|
-
if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
8194
|
+
for (const mappedPackage of binToPackage.get(candidateBinary) ?? []) if (declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
8007
8195
|
if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
|
|
8008
8196
|
}
|
|
8009
8197
|
}
|
|
@@ -8083,6 +8271,12 @@ const collectConfigReferencedPackages = (rootDir, graph, declaredNames, summaryC
|
|
|
8083
8271
|
deep: 6
|
|
8084
8272
|
}, summaryCache);
|
|
8085
8273
|
for (const documentationPath of documentationFiles) addMatchesFromFile(documentationPath, "importReference", matchesPackageImportReference);
|
|
8274
|
+
const toolingSourceFiles = globPackageFiles(rootDir, ["**/{.dumi,.storybook,.docz,.styleguidist}/**/*.{ts,tsx,js,jsx,mts,mjs}"], {
|
|
8275
|
+
ignore: ["**/node_modules/**"],
|
|
8276
|
+
dot: true,
|
|
8277
|
+
deep: 8
|
|
8278
|
+
}, summaryCache);
|
|
8279
|
+
for (const toolingSourcePath of toolingSourceFiles) addMatchesFromFile(toolingSourcePath, "importReference", matchesPackageImportReference);
|
|
8086
8280
|
return referenced;
|
|
8087
8281
|
};
|
|
8088
8282
|
const PACKAGE_JSON_CONFIG_SECTIONS = [
|
|
@@ -8335,14 +8529,47 @@ const isAlwaysConsideredUsed = (dependencyName) => {
|
|
|
8335
8529
|
//#endregion
|
|
8336
8530
|
//#region src/report/cycles.ts
|
|
8337
8531
|
const UNDEFINED_INDEX = -1;
|
|
8532
|
+
const isCompileTimeErasedEdge = (edge, graph) => {
|
|
8533
|
+
if (edge.isReExportEdge) return false;
|
|
8534
|
+
if (edge.importedSymbols.length === 0) return false;
|
|
8535
|
+
const targetModule = graph.modules[edge.target];
|
|
8536
|
+
if (!targetModule) return false;
|
|
8537
|
+
return edge.importedSymbols.every((symbol) => {
|
|
8538
|
+
if (symbol.isTypeOnly) return true;
|
|
8539
|
+
if (symbol.isNamespace) return false;
|
|
8540
|
+
const exportName = symbol.isDefault ? "default" : symbol.importedName;
|
|
8541
|
+
const matchingExports = targetModule.exports.filter((exportInfo) => exportInfo.name === exportName);
|
|
8542
|
+
return matchingExports.length > 0 && matchingExports.every((exportInfo) => exportInfo.isTypeOnly);
|
|
8543
|
+
});
|
|
8544
|
+
};
|
|
8338
8545
|
const buildAdjacencyList = (graph) => {
|
|
8339
8546
|
const targetSets = Array.from({ length: graph.modules.length }, () => /* @__PURE__ */ new Set());
|
|
8340
8547
|
for (const edge of graph.edges) {
|
|
8548
|
+
if (edge.isDynamic) continue;
|
|
8341
8549
|
if (edge.importedSymbols.every((symbol) => symbol.isTypeOnly)) continue;
|
|
8550
|
+
if (isCompileTimeErasedEdge(edge, graph)) continue;
|
|
8342
8551
|
if (edge.target < graph.modules.length) targetSets[edge.source].add(edge.target);
|
|
8343
8552
|
}
|
|
8344
8553
|
return targetSets.map((targets) => [...targets]);
|
|
8345
8554
|
};
|
|
8555
|
+
const buildModuleInitAccessEdgeSet = (graph) => {
|
|
8556
|
+
const initAccessEdges = /* @__PURE__ */ new Set();
|
|
8557
|
+
for (const edge of graph.edges) {
|
|
8558
|
+
if (edge.isDynamic || edge.isReExportEdge) continue;
|
|
8559
|
+
const topLevelReferences = graph.modules[edge.source]?.topLevelImportReferences;
|
|
8560
|
+
if (!topLevelReferences || topLevelReferences.length === 0) continue;
|
|
8561
|
+
if (edge.importedSymbols.some((symbol) => !symbol.isTypeOnly && topLevelReferences.includes(symbol.localName))) initAccessEdges.add(`${edge.source}:${edge.target}`);
|
|
8562
|
+
}
|
|
8563
|
+
return initAccessEdges;
|
|
8564
|
+
};
|
|
8565
|
+
const cycleHasModuleInitAccess = (cycle, initAccessEdges) => {
|
|
8566
|
+
for (let position = 0; position < cycle.length; position++) {
|
|
8567
|
+
const source = cycle[position];
|
|
8568
|
+
const target = cycle[(position + 1) % cycle.length];
|
|
8569
|
+
if (initAccessEdges.has(`${source}:${target}`)) return true;
|
|
8570
|
+
}
|
|
8571
|
+
return false;
|
|
8572
|
+
};
|
|
8346
8573
|
const findStronglyConnectedComponents = (adjacencyList) => {
|
|
8347
8574
|
const nodeCount = adjacencyList.length;
|
|
8348
8575
|
if (nodeCount === 0) return [];
|
|
@@ -8463,6 +8690,7 @@ const enumerateElementaryCycles = (componentNodes, adjacencyList, graph) => {
|
|
|
8463
8690
|
};
|
|
8464
8691
|
const detectCycles = (graph) => {
|
|
8465
8692
|
const adjacencyList = buildAdjacencyList(graph);
|
|
8693
|
+
const initAccessEdges = buildModuleInitAccessEdgeSet(graph);
|
|
8466
8694
|
const components = findStronglyConnectedComponents(adjacencyList);
|
|
8467
8695
|
const allCycles = [];
|
|
8468
8696
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
@@ -8472,6 +8700,7 @@ const detectCycles = (graph) => {
|
|
|
8472
8700
|
if (component.length > 50) continue;
|
|
8473
8701
|
const elementaryCycles = enumerateElementaryCycles(component, adjacencyList, graph);
|
|
8474
8702
|
for (const cycle of elementaryCycles) {
|
|
8703
|
+
if (!cycleHasModuleInitAccess(cycle, initAccessEdges)) continue;
|
|
8475
8704
|
const key = cycle.join(",");
|
|
8476
8705
|
if (!seenKeys.has(key)) {
|
|
8477
8706
|
seenKeys.add(key);
|
|
@@ -12496,7 +12725,7 @@ const isRecordValue = (value) => typeof value === "object" && value !== null &&
|
|
|
12496
12725
|
const isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
12497
12726
|
const isOptionalArray = (value) => value === void 0 || Array.isArray(value);
|
|
12498
12727
|
const emptyStore = (scopeHash) => ({
|
|
12499
|
-
version:
|
|
12728
|
+
version: 3,
|
|
12500
12729
|
scopeHash,
|
|
12501
12730
|
fileList: null,
|
|
12502
12731
|
resolutions: null,
|
|
@@ -12506,10 +12735,10 @@ const emptyStore = (scopeHash) => ({
|
|
|
12506
12735
|
const readPersistedStore = (cachePath, scopeHash) => {
|
|
12507
12736
|
try {
|
|
12508
12737
|
const parsed = JSON.parse((0, node_fs.readFileSync)(cachePath, "utf-8"));
|
|
12509
|
-
if (isRecordValue(parsed) && parsed.version ===
|
|
12738
|
+
if (isRecordValue(parsed) && parsed.version === 3 && parsed.scopeHash === scopeHash && isRecordValue(parsed.summaries) && isRecordValue(parsed.packageFacts)) {
|
|
12510
12739
|
const persisted = parsed;
|
|
12511
12740
|
return {
|
|
12512
|
-
version:
|
|
12741
|
+
version: 3,
|
|
12513
12742
|
scopeHash,
|
|
12514
12743
|
fileList: isRecordValue(persisted.fileList) ? persisted.fileList : null,
|
|
12515
12744
|
resolutions: isRecordValue(persisted.resolutions) && typeof persisted.resolutions.hash === "string" && isRecordValue(persisted.resolutions.entries) ? persisted.resolutions : null,
|
|
@@ -12532,6 +12761,7 @@ const serializeParsedSource = (parsed, shouldPersistDryPatternFields) => ({
|
|
|
12532
12761
|
memberAccesses: toPersistedArray(parsed.memberAccesses),
|
|
12533
12762
|
wholeObjectUses: toPersistedArray(parsed.wholeObjectUses),
|
|
12534
12763
|
localIdentifierReferences: toPersistedArray(intersectLocalReferencesWithOwnExports(parsed)),
|
|
12764
|
+
topLevelImportReferences: toPersistedArray(parsed.topLevelImportReferences),
|
|
12535
12765
|
referencedFilenames: toPersistedArray(parsed.referencedFilenames),
|
|
12536
12766
|
...shouldPersistDryPatternFields ? {
|
|
12537
12767
|
redundantTypePatterns: toPersistedArray(parsed.redundantTypePatterns),
|
|
@@ -12551,6 +12781,7 @@ const PERSISTED_SOURCE_ARRAY_FIELDS = [
|
|
|
12551
12781
|
"memberAccesses",
|
|
12552
12782
|
"wholeObjectUses",
|
|
12553
12783
|
"localIdentifierReferences",
|
|
12784
|
+
"topLevelImportReferences",
|
|
12554
12785
|
"referencedFilenames",
|
|
12555
12786
|
"redundantTypePatterns",
|
|
12556
12787
|
"identityWrappers",
|
|
@@ -12573,6 +12804,7 @@ const reviveParsedSource = (persisted) => {
|
|
|
12573
12804
|
memberAccesses: source.memberAccesses ?? [],
|
|
12574
12805
|
wholeObjectUses: source.wholeObjectUses ?? [],
|
|
12575
12806
|
localIdentifierReferences: source.localIdentifierReferences ?? [],
|
|
12807
|
+
topLevelImportReferences: source.topLevelImportReferences ?? [],
|
|
12576
12808
|
referencedFilenames: source.referencedFilenames ?? [],
|
|
12577
12809
|
redundantTypePatterns: source.redundantTypePatterns ?? [],
|
|
12578
12810
|
identityWrappers: source.identityWrappers ?? [],
|
|
@@ -12776,7 +13008,7 @@ const createSummaryCache = (cachePath, config) => {
|
|
|
12776
13008
|
if (resolutionEntry !== void 0) compactedResolutions[resolutionKey] = resolutionEntry;
|
|
12777
13009
|
}
|
|
12778
13010
|
const serialized = JSON.stringify({
|
|
12779
|
-
version:
|
|
13011
|
+
version: 3,
|
|
12780
13012
|
scopeHash,
|
|
12781
13013
|
fileList: store.fileList,
|
|
12782
13014
|
resolutions: {
|
package/dist/index.mjs
CHANGED
|
@@ -1322,6 +1322,7 @@ const parseCssImports = (filePath) => {
|
|
|
1322
1322
|
memberAccesses: [],
|
|
1323
1323
|
wholeObjectUses: [],
|
|
1324
1324
|
localIdentifierReferences: [],
|
|
1325
|
+
topLevelImportReferences: [],
|
|
1325
1326
|
referencedFilenames: [],
|
|
1326
1327
|
redundantTypePatterns: [],
|
|
1327
1328
|
identityWrappers: [],
|
|
@@ -1350,18 +1351,142 @@ const collectLocalIdentifierReferences = (statements) => {
|
|
|
1350
1351
|
for (const value of Object.values(record)) if (Array.isArray(value)) for (const innerValue of value) visitNode(innerValue);
|
|
1351
1352
|
else if (value && typeof value === "object") visitNode(value);
|
|
1352
1353
|
};
|
|
1354
|
+
const visitExportedDeclarationValues = (declaration) => {
|
|
1355
|
+
if (!declaration || typeof declaration !== "object") return;
|
|
1356
|
+
const record = declaration;
|
|
1357
|
+
if (record.type === "VariableDeclaration" && Array.isArray(record.declarations)) {
|
|
1358
|
+
for (const declarator of record.declarations) if (declarator && typeof declarator === "object") visitNode(declarator.init);
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1361
|
+
if (record.type === "FunctionDeclaration" || record.type === "ClassDeclaration") {
|
|
1362
|
+
visitNode(record.params);
|
|
1363
|
+
visitNode(record.superClass);
|
|
1364
|
+
visitNode(record.body);
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
if (typeof record.type === "string" && !record.type.startsWith("TS")) visitNode(declaration);
|
|
1368
|
+
};
|
|
1353
1369
|
for (const statement of statements) {
|
|
1354
|
-
if (statement.type === "ImportDeclaration" || statement.type === "
|
|
1370
|
+
if (statement.type === "ImportDeclaration" || statement.type === "ExportAllDeclaration") continue;
|
|
1371
|
+
if (statement.type === "ExportNamedDeclaration") {
|
|
1372
|
+
visitExportedDeclarationValues(statement.declaration);
|
|
1373
|
+
continue;
|
|
1374
|
+
}
|
|
1375
|
+
if (statement.type === "ExportDefaultDeclaration") {
|
|
1376
|
+
visitExportedDeclarationValues(statement.declaration);
|
|
1377
|
+
continue;
|
|
1378
|
+
}
|
|
1355
1379
|
visitNode(statement);
|
|
1356
1380
|
}
|
|
1357
1381
|
return references;
|
|
1358
1382
|
};
|
|
1383
|
+
const TS_VALUE_WRAPPER_NODE_TYPES = new Set([
|
|
1384
|
+
"TSAsExpression",
|
|
1385
|
+
"TSSatisfiesExpression",
|
|
1386
|
+
"TSNonNullExpression",
|
|
1387
|
+
"TSInstantiationExpression",
|
|
1388
|
+
"TSTypeAssertion"
|
|
1389
|
+
]);
|
|
1390
|
+
const TS_RUNTIME_DECLARATION_NODE_TYPES = new Set([
|
|
1391
|
+
"TSEnumDeclaration",
|
|
1392
|
+
"TSModuleDeclaration",
|
|
1393
|
+
"TSExportAssignment"
|
|
1394
|
+
]);
|
|
1395
|
+
const FUNCTION_NODE_TYPES = new Set([
|
|
1396
|
+
"FunctionDeclaration",
|
|
1397
|
+
"FunctionExpression",
|
|
1398
|
+
"ArrowFunctionExpression"
|
|
1399
|
+
]);
|
|
1400
|
+
const collectStaticImportLocalNames = (imports) => {
|
|
1401
|
+
const localNames = /* @__PURE__ */ new Set();
|
|
1402
|
+
for (const importInfo of imports) {
|
|
1403
|
+
if (importInfo.isDynamic || importInfo.isTypeOnly) continue;
|
|
1404
|
+
for (const binding of importInfo.importedNames) {
|
|
1405
|
+
if (binding.isTypeOnly) continue;
|
|
1406
|
+
const localName = binding.alias ?? binding.name;
|
|
1407
|
+
if (localName && localName !== "*") localNames.add(localName);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
return localNames;
|
|
1411
|
+
};
|
|
1412
|
+
const collectTopLevelImportReferences = (bodyNodes, importLocalNames) => {
|
|
1413
|
+
const referencedNames = /* @__PURE__ */ new Set();
|
|
1414
|
+
if (importLocalNames.size === 0) return [];
|
|
1415
|
+
const visitClassBody = (classBody) => {
|
|
1416
|
+
const bodyElements = classBody.body ?? [];
|
|
1417
|
+
for (const element of bodyElements) {
|
|
1418
|
+
if (element.type === "StaticBlock") {
|
|
1419
|
+
visitValueNode(element.body);
|
|
1420
|
+
continue;
|
|
1421
|
+
}
|
|
1422
|
+
if (Boolean(element.computed)) visitValueNode(element.key);
|
|
1423
|
+
const isStatic = Boolean(element.static);
|
|
1424
|
+
if (element.type === "PropertyDefinition" && isStatic) visitValueNode(element.value);
|
|
1425
|
+
visitValueNode(element.decorators);
|
|
1426
|
+
}
|
|
1427
|
+
};
|
|
1428
|
+
const visitValueNode = (node) => {
|
|
1429
|
+
if (Array.isArray(node)) {
|
|
1430
|
+
for (const element of node) visitValueNode(element);
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
if (!isWalkableNode(node)) return;
|
|
1434
|
+
if (node.type === "Identifier" || node.type === "JSXIdentifier") {
|
|
1435
|
+
const identifierName = node.name;
|
|
1436
|
+
if (identifierName && importLocalNames.has(identifierName)) referencedNames.add(identifierName);
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
if (node.type.startsWith("TS")) {
|
|
1440
|
+
if (TS_VALUE_WRAPPER_NODE_TYPES.has(node.type)) {
|
|
1441
|
+
visitValueNode(node.expression);
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
if (!TS_RUNTIME_DECLARATION_NODE_TYPES.has(node.type)) return;
|
|
1445
|
+
}
|
|
1446
|
+
if (FUNCTION_NODE_TYPES.has(node.type)) return;
|
|
1447
|
+
if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
|
|
1448
|
+
visitValueNode(node.superClass);
|
|
1449
|
+
visitValueNode(node.decorators);
|
|
1450
|
+
const classBody = node.body;
|
|
1451
|
+
if (classBody) visitClassBody(classBody);
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
if (node.type === "CallExpression" || node.type === "NewExpression") {
|
|
1455
|
+
const callee = node.callee;
|
|
1456
|
+
if (callee && FUNCTION_NODE_TYPES.has(callee.type)) visitValueNode(callee.body);
|
|
1457
|
+
}
|
|
1458
|
+
if (node.type === "MemberExpression" || node.type === "JSXMemberExpression") {
|
|
1459
|
+
const memberNode = node;
|
|
1460
|
+
visitValueNode(memberNode.object);
|
|
1461
|
+
if (node.computed) visitValueNode(memberNode.property);
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
if (node.type === "Property") {
|
|
1465
|
+
const propertyNode = node;
|
|
1466
|
+
if (node.computed) visitValueNode(propertyNode.key);
|
|
1467
|
+
visitValueNode(propertyNode.value);
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) for (const element of value) visitValueNode(element);
|
|
1471
|
+
else if (value && typeof value === "object") visitValueNode(value);
|
|
1472
|
+
};
|
|
1473
|
+
for (const statement of bodyNodes) {
|
|
1474
|
+
if (statement.type === "ImportDeclaration" || statement.type === "ExportAllDeclaration") continue;
|
|
1475
|
+
if (statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration") {
|
|
1476
|
+
visitValueNode(statement.declaration);
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1479
|
+
visitValueNode(statement);
|
|
1480
|
+
}
|
|
1481
|
+
return [...referencedNames];
|
|
1482
|
+
};
|
|
1359
1483
|
const createEmptyParsedSource = () => ({
|
|
1360
1484
|
imports: [],
|
|
1361
1485
|
exports: [],
|
|
1362
1486
|
memberAccesses: [],
|
|
1363
1487
|
wholeObjectUses: [],
|
|
1364
1488
|
localIdentifierReferences: [],
|
|
1489
|
+
topLevelImportReferences: [],
|
|
1365
1490
|
referencedFilenames: [],
|
|
1366
1491
|
redundantTypePatterns: [],
|
|
1367
1492
|
identityWrappers: [],
|
|
@@ -1573,6 +1698,7 @@ const parseSourceFile = (filePath) => {
|
|
|
1573
1698
|
collectMemberAccesses(program.body, namespaceLocalNames, memberAccesses, wholeObjectUses);
|
|
1574
1699
|
}, void 0);
|
|
1575
1700
|
const localIdentifierReferences = safeWalk("collectLocalIdentifierReferences", () => collectLocalIdentifierReferences(program.body), []);
|
|
1701
|
+
const topLevelImportReferences = safeWalk("collectTopLevelImportReferences", () => collectTopLevelImportReferences(program.body, collectStaticImportLocalNames(imports)), []);
|
|
1576
1702
|
const redundantTypePatterns = [];
|
|
1577
1703
|
const identityWrappers = [];
|
|
1578
1704
|
const typeDefinitionHashes = [];
|
|
@@ -1617,6 +1743,7 @@ const parseSourceFile = (filePath) => {
|
|
|
1617
1743
|
memberAccesses,
|
|
1618
1744
|
wholeObjectUses,
|
|
1619
1745
|
localIdentifierReferences,
|
|
1746
|
+
topLevelImportReferences,
|
|
1620
1747
|
referencedFilenames: extractReferencedFilenames(sourceText),
|
|
1621
1748
|
redundantTypePatterns,
|
|
1622
1749
|
identityWrappers,
|
|
@@ -1757,6 +1884,29 @@ const collectMemberAccesses = (bodyNodes, namespaceLocalNames, memberAccesses, w
|
|
|
1757
1884
|
const spreadArgument = node.argument;
|
|
1758
1885
|
if (spreadArgument?.type === "Identifier" && namespaceLocalNames.has(spreadArgument.name)) wholeObjectUses.push(spreadArgument.name);
|
|
1759
1886
|
}
|
|
1887
|
+
if (node.type === "VariableDeclarator") {
|
|
1888
|
+
const declarator = node;
|
|
1889
|
+
if (declarator.init?.type === "Identifier" && namespaceLocalNames.has(declarator.init.name) && declarator.id?.type === "ObjectPattern") {
|
|
1890
|
+
const namespaceName = declarator.init.name;
|
|
1891
|
+
const patternProperties = declarator.id.properties;
|
|
1892
|
+
for (const property of patternProperties) {
|
|
1893
|
+
if (property.type === "RestElement") {
|
|
1894
|
+
wholeObjectUses.push(namespaceName);
|
|
1895
|
+
continue;
|
|
1896
|
+
}
|
|
1897
|
+
const propertyKey = property.key;
|
|
1898
|
+
if (Boolean(property.computed)) wholeObjectUses.push(namespaceName);
|
|
1899
|
+
else if (propertyKey?.type === "Identifier" && propertyKey.name) memberAccesses.push({
|
|
1900
|
+
objectName: namespaceName,
|
|
1901
|
+
memberName: propertyKey.name
|
|
1902
|
+
});
|
|
1903
|
+
else if (propertyKey?.type === "Literal" && typeof propertyKey.value === "string") memberAccesses.push({
|
|
1904
|
+
objectName: namespaceName,
|
|
1905
|
+
memberName: propertyKey.value
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1760
1910
|
if (node.type === "ForInStatement") {
|
|
1761
1911
|
const forInRight = node.right;
|
|
1762
1912
|
if (forInRight?.type === "Identifier" && namespaceLocalNames.has(forInRight.name)) wholeObjectUses.push(forInRight.name);
|
|
@@ -5090,6 +5240,13 @@ const extractCiWorkflowEntries = (rootDir) => {
|
|
|
5090
5240
|
const entries = [];
|
|
5091
5241
|
const workflowsDir = join(rootDir, ".github", "workflows");
|
|
5092
5242
|
if (!existsSync(workflowsDir)) return entries;
|
|
5243
|
+
const nestedToolPackageJsonPaths = fg.sync("**/package.json", {
|
|
5244
|
+
cwd: join(rootDir, ".github"),
|
|
5245
|
+
absolute: true,
|
|
5246
|
+
onlyFiles: true,
|
|
5247
|
+
ignore: ["**/node_modules/**"]
|
|
5248
|
+
});
|
|
5249
|
+
for (const nestedPackageJsonPath of nestedToolPackageJsonPaths) entries.push(...extractScriptEntries(dirname(nestedPackageJsonPath)));
|
|
5093
5250
|
const workflowFiles = fg.sync("*.{yml,yaml}", {
|
|
5094
5251
|
cwd: workflowsDir,
|
|
5095
5252
|
absolute: true,
|
|
@@ -6692,8 +6849,10 @@ const discoverTestRunnerEntryPoints = (rootDir, workspacePackages) => {
|
|
|
6692
6849
|
customPatterns = extractJestTestMatchPatterns(directory);
|
|
6693
6850
|
if (customPatterns.length === 0 && monorepoRoot) customPatterns = extractJestTestMatchPatterns(monorepoRoot);
|
|
6694
6851
|
}
|
|
6695
|
-
if (customPatterns.length > 0)
|
|
6696
|
-
|
|
6852
|
+
if (customPatterns.length > 0) {
|
|
6853
|
+
activatedPatterns.push(...customPatterns);
|
|
6854
|
+
if (isJestRunner) activatedPatterns.push("**/__mocks__/**/*.{ts,tsx,js,jsx,mjs,cjs}");
|
|
6855
|
+
} else activatedPatterns.push(...runner.entryPatterns);
|
|
6697
6856
|
activatedFixturePatterns.push(...runner.fixturePatterns);
|
|
6698
6857
|
activatedAlwaysUsed.push(...runner.alwaysUsed);
|
|
6699
6858
|
}
|
|
@@ -6924,6 +7083,7 @@ const deserializeParsedSource = (serialized) => ({
|
|
|
6924
7083
|
memberAccesses: serialized.memberAccesses,
|
|
6925
7084
|
wholeObjectUses: serialized.wholeObjectUses,
|
|
6926
7085
|
localIdentifierReferences: serialized.localIdentifierReferences,
|
|
7086
|
+
topLevelImportReferences: serialized.topLevelImportReferences,
|
|
6927
7087
|
referencedFilenames: serialized.referencedFilenames,
|
|
6928
7088
|
redundantTypePatterns: serialized.redundantTypePatterns,
|
|
6929
7089
|
identityWrappers: serialized.identityWrappers,
|
|
@@ -6988,6 +7148,7 @@ const parseFilesWithWorkerPool = async (files, workerCount) => {
|
|
|
6988
7148
|
memberAccesses: [],
|
|
6989
7149
|
wholeObjectUses: [],
|
|
6990
7150
|
localIdentifierReferences: [],
|
|
7151
|
+
topLevelImportReferences: [],
|
|
6991
7152
|
referencedFilenames: [],
|
|
6992
7153
|
redundantTypePatterns: [],
|
|
6993
7154
|
identityWrappers: [],
|
|
@@ -7062,6 +7223,7 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7062
7223
|
memberAccesses: input.parsed.memberAccesses,
|
|
7063
7224
|
wholeObjectUses: input.parsed.wholeObjectUses,
|
|
7064
7225
|
localIdentifierReferences: input.parsed.localIdentifierReferences,
|
|
7226
|
+
topLevelImportReferences: input.parsed.topLevelImportReferences,
|
|
7065
7227
|
referencedFilenames: input.parsed.referencedFilenames,
|
|
7066
7228
|
redundantTypePatterns: input.parsed.redundantTypePatterns,
|
|
7067
7229
|
identityWrappers: input.parsed.identityWrappers,
|
|
@@ -7080,12 +7242,13 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7080
7242
|
}));
|
|
7081
7243
|
const edges = [];
|
|
7082
7244
|
const reverseEdges = /* @__PURE__ */ new Map();
|
|
7083
|
-
const addEdge = (sourceIndex, targetIndex, symbols, isReExportEdge = false, reExportedNames = [], reExportMappings = []) => {
|
|
7245
|
+
const addEdge = (sourceIndex, targetIndex, symbols, isReExportEdge = false, reExportedNames = [], reExportMappings = [], isDynamic = false) => {
|
|
7084
7246
|
edges.push({
|
|
7085
7247
|
source: sourceIndex,
|
|
7086
7248
|
target: targetIndex,
|
|
7087
7249
|
importedSymbols: symbols,
|
|
7088
7250
|
isReExportEdge,
|
|
7251
|
+
isDynamic,
|
|
7089
7252
|
reExportedNames,
|
|
7090
7253
|
reExportMappings
|
|
7091
7254
|
});
|
|
@@ -7104,7 +7267,7 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7104
7267
|
const relativePath = toPosixPath(path.relative(sourceDir, filePath));
|
|
7105
7268
|
if (minimatch(relativePath.startsWith(".") ? relativePath : `./${relativePath}`, globPattern)) {
|
|
7106
7269
|
const targetIndex = fileIdMap.get(filePath);
|
|
7107
|
-
if (targetIndex !== void 0) addEdge(sourceIndex, targetIndex, []);
|
|
7270
|
+
if (targetIndex !== void 0) addEdge(sourceIndex, targetIndex, [], false, [], [], true);
|
|
7108
7271
|
}
|
|
7109
7272
|
}
|
|
7110
7273
|
continue;
|
|
@@ -7119,7 +7282,7 @@ const buildDependencyGraph = (inputs) => {
|
|
|
7119
7282
|
isTypeOnly: importedName.isTypeOnly,
|
|
7120
7283
|
isNamespace: importedName.isNamespace,
|
|
7121
7284
|
isDefault: importedName.isDefault
|
|
7122
|
-
})));
|
|
7285
|
+
})), false, [], [], importInfo.isDynamic);
|
|
7123
7286
|
}
|
|
7124
7287
|
const reExportsByTarget = /* @__PURE__ */ new Map();
|
|
7125
7288
|
for (const exportInfo of input.parsed.exports) {
|
|
@@ -7382,9 +7545,9 @@ const EXCLUDED_EXTENSIONS = new Set([
|
|
|
7382
7545
|
".graphql",
|
|
7383
7546
|
".gql"
|
|
7384
7547
|
]);
|
|
7385
|
-
const TEST_FILE_PATTERN = /(?:\.(?:test|spec|stories|story|cy)\.|(?:^|\/)__tests__\/)/;
|
|
7386
|
-
const EXCLUDED_DIRECTORY_PATTERN = /(?:^|\/)(?:e2e|cypress|playwright|__fixtures__|__snapshots__|scripts)\/(?!.*node_modules)/;
|
|
7387
|
-
const CONFIG_FILE_PATTERN = /(?:^|\/)(?:[^/]+\.config\.[tj]sx?$|[^/]+\.setup\.[tj]sx?$|setupTests\.[tj]sx?$|jest\.setup\.[tj]sx?$|vitest\.setup\.[tj]sx?$)/;
|
|
7548
|
+
const TEST_FILE_PATTERN = /(?:\.(?:test|spec|stories|story|cy|test-d)\.|(?:^|\/)__tests__\/)/;
|
|
7549
|
+
const EXCLUDED_DIRECTORY_PATTERN = /(?:^|\/)(?:e2e|cypress|playwright|__fixtures__|__snapshots__|public|scripts)\/(?!.*node_modules)/;
|
|
7550
|
+
const CONFIG_FILE_PATTERN = /(?:^|\/)(?:[^/]+\.config\.[tj]sx?$|[^/]+\.config\.[^/]+\.[tj]sx?$|[^/]+\.setup\.[tj]sx?$|setupTests\.[tj]sx?$|jest\.setup\.[tj]sx?$|vitest\.setup\.[tj]sx?$)/;
|
|
7388
7551
|
const hasExcludedExtension = (filePath) => {
|
|
7389
7552
|
const lastDot = filePath.lastIndexOf(".");
|
|
7390
7553
|
if (lastDot === -1) return false;
|
|
@@ -7460,6 +7623,7 @@ const detectDeadExports = (graph, config) => {
|
|
|
7460
7623
|
if (usageMap.has(usageKey)) continue;
|
|
7461
7624
|
if (module.localIdentifierReferences.includes(exportInfo.name)) continue;
|
|
7462
7625
|
if (!exportInfo.isDefault && defaultExportLinkedNames.has(exportInfo.name)) continue;
|
|
7626
|
+
if (exportInfo.isDefault && exportInfo.defaultExportLocalName && usageMap.has(`${module.fileId.path}::${exportInfo.defaultExportLocalName}`)) continue;
|
|
7463
7627
|
unusedExports.push({
|
|
7464
7628
|
path: module.fileId.path,
|
|
7465
7629
|
name: exportInfo.name,
|
|
@@ -7494,6 +7658,10 @@ const buildUsageMap = (graph) => {
|
|
|
7494
7658
|
const targetModule = graph.modules[edge.target];
|
|
7495
7659
|
if (!targetModule) continue;
|
|
7496
7660
|
const sourceModule = graph.modules[edge.source];
|
|
7661
|
+
if (edge.isDynamic && edge.importedSymbols.length === 0) {
|
|
7662
|
+
markAllExportsUsedRecursive(targetModule, graph, sourceToTargetMap, usedExportKeys, /* @__PURE__ */ new Set());
|
|
7663
|
+
continue;
|
|
7664
|
+
}
|
|
7497
7665
|
for (const symbol of edge.importedSymbols) if (symbol.isNamespace) handleNamespaceImport(sourceModule, targetModule, symbol.localName, graph, sourceToTargetMap, usedExportKeys);
|
|
7498
7666
|
else {
|
|
7499
7667
|
const importName = symbol.isDefault ? "default" : symbol.importedName;
|
|
@@ -7883,10 +8051,12 @@ const hasJsxFiles = (graph) => graph.modules.some((module) => {
|
|
|
7883
8051
|
const filePath = module.fileId.path;
|
|
7884
8052
|
return filePath.endsWith(".tsx") || filePath.endsWith(".jsx");
|
|
7885
8053
|
});
|
|
8054
|
+
const KNOWN_PEER_DEPENDENCY_NAMES = new Map([["vitest-axe", ["axe-core"]], ["jest-axe", ["axe-core"]]]);
|
|
7886
8055
|
const collectPeerSatisfiedPackages = (nodeModulesSearchRoots, declaredNames, confirmedUsedNames) => {
|
|
7887
8056
|
const peerSatisfied = /* @__PURE__ */ new Set();
|
|
7888
8057
|
for (const installedName of declaredNames) {
|
|
7889
8058
|
if (!confirmedUsedNames.has(installedName)) continue;
|
|
8059
|
+
for (const knownPeerName of KNOWN_PEER_DEPENDENCY_NAMES.get(installedName) ?? []) if (declaredNames.has(knownPeerName)) peerSatisfied.add(knownPeerName);
|
|
7890
8060
|
const installedPackageJsonPath = findInstalledPackageJsonPath(installedName, nodeModulesSearchRoots);
|
|
7891
8061
|
if (!installedPackageJsonPath) continue;
|
|
7892
8062
|
try {
|
|
@@ -7909,22 +8079,41 @@ const findInstalledPackageJsonPath = (packageName, nodeModulesSearchRoots) => {
|
|
|
7909
8079
|
};
|
|
7910
8080
|
const SHELL_SPLIT_PATTERN = /\s*(?:&&|\|\||[;&|])\s*/;
|
|
7911
8081
|
const INLINE_ENV_VAR_PATTERN = /^[A-Z_][A-Z0-9_]*=/;
|
|
8082
|
+
const KNOWN_PACKAGE_BIN_NAMES = new Map([
|
|
8083
|
+
["@tauri-apps/cli", ["tauri"]],
|
|
8084
|
+
["@typescript/native-preview", ["tsgo"]],
|
|
8085
|
+
["playwright-chromium", ["playwright"]],
|
|
8086
|
+
["playwright-firefox", ["playwright"]],
|
|
8087
|
+
["playwright-webkit", ["playwright"]]
|
|
8088
|
+
]);
|
|
8089
|
+
const staticBinNamesForPackage = (packageName) => {
|
|
8090
|
+
const binNames = [...KNOWN_PACKAGE_BIN_NAMES.get(packageName) ?? []];
|
|
8091
|
+
const unscopedName = packageName.split("/").pop();
|
|
8092
|
+
if (unscopedName.endsWith("-cli") && unscopedName.length > 4) binNames.push(unscopedName.slice(0, -4));
|
|
8093
|
+
return binNames;
|
|
8094
|
+
};
|
|
7912
8095
|
const buildBinaryPackageIndex = (nodeModulesSearchRoots, declaredNames) => {
|
|
7913
8096
|
const binToPackage = /* @__PURE__ */ new Map();
|
|
7914
8097
|
const packagesProvidingBinary = /* @__PURE__ */ new Set();
|
|
8098
|
+
const addBinMapping = (binaryName, packageName) => {
|
|
8099
|
+
const mappedPackages = binToPackage.get(binaryName) ?? /* @__PURE__ */ new Set();
|
|
8100
|
+
mappedPackages.add(packageName);
|
|
8101
|
+
binToPackage.set(binaryName, mappedPackages);
|
|
8102
|
+
};
|
|
7915
8103
|
for (const packageName of declaredNames) {
|
|
8104
|
+
for (const staticBinName of staticBinNamesForPackage(packageName)) addBinMapping(staticBinName, packageName);
|
|
7916
8105
|
const packageBinJsonPath = findInstalledPackageJsonPath(packageName, nodeModulesSearchRoots);
|
|
7917
8106
|
if (!packageBinJsonPath) continue;
|
|
7918
8107
|
try {
|
|
7919
8108
|
const binContent = readFileSync(packageBinJsonPath, "utf-8");
|
|
7920
8109
|
const binField = JSON.parse(binContent).bin;
|
|
7921
8110
|
if (typeof binField === "string" && binField.length > 0) {
|
|
7922
|
-
|
|
8111
|
+
addBinMapping(packageName.split("/").pop(), packageName);
|
|
7923
8112
|
packagesProvidingBinary.add(packageName);
|
|
7924
8113
|
} else if (typeof binField === "object" && binField !== null) {
|
|
7925
8114
|
const binaryNames = Object.keys(binField);
|
|
7926
8115
|
if (binaryNames.length === 0) continue;
|
|
7927
|
-
for (const binaryName of binaryNames)
|
|
8116
|
+
for (const binaryName of binaryNames) addBinMapping(binaryName, packageName);
|
|
7928
8117
|
packagesProvidingBinary.add(packageName);
|
|
7929
8118
|
}
|
|
7930
8119
|
} catch {
|
|
@@ -7969,8 +8158,7 @@ const collectCommandReferencedPackages = (command, declaredNames, binToPackage)
|
|
|
7969
8158
|
const effectiveBinary = binaryToken === "npx" || binaryToken === "pnpx" || binaryToken === "bunx" ? tokens[binaryIndex + 1]?.replace(/^.*\//, "") ?? "" : binaryToken;
|
|
7970
8159
|
for (const candidateBinary of [binaryToken, effectiveBinary]) {
|
|
7971
8160
|
if (!candidateBinary) continue;
|
|
7972
|
-
const mappedPackage
|
|
7973
|
-
if (mappedPackage && declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
8161
|
+
for (const mappedPackage of binToPackage.get(candidateBinary) ?? []) if (declaredNames.has(mappedPackage)) referenced.add(mappedPackage);
|
|
7974
8162
|
if (declaredNames.has(candidateBinary)) referenced.add(candidateBinary);
|
|
7975
8163
|
}
|
|
7976
8164
|
}
|
|
@@ -8050,6 +8238,12 @@ const collectConfigReferencedPackages = (rootDir, graph, declaredNames, summaryC
|
|
|
8050
8238
|
deep: 6
|
|
8051
8239
|
}, summaryCache);
|
|
8052
8240
|
for (const documentationPath of documentationFiles) addMatchesFromFile(documentationPath, "importReference", matchesPackageImportReference);
|
|
8241
|
+
const toolingSourceFiles = globPackageFiles(rootDir, ["**/{.dumi,.storybook,.docz,.styleguidist}/**/*.{ts,tsx,js,jsx,mts,mjs}"], {
|
|
8242
|
+
ignore: ["**/node_modules/**"],
|
|
8243
|
+
dot: true,
|
|
8244
|
+
deep: 8
|
|
8245
|
+
}, summaryCache);
|
|
8246
|
+
for (const toolingSourcePath of toolingSourceFiles) addMatchesFromFile(toolingSourcePath, "importReference", matchesPackageImportReference);
|
|
8053
8247
|
return referenced;
|
|
8054
8248
|
};
|
|
8055
8249
|
const PACKAGE_JSON_CONFIG_SECTIONS = [
|
|
@@ -8302,14 +8496,47 @@ const isAlwaysConsideredUsed = (dependencyName) => {
|
|
|
8302
8496
|
//#endregion
|
|
8303
8497
|
//#region src/report/cycles.ts
|
|
8304
8498
|
const UNDEFINED_INDEX = -1;
|
|
8499
|
+
const isCompileTimeErasedEdge = (edge, graph) => {
|
|
8500
|
+
if (edge.isReExportEdge) return false;
|
|
8501
|
+
if (edge.importedSymbols.length === 0) return false;
|
|
8502
|
+
const targetModule = graph.modules[edge.target];
|
|
8503
|
+
if (!targetModule) return false;
|
|
8504
|
+
return edge.importedSymbols.every((symbol) => {
|
|
8505
|
+
if (symbol.isTypeOnly) return true;
|
|
8506
|
+
if (symbol.isNamespace) return false;
|
|
8507
|
+
const exportName = symbol.isDefault ? "default" : symbol.importedName;
|
|
8508
|
+
const matchingExports = targetModule.exports.filter((exportInfo) => exportInfo.name === exportName);
|
|
8509
|
+
return matchingExports.length > 0 && matchingExports.every((exportInfo) => exportInfo.isTypeOnly);
|
|
8510
|
+
});
|
|
8511
|
+
};
|
|
8305
8512
|
const buildAdjacencyList = (graph) => {
|
|
8306
8513
|
const targetSets = Array.from({ length: graph.modules.length }, () => /* @__PURE__ */ new Set());
|
|
8307
8514
|
for (const edge of graph.edges) {
|
|
8515
|
+
if (edge.isDynamic) continue;
|
|
8308
8516
|
if (edge.importedSymbols.every((symbol) => symbol.isTypeOnly)) continue;
|
|
8517
|
+
if (isCompileTimeErasedEdge(edge, graph)) continue;
|
|
8309
8518
|
if (edge.target < graph.modules.length) targetSets[edge.source].add(edge.target);
|
|
8310
8519
|
}
|
|
8311
8520
|
return targetSets.map((targets) => [...targets]);
|
|
8312
8521
|
};
|
|
8522
|
+
const buildModuleInitAccessEdgeSet = (graph) => {
|
|
8523
|
+
const initAccessEdges = /* @__PURE__ */ new Set();
|
|
8524
|
+
for (const edge of graph.edges) {
|
|
8525
|
+
if (edge.isDynamic || edge.isReExportEdge) continue;
|
|
8526
|
+
const topLevelReferences = graph.modules[edge.source]?.topLevelImportReferences;
|
|
8527
|
+
if (!topLevelReferences || topLevelReferences.length === 0) continue;
|
|
8528
|
+
if (edge.importedSymbols.some((symbol) => !symbol.isTypeOnly && topLevelReferences.includes(symbol.localName))) initAccessEdges.add(`${edge.source}:${edge.target}`);
|
|
8529
|
+
}
|
|
8530
|
+
return initAccessEdges;
|
|
8531
|
+
};
|
|
8532
|
+
const cycleHasModuleInitAccess = (cycle, initAccessEdges) => {
|
|
8533
|
+
for (let position = 0; position < cycle.length; position++) {
|
|
8534
|
+
const source = cycle[position];
|
|
8535
|
+
const target = cycle[(position + 1) % cycle.length];
|
|
8536
|
+
if (initAccessEdges.has(`${source}:${target}`)) return true;
|
|
8537
|
+
}
|
|
8538
|
+
return false;
|
|
8539
|
+
};
|
|
8313
8540
|
const findStronglyConnectedComponents = (adjacencyList) => {
|
|
8314
8541
|
const nodeCount = adjacencyList.length;
|
|
8315
8542
|
if (nodeCount === 0) return [];
|
|
@@ -8430,6 +8657,7 @@ const enumerateElementaryCycles = (componentNodes, adjacencyList, graph) => {
|
|
|
8430
8657
|
};
|
|
8431
8658
|
const detectCycles = (graph) => {
|
|
8432
8659
|
const adjacencyList = buildAdjacencyList(graph);
|
|
8660
|
+
const initAccessEdges = buildModuleInitAccessEdgeSet(graph);
|
|
8433
8661
|
const components = findStronglyConnectedComponents(adjacencyList);
|
|
8434
8662
|
const allCycles = [];
|
|
8435
8663
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
@@ -8439,6 +8667,7 @@ const detectCycles = (graph) => {
|
|
|
8439
8667
|
if (component.length > 50) continue;
|
|
8440
8668
|
const elementaryCycles = enumerateElementaryCycles(component, adjacencyList, graph);
|
|
8441
8669
|
for (const cycle of elementaryCycles) {
|
|
8670
|
+
if (!cycleHasModuleInitAccess(cycle, initAccessEdges)) continue;
|
|
8442
8671
|
const key = cycle.join(",");
|
|
8443
8672
|
if (!seenKeys.has(key)) {
|
|
8444
8673
|
seenKeys.add(key);
|
|
@@ -12463,7 +12692,7 @@ const isRecordValue = (value) => typeof value === "object" && value !== null &&
|
|
|
12463
12692
|
const isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
12464
12693
|
const isOptionalArray = (value) => value === void 0 || Array.isArray(value);
|
|
12465
12694
|
const emptyStore = (scopeHash) => ({
|
|
12466
|
-
version:
|
|
12695
|
+
version: 3,
|
|
12467
12696
|
scopeHash,
|
|
12468
12697
|
fileList: null,
|
|
12469
12698
|
resolutions: null,
|
|
@@ -12473,10 +12702,10 @@ const emptyStore = (scopeHash) => ({
|
|
|
12473
12702
|
const readPersistedStore = (cachePath, scopeHash) => {
|
|
12474
12703
|
try {
|
|
12475
12704
|
const parsed = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
12476
|
-
if (isRecordValue(parsed) && parsed.version ===
|
|
12705
|
+
if (isRecordValue(parsed) && parsed.version === 3 && parsed.scopeHash === scopeHash && isRecordValue(parsed.summaries) && isRecordValue(parsed.packageFacts)) {
|
|
12477
12706
|
const persisted = parsed;
|
|
12478
12707
|
return {
|
|
12479
|
-
version:
|
|
12708
|
+
version: 3,
|
|
12480
12709
|
scopeHash,
|
|
12481
12710
|
fileList: isRecordValue(persisted.fileList) ? persisted.fileList : null,
|
|
12482
12711
|
resolutions: isRecordValue(persisted.resolutions) && typeof persisted.resolutions.hash === "string" && isRecordValue(persisted.resolutions.entries) ? persisted.resolutions : null,
|
|
@@ -12499,6 +12728,7 @@ const serializeParsedSource = (parsed, shouldPersistDryPatternFields) => ({
|
|
|
12499
12728
|
memberAccesses: toPersistedArray(parsed.memberAccesses),
|
|
12500
12729
|
wholeObjectUses: toPersistedArray(parsed.wholeObjectUses),
|
|
12501
12730
|
localIdentifierReferences: toPersistedArray(intersectLocalReferencesWithOwnExports(parsed)),
|
|
12731
|
+
topLevelImportReferences: toPersistedArray(parsed.topLevelImportReferences),
|
|
12502
12732
|
referencedFilenames: toPersistedArray(parsed.referencedFilenames),
|
|
12503
12733
|
...shouldPersistDryPatternFields ? {
|
|
12504
12734
|
redundantTypePatterns: toPersistedArray(parsed.redundantTypePatterns),
|
|
@@ -12518,6 +12748,7 @@ const PERSISTED_SOURCE_ARRAY_FIELDS = [
|
|
|
12518
12748
|
"memberAccesses",
|
|
12519
12749
|
"wholeObjectUses",
|
|
12520
12750
|
"localIdentifierReferences",
|
|
12751
|
+
"topLevelImportReferences",
|
|
12521
12752
|
"referencedFilenames",
|
|
12522
12753
|
"redundantTypePatterns",
|
|
12523
12754
|
"identityWrappers",
|
|
@@ -12540,6 +12771,7 @@ const reviveParsedSource = (persisted) => {
|
|
|
12540
12771
|
memberAccesses: source.memberAccesses ?? [],
|
|
12541
12772
|
wholeObjectUses: source.wholeObjectUses ?? [],
|
|
12542
12773
|
localIdentifierReferences: source.localIdentifierReferences ?? [],
|
|
12774
|
+
topLevelImportReferences: source.topLevelImportReferences ?? [],
|
|
12543
12775
|
referencedFilenames: source.referencedFilenames ?? [],
|
|
12544
12776
|
redundantTypePatterns: source.redundantTypePatterns ?? [],
|
|
12545
12777
|
identityWrappers: source.identityWrappers ?? [],
|
|
@@ -12743,7 +12975,7 @@ const createSummaryCache = (cachePath, config) => {
|
|
|
12743
12975
|
if (resolutionEntry !== void 0) compactedResolutions[resolutionKey] = resolutionEntry;
|
|
12744
12976
|
}
|
|
12745
12977
|
const serialized = JSON.stringify({
|
|
12746
|
-
version:
|
|
12978
|
+
version: 3,
|
|
12747
12979
|
scopeHash,
|
|
12748
12980
|
fileList: store.fileList,
|
|
12749
12981
|
resolutions: {
|
|
@@ -1365,6 +1365,7 @@ const parseCssImports = (filePath) => {
|
|
|
1365
1365
|
memberAccesses: [],
|
|
1366
1366
|
wholeObjectUses: [],
|
|
1367
1367
|
localIdentifierReferences: [],
|
|
1368
|
+
topLevelImportReferences: [],
|
|
1368
1369
|
referencedFilenames: [],
|
|
1369
1370
|
redundantTypePatterns: [],
|
|
1370
1371
|
identityWrappers: [],
|
|
@@ -1393,18 +1394,142 @@ const collectLocalIdentifierReferences = (statements) => {
|
|
|
1393
1394
|
for (const value of Object.values(record)) if (Array.isArray(value)) for (const innerValue of value) visitNode(innerValue);
|
|
1394
1395
|
else if (value && typeof value === "object") visitNode(value);
|
|
1395
1396
|
};
|
|
1397
|
+
const visitExportedDeclarationValues = (declaration) => {
|
|
1398
|
+
if (!declaration || typeof declaration !== "object") return;
|
|
1399
|
+
const record = declaration;
|
|
1400
|
+
if (record.type === "VariableDeclaration" && Array.isArray(record.declarations)) {
|
|
1401
|
+
for (const declarator of record.declarations) if (declarator && typeof declarator === "object") visitNode(declarator.init);
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
if (record.type === "FunctionDeclaration" || record.type === "ClassDeclaration") {
|
|
1405
|
+
visitNode(record.params);
|
|
1406
|
+
visitNode(record.superClass);
|
|
1407
|
+
visitNode(record.body);
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
if (typeof record.type === "string" && !record.type.startsWith("TS")) visitNode(declaration);
|
|
1411
|
+
};
|
|
1396
1412
|
for (const statement of statements) {
|
|
1397
|
-
if (statement.type === "ImportDeclaration" || statement.type === "
|
|
1413
|
+
if (statement.type === "ImportDeclaration" || statement.type === "ExportAllDeclaration") continue;
|
|
1414
|
+
if (statement.type === "ExportNamedDeclaration") {
|
|
1415
|
+
visitExportedDeclarationValues(statement.declaration);
|
|
1416
|
+
continue;
|
|
1417
|
+
}
|
|
1418
|
+
if (statement.type === "ExportDefaultDeclaration") {
|
|
1419
|
+
visitExportedDeclarationValues(statement.declaration);
|
|
1420
|
+
continue;
|
|
1421
|
+
}
|
|
1398
1422
|
visitNode(statement);
|
|
1399
1423
|
}
|
|
1400
1424
|
return references;
|
|
1401
1425
|
};
|
|
1426
|
+
const TS_VALUE_WRAPPER_NODE_TYPES = new Set([
|
|
1427
|
+
"TSAsExpression",
|
|
1428
|
+
"TSSatisfiesExpression",
|
|
1429
|
+
"TSNonNullExpression",
|
|
1430
|
+
"TSInstantiationExpression",
|
|
1431
|
+
"TSTypeAssertion"
|
|
1432
|
+
]);
|
|
1433
|
+
const TS_RUNTIME_DECLARATION_NODE_TYPES = new Set([
|
|
1434
|
+
"TSEnumDeclaration",
|
|
1435
|
+
"TSModuleDeclaration",
|
|
1436
|
+
"TSExportAssignment"
|
|
1437
|
+
]);
|
|
1438
|
+
const FUNCTION_NODE_TYPES = new Set([
|
|
1439
|
+
"FunctionDeclaration",
|
|
1440
|
+
"FunctionExpression",
|
|
1441
|
+
"ArrowFunctionExpression"
|
|
1442
|
+
]);
|
|
1443
|
+
const collectStaticImportLocalNames = (imports) => {
|
|
1444
|
+
const localNames = /* @__PURE__ */ new Set();
|
|
1445
|
+
for (const importInfo of imports) {
|
|
1446
|
+
if (importInfo.isDynamic || importInfo.isTypeOnly) continue;
|
|
1447
|
+
for (const binding of importInfo.importedNames) {
|
|
1448
|
+
if (binding.isTypeOnly) continue;
|
|
1449
|
+
const localName = binding.alias ?? binding.name;
|
|
1450
|
+
if (localName && localName !== "*") localNames.add(localName);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
return localNames;
|
|
1454
|
+
};
|
|
1455
|
+
const collectTopLevelImportReferences = (bodyNodes, importLocalNames) => {
|
|
1456
|
+
const referencedNames = /* @__PURE__ */ new Set();
|
|
1457
|
+
if (importLocalNames.size === 0) return [];
|
|
1458
|
+
const visitClassBody = (classBody) => {
|
|
1459
|
+
const bodyElements = classBody.body ?? [];
|
|
1460
|
+
for (const element of bodyElements) {
|
|
1461
|
+
if (element.type === "StaticBlock") {
|
|
1462
|
+
visitValueNode(element.body);
|
|
1463
|
+
continue;
|
|
1464
|
+
}
|
|
1465
|
+
if (Boolean(element.computed)) visitValueNode(element.key);
|
|
1466
|
+
const isStatic = Boolean(element.static);
|
|
1467
|
+
if (element.type === "PropertyDefinition" && isStatic) visitValueNode(element.value);
|
|
1468
|
+
visitValueNode(element.decorators);
|
|
1469
|
+
}
|
|
1470
|
+
};
|
|
1471
|
+
const visitValueNode = (node) => {
|
|
1472
|
+
if (Array.isArray(node)) {
|
|
1473
|
+
for (const element of node) visitValueNode(element);
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
if (!isWalkableNode(node)) return;
|
|
1477
|
+
if (node.type === "Identifier" || node.type === "JSXIdentifier") {
|
|
1478
|
+
const identifierName = node.name;
|
|
1479
|
+
if (identifierName && importLocalNames.has(identifierName)) referencedNames.add(identifierName);
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
if (node.type.startsWith("TS")) {
|
|
1483
|
+
if (TS_VALUE_WRAPPER_NODE_TYPES.has(node.type)) {
|
|
1484
|
+
visitValueNode(node.expression);
|
|
1485
|
+
return;
|
|
1486
|
+
}
|
|
1487
|
+
if (!TS_RUNTIME_DECLARATION_NODE_TYPES.has(node.type)) return;
|
|
1488
|
+
}
|
|
1489
|
+
if (FUNCTION_NODE_TYPES.has(node.type)) return;
|
|
1490
|
+
if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
|
|
1491
|
+
visitValueNode(node.superClass);
|
|
1492
|
+
visitValueNode(node.decorators);
|
|
1493
|
+
const classBody = node.body;
|
|
1494
|
+
if (classBody) visitClassBody(classBody);
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
if (node.type === "CallExpression" || node.type === "NewExpression") {
|
|
1498
|
+
const callee = node.callee;
|
|
1499
|
+
if (callee && FUNCTION_NODE_TYPES.has(callee.type)) visitValueNode(callee.body);
|
|
1500
|
+
}
|
|
1501
|
+
if (node.type === "MemberExpression" || node.type === "JSXMemberExpression") {
|
|
1502
|
+
const memberNode = node;
|
|
1503
|
+
visitValueNode(memberNode.object);
|
|
1504
|
+
if (node.computed) visitValueNode(memberNode.property);
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
if (node.type === "Property") {
|
|
1508
|
+
const propertyNode = node;
|
|
1509
|
+
if (node.computed) visitValueNode(propertyNode.key);
|
|
1510
|
+
visitValueNode(propertyNode.value);
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) for (const element of value) visitValueNode(element);
|
|
1514
|
+
else if (value && typeof value === "object") visitValueNode(value);
|
|
1515
|
+
};
|
|
1516
|
+
for (const statement of bodyNodes) {
|
|
1517
|
+
if (statement.type === "ImportDeclaration" || statement.type === "ExportAllDeclaration") continue;
|
|
1518
|
+
if (statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration") {
|
|
1519
|
+
visitValueNode(statement.declaration);
|
|
1520
|
+
continue;
|
|
1521
|
+
}
|
|
1522
|
+
visitValueNode(statement);
|
|
1523
|
+
}
|
|
1524
|
+
return [...referencedNames];
|
|
1525
|
+
};
|
|
1402
1526
|
const createEmptyParsedSource = () => ({
|
|
1403
1527
|
imports: [],
|
|
1404
1528
|
exports: [],
|
|
1405
1529
|
memberAccesses: [],
|
|
1406
1530
|
wholeObjectUses: [],
|
|
1407
1531
|
localIdentifierReferences: [],
|
|
1532
|
+
topLevelImportReferences: [],
|
|
1408
1533
|
referencedFilenames: [],
|
|
1409
1534
|
redundantTypePatterns: [],
|
|
1410
1535
|
identityWrappers: [],
|
|
@@ -1616,6 +1741,7 @@ const parseSourceFile = (filePath) => {
|
|
|
1616
1741
|
collectMemberAccesses(program.body, namespaceLocalNames, memberAccesses, wholeObjectUses);
|
|
1617
1742
|
}, void 0);
|
|
1618
1743
|
const localIdentifierReferences = safeWalk("collectLocalIdentifierReferences", () => collectLocalIdentifierReferences(program.body), []);
|
|
1744
|
+
const topLevelImportReferences = safeWalk("collectTopLevelImportReferences", () => collectTopLevelImportReferences(program.body, collectStaticImportLocalNames(imports)), []);
|
|
1619
1745
|
const redundantTypePatterns = [];
|
|
1620
1746
|
const identityWrappers = [];
|
|
1621
1747
|
const typeDefinitionHashes = [];
|
|
@@ -1660,6 +1786,7 @@ const parseSourceFile = (filePath) => {
|
|
|
1660
1786
|
memberAccesses,
|
|
1661
1787
|
wholeObjectUses,
|
|
1662
1788
|
localIdentifierReferences,
|
|
1789
|
+
topLevelImportReferences,
|
|
1663
1790
|
referencedFilenames: extractReferencedFilenames(sourceText),
|
|
1664
1791
|
redundantTypePatterns,
|
|
1665
1792
|
identityWrappers,
|
|
@@ -1800,6 +1927,29 @@ const collectMemberAccesses = (bodyNodes, namespaceLocalNames, memberAccesses, w
|
|
|
1800
1927
|
const spreadArgument = node.argument;
|
|
1801
1928
|
if (spreadArgument?.type === "Identifier" && namespaceLocalNames.has(spreadArgument.name)) wholeObjectUses.push(spreadArgument.name);
|
|
1802
1929
|
}
|
|
1930
|
+
if (node.type === "VariableDeclarator") {
|
|
1931
|
+
const declarator = node;
|
|
1932
|
+
if (declarator.init?.type === "Identifier" && namespaceLocalNames.has(declarator.init.name) && declarator.id?.type === "ObjectPattern") {
|
|
1933
|
+
const namespaceName = declarator.init.name;
|
|
1934
|
+
const patternProperties = declarator.id.properties;
|
|
1935
|
+
for (const property of patternProperties) {
|
|
1936
|
+
if (property.type === "RestElement") {
|
|
1937
|
+
wholeObjectUses.push(namespaceName);
|
|
1938
|
+
continue;
|
|
1939
|
+
}
|
|
1940
|
+
const propertyKey = property.key;
|
|
1941
|
+
if (Boolean(property.computed)) wholeObjectUses.push(namespaceName);
|
|
1942
|
+
else if (propertyKey?.type === "Identifier" && propertyKey.name) memberAccesses.push({
|
|
1943
|
+
objectName: namespaceName,
|
|
1944
|
+
memberName: propertyKey.name
|
|
1945
|
+
});
|
|
1946
|
+
else if (propertyKey?.type === "Literal" && typeof propertyKey.value === "string") memberAccesses.push({
|
|
1947
|
+
objectName: namespaceName,
|
|
1948
|
+
memberName: propertyKey.value
|
|
1949
|
+
});
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1803
1953
|
if (node.type === "ForInStatement") {
|
|
1804
1954
|
const forInRight = node.right;
|
|
1805
1955
|
if (forInRight?.type === "Identifier" && namespaceLocalNames.has(forInRight.name)) wholeObjectUses.push(forInRight.name);
|
package/dist/parse-worker.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as parseSourceFile } from "./parse-
|
|
1
|
+
import { n as parseSourceFile } from "./parse-CDdo_Ppt.mjs";
|
|
2
2
|
import { parentPort } from "node:worker_threads";
|
|
3
3
|
|
|
4
4
|
//#region src/collect/parse-worker.ts
|
|
@@ -16,6 +16,7 @@ port.on("message", (message) => {
|
|
|
16
16
|
memberAccesses: parsed.memberAccesses,
|
|
17
17
|
wholeObjectUses: parsed.wholeObjectUses,
|
|
18
18
|
localIdentifierReferences: parsed.localIdentifierReferences,
|
|
19
|
+
topLevelImportReferences: parsed.topLevelImportReferences,
|
|
19
20
|
referencedFilenames: parsed.referencedFilenames,
|
|
20
21
|
redundantTypePatterns: parsed.redundantTypePatterns,
|
|
21
22
|
identityWrappers: parsed.identityWrappers,
|