190 lines
4.9 KiB
Plaintext
190 lines
4.9 KiB
Plaintext
// cell imports [<file>] - Trace module-level imports
|
|
//
|
|
// Usage:
|
|
// cell imports Trace imports for current package entry
|
|
// cell imports <file.ce> Trace imports starting from a .ce or .cm file
|
|
// cell imports <file.cm> Trace imports starting from a .cm file
|
|
//
|
|
// Options:
|
|
// --flat Flat list instead of tree
|
|
// --packages Only show unique packages, not individual modules
|
|
|
|
var shop = use('internal/shop')
|
|
var pkg = use('package')
|
|
var fd = use('fd')
|
|
|
|
var target = null
|
|
var flat_mode = false
|
|
var packages_only = false
|
|
var i = 0
|
|
var pkg_dir = null
|
|
var config = null
|
|
var target_path = null
|
|
|
|
for (i = 0; i < length(args); i++) {
|
|
if (args[i] == '--flat') {
|
|
flat_mode = true
|
|
} else if (args[i] == '--packages') {
|
|
packages_only = true
|
|
} else if (args[i] == '--help' || args[i] == '-h') {
|
|
log.console("Usage: cell imports [<file>] [options]")
|
|
log.console("")
|
|
log.console("Trace module-level imports across packages.")
|
|
log.console("")
|
|
log.console("Options:")
|
|
log.console(" --flat Flat list instead of tree")
|
|
log.console(" --packages Only show unique packages, not individual modules")
|
|
$stop()
|
|
} else if (!starts_with(args[i], '-')) {
|
|
target = args[i]
|
|
}
|
|
}
|
|
|
|
// Resolve target file
|
|
if (target) {
|
|
if (!ends_with(target, '.ce') && !ends_with(target, '.cm'))
|
|
target = target + '.ce'
|
|
if (fd.is_file(target))
|
|
target_path = fd.realpath(target)
|
|
else {
|
|
pkg_dir = pkg.find_package_dir('.')
|
|
if (pkg_dir)
|
|
target_path = pkg_dir + '/' + target
|
|
}
|
|
} else {
|
|
pkg_dir = pkg.find_package_dir('.')
|
|
if (pkg_dir) {
|
|
config = pkg.load_config(null)
|
|
if (config.entry)
|
|
target_path = pkg_dir + '/' + config.entry
|
|
}
|
|
}
|
|
|
|
if (!target_path || !fd.is_file(target_path)) {
|
|
log.error('Could not find file: ' + (target || '(no target specified)'))
|
|
$stop()
|
|
}
|
|
|
|
// Collect all imports recursively
|
|
var visited = {}
|
|
var all_imports = []
|
|
var all_packages = {}
|
|
|
|
function trace_imports(file_path, depth) {
|
|
if (visited[file_path]) return
|
|
visited[file_path] = true
|
|
|
|
var fi = shop.file_info(file_path)
|
|
var file_pkg = fi.package || '(local)'
|
|
var idx = null
|
|
var j = 0
|
|
var imp = null
|
|
var mod_path = null
|
|
var resolved = null
|
|
var imp_pkg = null
|
|
var imp_type = null
|
|
var rinfo = null
|
|
|
|
all_packages[file_pkg] = true
|
|
|
|
var _trace = function() {
|
|
idx = shop.index_file(file_path)
|
|
if (!idx || !idx.imports) return
|
|
|
|
j = 0
|
|
while (j < length(idx.imports)) {
|
|
imp = idx.imports[j]
|
|
mod_path = imp.module_path
|
|
resolved = null
|
|
imp_pkg = '?'
|
|
imp_type = 'unresolved'
|
|
|
|
// Use the full resolver that checks .cm files, C symbols, and aliases
|
|
rinfo = shop.resolve_import_info(mod_path, file_pkg)
|
|
if (rinfo) {
|
|
resolved = rinfo.resolved_path
|
|
imp_pkg = rinfo.package || '?'
|
|
imp_type = rinfo.type
|
|
}
|
|
|
|
all_packages[imp_pkg] = true
|
|
|
|
all_imports[] = {
|
|
from: file_path,
|
|
from_pkg: file_pkg,
|
|
module_path: mod_path,
|
|
resolved_path: resolved,
|
|
package: imp_pkg,
|
|
type: imp_type,
|
|
depth: depth
|
|
}
|
|
|
|
// Recurse into resolved scripts
|
|
if (resolved && (ends_with(resolved, '.cm') || ends_with(resolved, '.ce'))) {
|
|
trace_imports(resolved, depth + 1)
|
|
}
|
|
j = j + 1
|
|
}
|
|
} disruption {
|
|
// File might fail to parse/index
|
|
}
|
|
_trace()
|
|
}
|
|
|
|
trace_imports(target_path, 0)
|
|
|
|
// Output results
|
|
var fi2 = null
|
|
if (packages_only) {
|
|
log.console("Packages used by " + target_path + ":")
|
|
log.console("")
|
|
arrfor(array(all_packages), function(p) {
|
|
log.console(" " + p)
|
|
})
|
|
} else if (flat_mode) {
|
|
log.console("Imports from " + target_path + ":")
|
|
log.console("")
|
|
arrfor(all_imports, function(imp) {
|
|
var suffix = ''
|
|
if (imp.type == 'native') suffix = ' [native]'
|
|
if (imp.type == 'unresolved') suffix = ' [unresolved]'
|
|
log.console(" " + imp.module_path + " -> " + imp.package + suffix)
|
|
})
|
|
} else {
|
|
// Tree output
|
|
function print_tree(file_path, prefix, is_last) {
|
|
var children = filter(all_imports, function(imp) {
|
|
return imp.from == file_path
|
|
})
|
|
|
|
var j = 0
|
|
var imp = null
|
|
var last = false
|
|
var connector = null
|
|
var suffix = null
|
|
var child_prefix = null
|
|
while (j < length(children)) {
|
|
imp = children[j]
|
|
last = (j == length(children) - 1)
|
|
connector = last ? "\\-- " : "|-- "
|
|
suffix = " (" + imp.package + ")"
|
|
if (imp.type == 'native') suffix = suffix + " [native]"
|
|
if (imp.type == 'unresolved') suffix = suffix + " [unresolved]"
|
|
|
|
log.console(prefix + connector + imp.module_path + suffix)
|
|
|
|
if (imp.resolved_path) {
|
|
child_prefix = prefix + (last ? " " : "| ")
|
|
print_tree(imp.resolved_path, child_prefix, last)
|
|
}
|
|
j = j + 1
|
|
}
|
|
}
|
|
|
|
fi2 = shop.file_info(target_path)
|
|
log.console(target_path + " (" + (fi2.package || 'local') + ")")
|
|
print_tree(target_path, "", true)
|
|
}
|
|
|
|
$stop()
|