@pharaoh-so/local-analyzer 0.1.0 → 0.1.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/dist/analyzer.mjs +347 -74
- package/dist/bin/darwin-arm64/capture +0 -0
- package/package.json +5 -1
package/dist/analyzer.mjs
CHANGED
|
@@ -27904,7 +27904,7 @@ function extractExportStatement(node2, source, functions, classes, imports, expo
|
|
|
27904
27904
|
function extractImport(node2, imports) {
|
|
27905
27905
|
let sourceNode = node2.childForFieldName("source");
|
|
27906
27906
|
if (!sourceNode) return;
|
|
27907
|
-
let source = sourceNode.text.replace(/['"]/g, ""), symbols2 = [], isDefault = !1, isNamespace = !1, aliases = [],
|
|
27907
|
+
let source = sourceNode.text.replace(/['"]/g, ""), symbols2 = [], isDefault = !1, isNamespace = !1, aliases = [], isTypeOnly2 = node2.children.some((c) => c.type === "type");
|
|
27908
27908
|
for (let child of node2.children)
|
|
27909
27909
|
if (child.type === "import_clause") {
|
|
27910
27910
|
for (let clauseChild of child.children)
|
|
@@ -27933,7 +27933,7 @@ function extractImport(node2, imports) {
|
|
|
27933
27933
|
isDefault,
|
|
27934
27934
|
isNamespace,
|
|
27935
27935
|
line: node2.startPosition.row + 1,
|
|
27936
|
-
...
|
|
27936
|
+
...isTypeOnly2 ? { isTypeOnly: isTypeOnly2 } : {},
|
|
27937
27937
|
...aliases.length > 0 ? { aliases } : {}
|
|
27938
27938
|
});
|
|
27939
27939
|
}
|
|
@@ -28080,20 +28080,29 @@ function readDynamicImportCandidates(rootNode) {
|
|
|
28080
28080
|
importPath,
|
|
28081
28081
|
rootRelative: wrapper?.rootRelative ?? !1,
|
|
28082
28082
|
line: importCallNode.startPosition.row + 1,
|
|
28083
|
-
extracted
|
|
28083
|
+
extracted,
|
|
28084
|
+
...extracted.names.length > 0 && moduleScopeBinding(importCallNode) && { moduleScope: !0 }
|
|
28084
28085
|
});
|
|
28085
28086
|
}
|
|
28086
28087
|
return candidates;
|
|
28087
28088
|
}
|
|
28089
|
+
function moduleScopeBinding(call) {
|
|
28090
|
+
let expression = call.parent, awaited = expression?.type === "array" ? expression.parent?.parent?.parent : expression;
|
|
28091
|
+
if (awaited?.type !== "await_expression" || awaited.parent?.type !== "variable_declarator")
|
|
28092
|
+
return !1;
|
|
28093
|
+
let scope = awaited.parent.parent?.parent;
|
|
28094
|
+
return scope?.type === "program" || scope?.type === "export_statement" && scope.parent?.type === "program";
|
|
28095
|
+
}
|
|
28088
28096
|
function bindDynamicImportCandidates(candidates, filePath, resolveSpecifier2) {
|
|
28089
28097
|
let sites = [];
|
|
28090
|
-
for (let { importPath, rootRelative, line, extracted } of candidates) {
|
|
28098
|
+
for (let { importPath, rootRelative, line, extracted, moduleScope } of candidates) {
|
|
28091
28099
|
let extensionPath = rootRelative && importPath ? extensionRootPath(importPath) : null, specifier = rootRelative ? extensionPath ? resolveSpecifier2(extensionPath, filePath, "extension-root") : void 0 : importPath && !importPath.startsWith(".") ? resolveSpecifier2(importPath, filePath) : void 0;
|
|
28092
28100
|
specifier?.external || sites.push({
|
|
28093
28101
|
importPath,
|
|
28094
28102
|
resolvedTarget: importPath ? rootRelative ? specifier?.target ?? null : specifier ? specifier.target ?? null : resolveRelativeImport(filePath, importPath) : null,
|
|
28095
28103
|
line,
|
|
28096
|
-
extracted
|
|
28104
|
+
extracted,
|
|
28105
|
+
...moduleScope && { moduleScope }
|
|
28097
28106
|
});
|
|
28098
28107
|
}
|
|
28099
28108
|
return sites;
|
|
@@ -28176,7 +28185,7 @@ function resolveDynamicImportSites(sites, filePath, parsedFiles) {
|
|
|
28176
28185
|
importLine: site.line
|
|
28177
28186
|
});
|
|
28178
28187
|
}
|
|
28179
|
-
extracted.namespaceId && (symbols2.set(extracted.namespaceId, targetFile), extracted.namespaceMethods.length > 0 && imports.push({
|
|
28188
|
+
extracted.namespaceId && (symbols2.set(extracted.namespaceId, targetFile), renames.set(extracted.namespaceId, "*"), extracted.namespaceMethods.length > 0 && imports.push({
|
|
28180
28189
|
fromFile: filePath,
|
|
28181
28190
|
toFile: targetFile,
|
|
28182
28191
|
symbols: extracted.namespaceMethods,
|
|
@@ -28476,6 +28485,11 @@ var ExportRegistry = class {
|
|
|
28476
28485
|
let entry = this.files.get(filePath);
|
|
28477
28486
|
entry && returnTypes.size > 0 && (entry.returnTypes = returnTypes);
|
|
28478
28487
|
}
|
|
28488
|
+
/** Retain a file's explicit export bindings after releasing its syntax tree. */
|
|
28489
|
+
addNamedReExports(filePath, exports) {
|
|
28490
|
+
let entry = this.files.get(filePath);
|
|
28491
|
+
entry && (entry.namedReExports = exports);
|
|
28492
|
+
}
|
|
28479
28493
|
/**
|
|
28480
28494
|
* Get the set of all file paths stored in the registry across all chunks.
|
|
28481
28495
|
*
|
|
@@ -28586,7 +28600,7 @@ var ExportRegistry = class {
|
|
|
28586
28600
|
importLine: item.importLine
|
|
28587
28601
|
});
|
|
28588
28602
|
}
|
|
28589
|
-
item.namespaceId && (entry.symbols.has(item.namespaceId) || entry.symbols.set(item.namespaceId, targetFile), item.namespaceMethods.length > 0 && entry.imports.push({
|
|
28603
|
+
item.namespaceId && (entry.symbols.has(item.namespaceId) || (entry.symbols.set(item.namespaceId, targetFile), entry.renames.set(item.namespaceId, "*")), item.namespaceMethods.length > 0 && entry.imports.push({
|
|
28590
28604
|
fromFile: filePath,
|
|
28591
28605
|
toFile: targetFile,
|
|
28592
28606
|
symbols: item.namespaceMethods,
|
|
@@ -28775,6 +28789,237 @@ function starExportTargets(fileImports) {
|
|
|
28775
28789
|
return targets;
|
|
28776
28790
|
}
|
|
28777
28791
|
|
|
28792
|
+
// src/resolver/re-exports.ts
|
|
28793
|
+
function isTypeOnly(node2) {
|
|
28794
|
+
return node2.children.some(
|
|
28795
|
+
(child) => child.type === "type" || child.type === "ERROR" && child.text === "type"
|
|
28796
|
+
);
|
|
28797
|
+
}
|
|
28798
|
+
function moduleSpecifier(node2) {
|
|
28799
|
+
return node2.childForFieldName("source")?.text.slice(1, -1);
|
|
28800
|
+
}
|
|
28801
|
+
function nonCallableBinding(file, name = "*") {
|
|
28802
|
+
return { file, name, local: !0 };
|
|
28803
|
+
}
|
|
28804
|
+
function importedBindings(root2, file, names, resolveSpecifier2, dynamicSites, knownFiles) {
|
|
28805
|
+
let bindings = /* @__PURE__ */ new Map(), add = (local, binding2) => {
|
|
28806
|
+
names.has(local) && bindings.set(local, bindings.has(local) ? null : binding2);
|
|
28807
|
+
};
|
|
28808
|
+
for (let statement of root2.namedChildren) {
|
|
28809
|
+
if (statement.type !== "import_statement") continue;
|
|
28810
|
+
let source = moduleSpecifier(statement), clause = statement.namedChildren.find((child) => child.type === "import_clause");
|
|
28811
|
+
if (source === void 0 || !clause) continue;
|
|
28812
|
+
let typeOnly = isTypeOnly(statement), resolution, bind = (local, original, typeOnly2, namespace2 = !1) => {
|
|
28813
|
+
if (!names.has(local)) return;
|
|
28814
|
+
if (typeOnly2) {
|
|
28815
|
+
add(local, null);
|
|
28816
|
+
return;
|
|
28817
|
+
}
|
|
28818
|
+
resolution ??= resolveSpecifier2(source, file, void 0, statement.startPosition.row + 1);
|
|
28819
|
+
let target = resolution.target;
|
|
28820
|
+
add(
|
|
28821
|
+
local,
|
|
28822
|
+
target ? namespace2 ? nonCallableBinding(target) : { file: target, name: original } : nonCallableBinding(file, `*:${local}`)
|
|
28823
|
+
);
|
|
28824
|
+
};
|
|
28825
|
+
for (let child of clause.namedChildren) {
|
|
28826
|
+
if (child.type === "identifier" && bind(child.text, "default", typeOnly), child.type === "namespace_import") {
|
|
28827
|
+
let name = child.namedChildren.find((member) => member.type === "identifier")?.text;
|
|
28828
|
+
name && bind(name, "*", typeOnly, !0);
|
|
28829
|
+
}
|
|
28830
|
+
if (child.type === "named_imports")
|
|
28831
|
+
for (let specifier of child.namedChildren) {
|
|
28832
|
+
let name = specifier.childForFieldName("name")?.text, alias = specifier.childForFieldName("alias")?.text;
|
|
28833
|
+
name && bind(alias ?? name, name, typeOnly || isTypeOnly(specifier));
|
|
28834
|
+
}
|
|
28835
|
+
}
|
|
28836
|
+
}
|
|
28837
|
+
for (let site of dynamicSites) {
|
|
28838
|
+
if (!site.moduleScope || !site.extracted.names.some(({ local }) => names.has(local))) continue;
|
|
28839
|
+
let target = site.resolvedTarget && knownFiles && findParsedFilePath(knownFiles, site.resolvedTarget);
|
|
28840
|
+
for (let { local, original } of site.extracted.names)
|
|
28841
|
+
add(
|
|
28842
|
+
local,
|
|
28843
|
+
target ? { file: target, name: original } : nonCallableBinding(file, `*:${local}`)
|
|
28844
|
+
);
|
|
28845
|
+
}
|
|
28846
|
+
return bindings;
|
|
28847
|
+
}
|
|
28848
|
+
var CALLABLE_DECLARATIONS = /* @__PURE__ */ new Set([
|
|
28849
|
+
"function_declaration",
|
|
28850
|
+
"generator_function_declaration",
|
|
28851
|
+
"class_declaration",
|
|
28852
|
+
"abstract_class_declaration"
|
|
28853
|
+
]), CALLABLE_EXPRESSIONS = /* @__PURE__ */ new Set([
|
|
28854
|
+
"arrow_function",
|
|
28855
|
+
"function_expression",
|
|
28856
|
+
"generator_function",
|
|
28857
|
+
"class"
|
|
28858
|
+
]);
|
|
28859
|
+
function recordPattern(node2, record2) {
|
|
28860
|
+
if (node2.type === "identifier" || node2.type === "shorthand_property_identifier_pattern") {
|
|
28861
|
+
record2(node2.text);
|
|
28862
|
+
return;
|
|
28863
|
+
}
|
|
28864
|
+
if (node2.type === "pair_pattern" || node2.type === "assignment_pattern" || node2.type === "object_assignment_pattern") {
|
|
28865
|
+
let value = node2.childForFieldName(node2.type === "pair_pattern" ? "value" : "left");
|
|
28866
|
+
value && recordPattern(value, record2);
|
|
28867
|
+
return;
|
|
28868
|
+
}
|
|
28869
|
+
for (let child of node2.namedChildren) recordPattern(child, record2);
|
|
28870
|
+
}
|
|
28871
|
+
function recordDeclaration(node2, record2) {
|
|
28872
|
+
if (node2.type === "lexical_declaration" || node2.type === "variable_declaration") {
|
|
28873
|
+
for (let declarator of node2.namedChildren) {
|
|
28874
|
+
if (declarator.type !== "variable_declarator") continue;
|
|
28875
|
+
let pattern = declarator.childForFieldName("name"), value = declarator.childForFieldName("value");
|
|
28876
|
+
pattern && recordPattern(pattern, (name2) => record2(name2, CALLABLE_EXPRESSIONS.has(value?.type ?? "")));
|
|
28877
|
+
}
|
|
28878
|
+
return;
|
|
28879
|
+
}
|
|
28880
|
+
let callable = CALLABLE_DECLARATIONS.has(node2.type);
|
|
28881
|
+
if (!callable && node2.type !== "enum_declaration" && node2.type !== "internal_module") return;
|
|
28882
|
+
let name = node2.childForFieldName("name");
|
|
28883
|
+
name && record2(name.text, callable);
|
|
28884
|
+
}
|
|
28885
|
+
function commonJsAssignment(statement) {
|
|
28886
|
+
if (statement.type !== "expression_statement") return !1;
|
|
28887
|
+
let expression = statement.namedChildren[0];
|
|
28888
|
+
if (expression?.type !== "assignment_expression") return !1;
|
|
28889
|
+
let left = expression.childForFieldName("left");
|
|
28890
|
+
return !!left && /^(?:module\.exports|exports)(?:\.|\[|$)/.test(left.text);
|
|
28891
|
+
}
|
|
28892
|
+
function readNamedReExports(root2, file, resolveSpecifier2, dynamicSites = [], parsedExports = [], knownFiles) {
|
|
28893
|
+
let named = /* @__PURE__ */ new Map(), stars = /* @__PURE__ */ new Set(), localValues = /* @__PURE__ */ new Set(), callable = /* @__PURE__ */ new Set(), types2 = /* @__PURE__ */ new Set(), localExports = [], commonJs = !1, hasExportStatement = !1, local = (name) => ({ file, name, local: !0, topLevel: !0 }), recordLocal = (name, isCallable) => {
|
|
28894
|
+
localValues.add(name), isCallable && callable.add(name);
|
|
28895
|
+
}, addNamed = (name, binding2) => named.set(name, named.has(name) ? null : binding2);
|
|
28896
|
+
for (let statement of root2.namedChildren) {
|
|
28897
|
+
if (statement.type !== "export_statement") {
|
|
28898
|
+
recordDeclaration(statement, recordLocal), commonJs || (commonJs = commonJsAssignment(statement));
|
|
28899
|
+
continue;
|
|
28900
|
+
}
|
|
28901
|
+
hasExportStatement = !0;
|
|
28902
|
+
let source = moduleSpecifier(statement), typeOnly = isTypeOnly(statement), clause = statement.namedChildren.find((child) => child.type === "export_clause");
|
|
28903
|
+
if (clause) {
|
|
28904
|
+
let target = source !== void 0 && !typeOnly ? resolveSpecifier2(source, file, void 0, statement.startPosition.row + 1).target : void 0;
|
|
28905
|
+
for (let specifier of clause.namedChildren) {
|
|
28906
|
+
let original = specifier.childForFieldName("name")?.text;
|
|
28907
|
+
if (!original) continue;
|
|
28908
|
+
let name = specifier.childForFieldName("alias")?.text ?? original;
|
|
28909
|
+
typeOnly || isTypeOnly(specifier) ? types2.add(name) : source === void 0 ? localExports.push({ name, original }) : addNamed(
|
|
28910
|
+
name,
|
|
28911
|
+
target ? { file: target, name: original } : nonCallableBinding(file, `*:${name}`)
|
|
28912
|
+
);
|
|
28913
|
+
}
|
|
28914
|
+
continue;
|
|
28915
|
+
}
|
|
28916
|
+
if (typeOnly) continue;
|
|
28917
|
+
if (source !== void 0) {
|
|
28918
|
+
if (statement.children.some((child) => child.type === "*")) {
|
|
28919
|
+
let target = resolveSpecifier2(
|
|
28920
|
+
source,
|
|
28921
|
+
file,
|
|
28922
|
+
void 0,
|
|
28923
|
+
statement.startPosition.row + 1
|
|
28924
|
+
).target;
|
|
28925
|
+
target && stars.add(target);
|
|
28926
|
+
} else {
|
|
28927
|
+
let name = statement.namedChildren.find(
|
|
28928
|
+
(child) => child.type === "namespace_export"
|
|
28929
|
+
)?.namedChildren[0]?.text;
|
|
28930
|
+
if (name) {
|
|
28931
|
+
let target = resolveSpecifier2(
|
|
28932
|
+
source,
|
|
28933
|
+
file,
|
|
28934
|
+
void 0,
|
|
28935
|
+
statement.startPosition.row + 1
|
|
28936
|
+
).target;
|
|
28937
|
+
addNamed(
|
|
28938
|
+
name,
|
|
28939
|
+
target ? nonCallableBinding(target) : nonCallableBinding(file, `*:${name}`)
|
|
28940
|
+
);
|
|
28941
|
+
}
|
|
28942
|
+
}
|
|
28943
|
+
continue;
|
|
28944
|
+
}
|
|
28945
|
+
let isDefault = statement.children.some((child) => child.type === "default"), declaration2 = statement.childForFieldName("declaration"), value = statement.childForFieldName("value");
|
|
28946
|
+
if (declaration2)
|
|
28947
|
+
recordDeclaration(declaration2, (name, isCallable) => {
|
|
28948
|
+
recordLocal(name, isCallable), addNamed(isDefault ? "default" : name, local(name));
|
|
28949
|
+
});
|
|
28950
|
+
else if (isDefault && value?.type === "identifier")
|
|
28951
|
+
localExports.push({ name: "default", original: value.text });
|
|
28952
|
+
else if (isDefault) {
|
|
28953
|
+
let name = parsedExports.find((entry) => entry.isDefault)?.name ?? "default";
|
|
28954
|
+
recordLocal(name, CALLABLE_EXPRESSIONS.has(value?.type ?? "")), addNamed("default", local(name));
|
|
28955
|
+
}
|
|
28956
|
+
}
|
|
28957
|
+
if (localExports.length > 0) {
|
|
28958
|
+
let names = new Set(localExports.map(({ original }) => original)), imported = importedBindings(
|
|
28959
|
+
root2,
|
|
28960
|
+
file,
|
|
28961
|
+
names,
|
|
28962
|
+
resolveSpecifier2,
|
|
28963
|
+
dynamicSites,
|
|
28964
|
+
knownFiles
|
|
28965
|
+
);
|
|
28966
|
+
for (let { name, original } of localExports) {
|
|
28967
|
+
let binding2 = imported.get(original);
|
|
28968
|
+
addNamed(
|
|
28969
|
+
name,
|
|
28970
|
+
binding2 === void 0 ? localValues.has(original) ? local(original) : null : binding2
|
|
28971
|
+
);
|
|
28972
|
+
}
|
|
28973
|
+
}
|
|
28974
|
+
for (let name of types2) named.has(name) || named.set(name, null);
|
|
28975
|
+
return {
|
|
28976
|
+
named,
|
|
28977
|
+
stars: [...stars],
|
|
28978
|
+
callable,
|
|
28979
|
+
...commonJs && !hasExportStatement && { commonJs: !0 }
|
|
28980
|
+
};
|
|
28981
|
+
}
|
|
28982
|
+
var MAX_EXPORT_STATES = 4096;
|
|
28983
|
+
function createImportedSymbolResolver(imports, functions, reExports, defaultName, onExhausted) {
|
|
28984
|
+
return (startFile, startName) => {
|
|
28985
|
+
let start = reExports(startFile), binding2 = start?.named.get(startName);
|
|
28986
|
+
if (binding2 === null) return;
|
|
28987
|
+
if (binding2?.local)
|
|
28988
|
+
return start?.callable.has(binding2.name) && functions.get(startFile)?.has(binding2.name) ? { file: startFile, name: binding2.name, topLevel: !0 } : void 0;
|
|
28989
|
+
if (!binding2 && !start?.stars.length && functions.get(startFile)?.has(startName))
|
|
28990
|
+
return { file: startFile, name: startName };
|
|
28991
|
+
let queue2 = [{ file: startFile, name: startName }], visited = /* @__PURE__ */ new Map([[startFile, /* @__PURE__ */ new Set([startName])]]), enqueue = (file, name) => {
|
|
28992
|
+
let names = visited.get(file) ?? /* @__PURE__ */ new Set();
|
|
28993
|
+
return names.has(name) ? !0 : queue2.length >= MAX_EXPORT_STATES ? (onExhausted?.(startFile), !1) : (names.add(name), visited.set(file, names), queue2.push({ file, name }), !0);
|
|
28994
|
+
}, result2;
|
|
28995
|
+
for (let index = 0; index < queue2.length; index++) {
|
|
28996
|
+
let { file, name } = queue2[index], facts = reExports(file), explicit = facts?.named.get(name), declaration2;
|
|
28997
|
+
if (explicit !== null) {
|
|
28998
|
+
if (explicit?.local)
|
|
28999
|
+
declaration2 = { file: explicit.file, name: explicit.name, topLevel: !0 };
|
|
29000
|
+
else if (explicit) {
|
|
29001
|
+
if (!enqueue(explicit.file, explicit.name)) return;
|
|
29002
|
+
} else {
|
|
29003
|
+
let legacy = !facts || facts.commonJs || index === 0, actualName = name === "default" ? defaultName(file) ?? name : name;
|
|
29004
|
+
if (legacy && functions.get(file)?.has(actualName) && !facts?.stars.length)
|
|
29005
|
+
declaration2 = { file, name: actualName };
|
|
29006
|
+
else if (name !== "default") {
|
|
29007
|
+
let fileImports = imports.get(file), named = fileImports?.get(name), targets = facts && !facts.commonJs ? facts.stars : named ? [named] : starExportTargets(fileImports);
|
|
29008
|
+
for (let target of targets) if (!enqueue(target, name)) return;
|
|
29009
|
+
}
|
|
29010
|
+
}
|
|
29011
|
+
if (declaration2) {
|
|
29012
|
+
if (result2 && (result2.file !== declaration2.file || result2.name !== declaration2.name))
|
|
29013
|
+
return;
|
|
29014
|
+
result2 = declaration2;
|
|
29015
|
+
}
|
|
29016
|
+
}
|
|
29017
|
+
}
|
|
29018
|
+
if (!(!result2 || !functions.get(result2.file)?.has(result2.name)) && !(result2.topLevel && !reExports(result2.file)?.callable.has(result2.name)))
|
|
29019
|
+
return result2;
|
|
29020
|
+
};
|
|
29021
|
+
}
|
|
29022
|
+
|
|
28778
29023
|
// src/resolver/router-registration.ts
|
|
28779
29024
|
var ROUTER_PACKAGES = /* @__PURE__ */ new Set([
|
|
28780
29025
|
"express",
|
|
@@ -28899,6 +29144,7 @@ function resolveRegistryImports(registry, fileIndex, tsConfig, opts) {
|
|
|
28899
29144
|
stats.resolved++, resolved.push({
|
|
28900
29145
|
fromFile: filePath,
|
|
28901
29146
|
toFile: target,
|
|
29147
|
+
source: imp.source,
|
|
28902
29148
|
symbols: imp.symbols,
|
|
28903
29149
|
isTypeOnly: imp.isTypeOnly,
|
|
28904
29150
|
importLine: imp.line,
|
|
@@ -29280,7 +29526,7 @@ var tsParser2 = new Parser();
|
|
|
29280
29526
|
tsParser2.setLanguage(tsLanguage);
|
|
29281
29527
|
var tsxParser2 = new Parser();
|
|
29282
29528
|
tsxParser2.setLanguage(tsxLanguage);
|
|
29283
|
-
var pyParser2 = new Parser();
|
|
29529
|
+
var jsParser = tsxLanguage === tsxLanguage ? tsxParser2 : new Parser().setLanguage(tsxLanguage), pyParser2 = new Parser();
|
|
29284
29530
|
pyParser2.setLanguage(pyLanguage);
|
|
29285
29531
|
var BUILT_INS = /* @__PURE__ */ new Set([
|
|
29286
29532
|
"console",
|
|
@@ -29473,27 +29719,39 @@ function classifyCallContext(callNode) {
|
|
|
29473
29719
|
}
|
|
29474
29720
|
return "production";
|
|
29475
29721
|
}
|
|
29476
|
-
function
|
|
29477
|
-
|
|
29478
|
-
|
|
29479
|
-
|
|
29480
|
-
|
|
29481
|
-
|
|
29482
|
-
|
|
29483
|
-
|
|
29484
|
-
|
|
29485
|
-
|
|
29722
|
+
function resolvedFunctionUid(repoName, target, classNames) {
|
|
29723
|
+
return target ? buildFunctionUid(repoName, target.file, {
|
|
29724
|
+
name: target.name,
|
|
29725
|
+
className: target.topLevel ? void 0 : classNames.get(target.file)?.get(target.name)
|
|
29726
|
+
}) : void 0;
|
|
29727
|
+
}
|
|
29728
|
+
function namespaceBindings(imports) {
|
|
29729
|
+
let names = /* @__PURE__ */ new Set();
|
|
29730
|
+
for (let statement of imports) {
|
|
29731
|
+
if (!statement.isNamespace || statement.isTypeOnly) continue;
|
|
29732
|
+
let name = statement.symbols.at(-1);
|
|
29733
|
+
name && name !== "*" && names.add(name);
|
|
29486
29734
|
}
|
|
29487
|
-
return
|
|
29735
|
+
return names;
|
|
29488
29736
|
}
|
|
29489
|
-
function
|
|
29490
|
-
|
|
29491
|
-
|
|
29492
|
-
|
|
29493
|
-
|
|
29494
|
-
|
|
29495
|
-
|
|
29496
|
-
return file &&
|
|
29737
|
+
function isPythonModuleReceiver(file, binding2, functions) {
|
|
29738
|
+
return file.endsWith(".py") && pythonModuleName(file) === binding2 && !functions.get(file)?.has(binding2);
|
|
29739
|
+
}
|
|
29740
|
+
function functionReceiverMember(member) {
|
|
29741
|
+
return member === "call" || member === "apply" || member === "bind";
|
|
29742
|
+
}
|
|
29743
|
+
function pythonFactoryReceiverUid(repo, classes, file, name) {
|
|
29744
|
+
return file.endsWith(".py") && classes.byName.get(name)?.some((cls) => cls.file === file) ? buildFunctionUid(repo, file, { name }) : void 0;
|
|
29745
|
+
}
|
|
29746
|
+
function memberTarget(name, member, targetFile, importSymbolMap, aliases, resolveImported, instanceClasses, hasMember) {
|
|
29747
|
+
let instance = instanceClassOf(name, targetFile, importSymbolMap, instanceClasses), target;
|
|
29748
|
+
if (instance) {
|
|
29749
|
+
let [className2, file] = instance;
|
|
29750
|
+
if (hasMember(file, `${className2}.${member}`)) return { file, className: className2 };
|
|
29751
|
+
let imported = importSymbolMap.get(file)?.get(className2);
|
|
29752
|
+
imported && (target = resolveImported(imported, aliases.get(file)?.get(className2) ?? className2));
|
|
29753
|
+
} else target = resolveImported(targetFile, name);
|
|
29754
|
+
return target && hasMember(target.file, `${target.name}.${member}`) ? { file: target.file, className: target.name } : void 0;
|
|
29497
29755
|
}
|
|
29498
29756
|
function instanceClassOf(name, file, importSymbolMap, instanceClasses) {
|
|
29499
29757
|
let visited = /* @__PURE__ */ new Set(), current = file;
|
|
@@ -29956,7 +30214,15 @@ function traceCallChainsFromRegistry(registry, importSymbolMap, repoName, aliasM
|
|
|
29956
30214
|
let fnMap = fileFnClassNames.get(path5);
|
|
29957
30215
|
fnMap || (fnMap = /* @__PURE__ */ new Map(), fileFnClassNames.set(path5, fnMap)), fnMap.set(fn.name, fn.className);
|
|
29958
30216
|
}
|
|
29959
|
-
let effectiveAliasMap = aliasMap ?? /* @__PURE__ */ new Map(),
|
|
30217
|
+
let effectiveAliasMap = aliasMap ?? /* @__PURE__ */ new Map(), namespaceNames = new Map(
|
|
30218
|
+
[...registry.entries()].map(([file, entry]) => [file, namespaceBindings(entry.imports)])
|
|
30219
|
+
), exhausted = /* @__PURE__ */ new Set(), tracingFile, resolveImported = createImportedSymbolResolver(
|
|
30220
|
+
importSymbolMap,
|
|
30221
|
+
fileFunctionNames,
|
|
30222
|
+
(file) => registry.getFileEntry(file)?.namedReExports,
|
|
30223
|
+
(file) => registry.getFileEntry(file)?.defaultExportName,
|
|
30224
|
+
(file) => exhausted.add(tracingFile ?? file)
|
|
30225
|
+
), instanceClasses = /* @__PURE__ */ new Map();
|
|
29960
30226
|
for (let [path5, entry] of registry.entries())
|
|
29961
30227
|
entry.instanceClasses && instanceClasses.set(path5, new Map(Object.entries(entry.instanceClasses)));
|
|
29962
30228
|
let classMembers = /* @__PURE__ */ new Map();
|
|
@@ -29968,6 +30234,7 @@ function traceCallChainsFromRegistry(registry, importSymbolMap, repoName, aliasM
|
|
|
29968
30234
|
importSymbolMap,
|
|
29969
30235
|
aliasMap: effectiveAliasMap,
|
|
29970
30236
|
fileFunctionNames,
|
|
30237
|
+
resolveImported,
|
|
29971
30238
|
classes: buildClassIndex([...registry.entries()].map(([, entry]) => entry)),
|
|
29972
30239
|
hasMember: (file, classMember) => classMembers.get(file)?.has(classMember) ?? !1,
|
|
29973
30240
|
returnTypes: (file) => registry.getFileEntry(file)?.returnTypes,
|
|
@@ -29976,29 +30243,28 @@ function traceCallChainsFromRegistry(registry, importSymbolMap, repoName, aliasM
|
|
|
29976
30243
|
}, resolveReceiverCall = (call, filePath) => {
|
|
29977
30244
|
if (!call.receiver) return;
|
|
29978
30245
|
let receiverFile = importSymbolMap.get(filePath)?.get(call.receiver);
|
|
29979
|
-
if (receiverFile)
|
|
29980
|
-
|
|
29981
|
-
|
|
29982
|
-
|
|
29983
|
-
|
|
29984
|
-
|
|
29985
|
-
|
|
29986
|
-
instanceClasses,
|
|
29987
|
-
(f, key) => registry.getFileEntry(f)?.functions.some((fn) => `${fn.className}.${fn.name}` === key)
|
|
30246
|
+
if (!receiverFile) return;
|
|
30247
|
+
let alias = effectiveAliasMap.get(filePath)?.get(call.receiver);
|
|
30248
|
+
if (alias === "*" || namespaceNames.get(filePath)?.has(call.receiver) || isPythonModuleReceiver(receiverFile, alias ?? call.receiver, fileFunctionNames))
|
|
30249
|
+
return resolvedFunctionUid(
|
|
30250
|
+
repoName,
|
|
30251
|
+
resolveImported(receiverFile, call.calledName),
|
|
30252
|
+
fileFnClassNames
|
|
29988
30253
|
);
|
|
29989
|
-
|
|
29990
|
-
return buildFunctionUid(repoName, target.file, {
|
|
29991
|
-
name: call.calledName,
|
|
29992
|
-
className: target.className
|
|
29993
|
-
});
|
|
29994
|
-
}
|
|
29995
|
-
let names = receiverFile ? fileFunctionNames.get(receiverFile) : void 0;
|
|
29996
|
-
if (!receiverFile || !names) return;
|
|
29997
|
-
let name = names.has(call.calledName) ? call.calledName : names.has(call.receiver) ? call.receiver : void 0;
|
|
29998
|
-
return name ? buildFunctionUid(repoName, receiverFile, {
|
|
30254
|
+
let name = alias ?? call.receiver, target = memberTarget(
|
|
29999
30255
|
name,
|
|
30000
|
-
|
|
30001
|
-
|
|
30256
|
+
call.calledName,
|
|
30257
|
+
receiverFile,
|
|
30258
|
+
importSymbolMap,
|
|
30259
|
+
effectiveAliasMap,
|
|
30260
|
+
resolveImported,
|
|
30261
|
+
instanceClasses,
|
|
30262
|
+
(f, key) => classMembers.get(f)?.has(key)
|
|
30263
|
+
);
|
|
30264
|
+
return target ? buildFunctionUid(repoName, target.file, {
|
|
30265
|
+
name: call.calledName,
|
|
30266
|
+
className: target.className
|
|
30267
|
+
}) : pythonFactoryReceiverUid(repoName, typedContext.classes, receiverFile, name) ?? (functionReceiverMember(call.calledName) ? resolvedFunctionUid(repoName, resolveImported(receiverFile, name), fileFnClassNames) : void 0);
|
|
30002
30268
|
};
|
|
30003
30269
|
registry.resolvePendingDynamicImports();
|
|
30004
30270
|
let registryDynamicImports = [], perFileDynImportCounts = /* @__PURE__ */ new Map();
|
|
@@ -30043,15 +30309,11 @@ function traceCallChainsFromRegistry(registry, importSymbolMap, repoName, aliasM
|
|
|
30043
30309
|
}
|
|
30044
30310
|
let viaReceiver = resolveReceiverCall(call, filePath);
|
|
30045
30311
|
if (viaReceiver) return [viaReceiver];
|
|
30312
|
+
if (call.receiver && importSymbolMap.get(filePath)?.has(call.receiver)) return [];
|
|
30046
30313
|
let targetFile = !!call.receiver && isSelfReceiver(call.receiver) ? void 0 : importSymbolMap.get(filePath)?.get(calledName);
|
|
30047
30314
|
if (targetFile) {
|
|
30048
|
-
let originalName = effectiveAliasMap.get(filePath)?.get(calledName) ?? calledName,
|
|
30049
|
-
return
|
|
30050
|
-
buildFunctionUid(repoName, definingFile, {
|
|
30051
|
-
name: originalName,
|
|
30052
|
-
className: fileFnClassNames.get(definingFile)?.get(originalName)
|
|
30053
|
-
})
|
|
30054
|
-
] : [];
|
|
30315
|
+
let originalName = effectiveAliasMap.get(filePath)?.get(calledName) ?? calledName, target = resolveImported(targetFile, originalName), uid = resolvedFunctionUid(repoName, target, fileFnClassNames);
|
|
30316
|
+
return uid ? [uid] : [];
|
|
30055
30317
|
}
|
|
30056
30318
|
return calledName !== callerName && fileFunctionNames.get(filePath)?.has(calledName) ? [
|
|
30057
30319
|
buildFunctionUid(repoName, filePath, {
|
|
@@ -30073,8 +30335,10 @@ function traceCallChainsFromRegistry(registry, importSymbolMap, repoName, aliasM
|
|
|
30073
30335
|
});
|
|
30074
30336
|
callerName.startsWith("$module_init") && resolved.length > resolvedBefore && !topLevelCallerUids.includes(callerUid) && topLevelCallerUids.push(callerUid);
|
|
30075
30337
|
};
|
|
30076
|
-
for (let [filePath, entry] of registry.entries())
|
|
30338
|
+
for (let [filePath, entry] of registry.entries()) {
|
|
30339
|
+
tracingFile = filePath;
|
|
30077
30340
|
for (let fn of entry.functions) resolveCallsOf(fn.uid, fn.name, filePath, fn.calls);
|
|
30341
|
+
}
|
|
30078
30342
|
for (let [callerUid, calls] of registry.getAllCallSites()) {
|
|
30079
30343
|
let firstColon = callerUid.indexOf(":"), lastColon = callerUid.lastIndexOf(":");
|
|
30080
30344
|
if (firstColon < 0 || lastColon <= firstColon) continue;
|
|
@@ -30088,8 +30352,8 @@ function traceCallChainsFromRegistry(registry, importSymbolMap, repoName, aliasM
|
|
|
30088
30352
|
dynamicImports: registryDynamicImports,
|
|
30089
30353
|
topLevelCallerUids,
|
|
30090
30354
|
perFileDynImportCounts,
|
|
30091
|
-
untraced: []
|
|
30092
|
-
//
|
|
30355
|
+
untraced: [...exhausted]
|
|
30356
|
+
// the chunked pipeline adds files it could not parse or read
|
|
30093
30357
|
};
|
|
30094
30358
|
}
|
|
30095
30359
|
function referenceSites(node2, callerName, skip) {
|
|
@@ -30421,8 +30685,8 @@ function declaredClass(ctx, typeName, filePath, reachable) {
|
|
|
30421
30685
|
if (name = typeName.slice(dot + 1), !(module && pythonModuleName(module) === head && !ctx.fileFunctionNames.get(module)?.has(head)) || name.includes(".")) return;
|
|
30422
30686
|
typeFile = module;
|
|
30423
30687
|
}
|
|
30424
|
-
let
|
|
30425
|
-
return named.find((c) => c.file ===
|
|
30688
|
+
let target = typeFile === filePath ? { file: typeFile, name } : ctx.resolveImported(typeFile, name), named = (ctx.classes.byName.get(target?.name ?? name) ?? []).filter(reachable);
|
|
30689
|
+
return named.find((c) => c.file === target?.file) ?? (dot < 0 && named.length === 1 ? named[0] : void 0);
|
|
30426
30690
|
}
|
|
30427
30691
|
function methodOrder(ctx, cls, fromTest) {
|
|
30428
30692
|
let memo = fromTest ? ctx.methodOrders.test : ctx.methodOrders.production, reachable = (c) => fromTest || !c.test, ordering = /* @__PURE__ */ new Set(), external = (name) => {
|
|
@@ -30508,8 +30772,10 @@ function typedReceiverTargets(ctx, typeName, member, filePath, via = {}) {
|
|
|
30508
30772
|
return targets.map((c) => ({ file: c.file, className: c.name }));
|
|
30509
30773
|
}
|
|
30510
30774
|
function returnedClass(ctx, fn, awaited, filePath) {
|
|
30511
|
-
let name = ctx.aliasMap.get(filePath)?.get(fn) ?? fn, imported = ctx.importSymbolMap.get(filePath)?.get(fn),
|
|
30512
|
-
if (!
|
|
30775
|
+
let name = ctx.aliasMap.get(filePath)?.get(fn) ?? fn, imported = ctx.importSymbolMap.get(filePath)?.get(fn), target = imported ? ctx.resolveImported(imported, name) : { file: filePath, name };
|
|
30776
|
+
if (!target) return;
|
|
30777
|
+
let { file } = target, declared = ctx.returnTypes(file)?.get(target.name);
|
|
30778
|
+
if (!declared || declared.promised && !awaited) return;
|
|
30513
30779
|
let fromTest = isTestFile(file);
|
|
30514
30780
|
return declaredClass(ctx, declared.name, file, (c) => fromTest || !c.test) ? { name: declared.name, file } : void 0;
|
|
30515
30781
|
}
|
|
@@ -30839,28 +31105,35 @@ function queryLocalBlastRadius(graph, request) {
|
|
|
30839
31105
|
|
|
30840
31106
|
// src/analysis/local-analyzer.ts
|
|
30841
31107
|
function analyzeSavedCallers(input2, request, parser3) {
|
|
30842
|
-
let registry = new ExportRegistry(), files = [], dynamic = /* @__PURE__ */ new Map(), incomplete = input2.incomplete;
|
|
31108
|
+
let registry = new ExportRegistry(), files = [], dynamic = /* @__PURE__ */ new Map(), knownFiles = new Set(input2.sources.keys()), resolver = createCapturedTypeScriptResolver(knownFiles, input2.configFiles), incomplete = input2.incomplete;
|
|
30843
31109
|
for (let [filePath, bytes] of input2.sources)
|
|
30844
31110
|
try {
|
|
30845
|
-
let python = filePath.endsWith(".py"), parse2 = python ? parser3.parsePythonSource : parser3.parseTypeScriptSource, callFacts, pythonClasses, dynamicImports, parsed = parse2(bytes, filePath, (tree, file) => {
|
|
30846
|
-
tree.hasError && (incomplete = !0), callFacts = readRegistryCallFacts(tree, file, input2.repoName), python ? pythonClasses = readPythonClasses(tree) : dynamicImports =
|
|
31111
|
+
let python = filePath.endsWith(".py"), parse2 = python ? parser3.parsePythonSource : parser3.parseTypeScriptSource, callFacts, pythonClasses, dynamicImports, namedReExports, parsed = parse2(bytes, filePath, (tree, file) => {
|
|
31112
|
+
tree.hasError && (incomplete = !0), callFacts = readRegistryCallFacts(tree, file, input2.repoName), python ? pythonClasses = readPythonClasses(tree) : (dynamicImports = bindDynamicImportCandidates(
|
|
31113
|
+
readDynamicImportCandidates(tree),
|
|
31114
|
+
filePath,
|
|
31115
|
+
resolver.resolveSpecifier
|
|
31116
|
+
), namedReExports = readNamedReExports(
|
|
31117
|
+
tree,
|
|
31118
|
+
filePath,
|
|
31119
|
+
resolver.resolveSpecifier,
|
|
31120
|
+
dynamicImports,
|
|
31121
|
+
file.exports,
|
|
31122
|
+
knownFiles
|
|
31123
|
+
));
|
|
30847
31124
|
});
|
|
30848
31125
|
if (files.push(parsed), registry.addFromParsed([parsed], input2.repoName), callFacts) {
|
|
30849
31126
|
for (let [uid, sites] of callFacts.callSites)
|
|
30850
31127
|
registry.addCallSites(uid, parsed.path, sites);
|
|
30851
31128
|
registry.addReturnTypes(parsed.path, callFacts.returnTypes);
|
|
30852
31129
|
}
|
|
30853
|
-
pythonClasses && registry.addPythonClasses(parsed.path, pythonClasses), dynamicImports && dynamic.set(parsed.path, dynamicImports);
|
|
31130
|
+
pythonClasses && registry.addPythonClasses(parsed.path, pythonClasses), namedReExports && registry.addNamedReExports(parsed.path, namedReExports), dynamicImports && dynamic.set(parsed.path, dynamicImports);
|
|
30854
31131
|
} catch (error2) {
|
|
30855
31132
|
if (isWasmAbort(error2)) throw error2;
|
|
30856
31133
|
incomplete = !0;
|
|
30857
31134
|
}
|
|
30858
|
-
let
|
|
30859
|
-
|
|
30860
|
-
if (candidates.length === 0) continue;
|
|
30861
|
-
let sites = bindDynamicImportCandidates(candidates, filePath, resolver.resolveSpecifier);
|
|
30862
|
-
registry.addDynamicImports(filePath, resolveDynamicImportSites(sites, filePath, files));
|
|
30863
|
-
}
|
|
31135
|
+
for (let [filePath, sites] of dynamic)
|
|
31136
|
+
sites.length !== 0 && registry.addDynamicImports(filePath, resolveDynamicImportSites(sites, filePath, files));
|
|
30864
31137
|
let stats = {
|
|
30865
31138
|
resolvedCount: 0,
|
|
30866
31139
|
unresolvedCount: 0,
|
|
@@ -30895,7 +31168,7 @@ function analyzeSavedCallers(input2, request, parser3) {
|
|
|
30895
31168
|
functions: file.functions
|
|
30896
31169
|
})),
|
|
30897
31170
|
trace,
|
|
30898
|
-
incomplete: incomplete || unresolvedDynamic || stats.unresolvedCount > 0
|
|
31171
|
+
incomplete: incomplete || !!trace.untraced?.length || unresolvedDynamic || stats.unresolvedCount > 0
|
|
30899
31172
|
},
|
|
30900
31173
|
request
|
|
30901
31174
|
);
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pharaoh-so/local-analyzer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Pharaoh-so/pharaoh.git"
|
|
9
|
+
},
|
|
6
10
|
"engines": {
|
|
7
11
|
"node": ">=18"
|
|
8
12
|
},
|