better error print
This commit is contained in:
20
audit.ce
20
audit.ce
@@ -37,6 +37,7 @@ var total_ok = 0
|
||||
var total_errors = 0
|
||||
var total_scripts = 0
|
||||
var all_failures = []
|
||||
var all_unresolved = []
|
||||
|
||||
if (target_package) {
|
||||
packages = [target_package]
|
||||
@@ -57,6 +58,12 @@ arrfor(packages, function(p) {
|
||||
arrfor(result.errors, function(e) {
|
||||
push(all_failures, p + ": " + e)
|
||||
})
|
||||
|
||||
// Check use() resolution
|
||||
var resolution = shop.audit_use_resolution(p)
|
||||
arrfor(resolution.unresolved, function(u) {
|
||||
push(all_unresolved, p + '/' + u.script + ": use('" + u.module + "') cannot be resolved")
|
||||
})
|
||||
})
|
||||
|
||||
log.console("")
|
||||
@@ -68,7 +75,18 @@ if (length(all_failures) > 0) {
|
||||
log.console("")
|
||||
}
|
||||
|
||||
log.console("Audit complete: " + text(total_ok) + "/" + text(total_scripts) + " scripts compiled" + (total_errors > 0 ? ", " + text(total_errors) + " failed" : ""))
|
||||
if (length(all_unresolved) > 0) {
|
||||
log.console("Unresolved modules:")
|
||||
arrfor(all_unresolved, function(u) {
|
||||
log.console(" " + u)
|
||||
})
|
||||
log.console("")
|
||||
}
|
||||
|
||||
var summary = "Audit complete: " + text(total_ok) + "/" + text(total_scripts) + " scripts compiled"
|
||||
if (total_errors > 0) summary = summary + ", " + text(total_errors) + " failed"
|
||||
if (length(all_unresolved) > 0) summary = summary + ", " + text(length(all_unresolved)) + " unresolved use() calls"
|
||||
log.console(summary)
|
||||
}
|
||||
run()
|
||||
|
||||
|
||||
109
internal/shop.cm
109
internal/shop.cm
@@ -48,6 +48,9 @@ function hash_path(content, salt)
|
||||
|
||||
var Shop = {}
|
||||
|
||||
// Stack tracking the chain of use() calls for error reporting
|
||||
var use_stack = []
|
||||
|
||||
var SCOPE_LOCAL = 0
|
||||
var SCOPE_PACKAGE = 1
|
||||
var SCOPE_CORE = 2
|
||||
@@ -1301,6 +1304,8 @@ Shop.use = function use(path, package_context) {
|
||||
var info = resolve_module_info(path, package_context)
|
||||
var _ctx_dir2 = null
|
||||
var _alias2 = null
|
||||
var _use_entry = path + ' (package: ' + package_context + ')'
|
||||
var _chain = null
|
||||
if (!info) {
|
||||
log.shop(`Module '${path}' could not be found in package '${package_context}'`)
|
||||
_ctx_dir2 = package_context ? (starts_with(package_context, '/') ? package_context : get_packages_dir() + '/' + fd.safe_package_path(package_context)) : null
|
||||
@@ -1311,13 +1316,32 @@ Shop.use = function use(path, package_context) {
|
||||
_alias2 = pkg_tools.split_alias(package_context, path)
|
||||
if (_alias2 == null && search(path, '/') != null)
|
||||
log.shop(`Alias '${array(path, '/')[0]}' could not be resolved in package '${package_context}'`)
|
||||
if (length(use_stack) > 0) {
|
||||
_chain = 'use() chain:'
|
||||
arrfor(use_stack, function(frame) { _chain = _chain + '\n -> ' + frame })
|
||||
_chain = _chain + '\n -> ' + path + ' [NOT FOUND]'
|
||||
log.error(_chain)
|
||||
}
|
||||
disrupt
|
||||
}
|
||||
|
||||
if (use_cache[info.cache_key])
|
||||
return use_cache[info.cache_key]
|
||||
use_cache[info.cache_key] = execute_module(info)
|
||||
return use_cache[info.cache_key]
|
||||
|
||||
push(use_stack, _use_entry)
|
||||
var _use_result = null
|
||||
var _use_ok = false
|
||||
var _load = function() {
|
||||
_use_result = execute_module(info)
|
||||
_use_ok = true
|
||||
} disruption {
|
||||
pop(use_stack)
|
||||
disrupt
|
||||
}
|
||||
_load()
|
||||
pop(use_stack)
|
||||
use_cache[info.cache_key] = _use_result
|
||||
return _use_result
|
||||
}
|
||||
|
||||
// Resolve a use() module path to a filesystem path without compiling.
|
||||
@@ -1856,6 +1880,30 @@ function get_package_scripts(package)
|
||||
return scripts
|
||||
}
|
||||
|
||||
// Extract use() call arguments from source text.
|
||||
// Returns an array of literal string arguments found in use('...') calls.
|
||||
function extract_use_calls(source) {
|
||||
var uses = []
|
||||
var idx = 0
|
||||
var start = 0
|
||||
var end = 0
|
||||
var arg = null
|
||||
idx = search(source, "use(")
|
||||
while (idx != null) {
|
||||
start = idx + 5
|
||||
end = search(text(source, start), "'")
|
||||
if (end == null) end = search(text(source, start), '"')
|
||||
if (end != null) {
|
||||
arg = text(source, start, start + end)
|
||||
push(uses, arg)
|
||||
}
|
||||
idx = search(text(source, idx + 4), "use(")
|
||||
if (idx != null) idx = idx + (source.length - (source.length - idx))
|
||||
else break
|
||||
}
|
||||
return uses
|
||||
}
|
||||
|
||||
Shop.build_package_scripts = function(package)
|
||||
{
|
||||
// compiles all .ce and .cm files in a package
|
||||
@@ -1879,6 +1927,63 @@ Shop.build_package_scripts = function(package)
|
||||
return {ok: ok, errors: errors, total: length(scripts)}
|
||||
}
|
||||
|
||||
// Check if all use() calls in a package's scripts can be resolved.
|
||||
// Returns {ok, unresolved: [{script, module}], total}
|
||||
Shop.audit_use_resolution = function(package) {
|
||||
var scripts = get_package_scripts(package)
|
||||
var pkg_dir = starts_with(package, '/') ? package : get_package_abs_dir(package)
|
||||
var unresolved = []
|
||||
var checked = 0
|
||||
var src = null
|
||||
var content = null
|
||||
var uses = null
|
||||
var info = null
|
||||
|
||||
arrfor(scripts, function(script) {
|
||||
var _check = function() {
|
||||
src = pkg_dir + '/' + script
|
||||
if (!fd.is_file(src)) return
|
||||
content = text(fd.slurp(src))
|
||||
if (!content || length(content) == 0) return
|
||||
|
||||
// Simple regex-free extraction: find use(' and use(" patterns
|
||||
uses = []
|
||||
var pos = 0
|
||||
var rest = content
|
||||
var ui = null
|
||||
var quote = null
|
||||
var end = null
|
||||
var arg = null
|
||||
while (length(rest) > 0) {
|
||||
ui = search(rest, "use(")
|
||||
if (ui == null) break
|
||||
rest = text(rest, ui + 4)
|
||||
if (length(rest) == 0) break
|
||||
quote = text(rest, 0, 1)
|
||||
if (quote != "'" && quote != '"') continue
|
||||
rest = text(rest, 1)
|
||||
end = search(rest, quote)
|
||||
if (end == null) continue
|
||||
arg = text(rest, 0, end)
|
||||
if (length(arg) > 0) push(uses, arg)
|
||||
rest = text(rest, end + 1)
|
||||
}
|
||||
|
||||
arrfor(uses, function(mod) {
|
||||
var _resolve = function() {
|
||||
info = resolve_module_info(mod, package)
|
||||
if (!info) push(unresolved, {script: script, module: mod})
|
||||
} disruption {}
|
||||
_resolve()
|
||||
})
|
||||
checked = checked + 1
|
||||
} disruption {}
|
||||
_check()
|
||||
})
|
||||
|
||||
return {ok: checked, unresolved: unresolved, total: length(scripts)}
|
||||
}
|
||||
|
||||
Shop.get_package_scripts = get_package_scripts
|
||||
|
||||
Shop.list_packages = function()
|
||||
|
||||
Reference in New Issue
Block a user