Phase 21.3 WIP: Hako Source Checker improvements - HC011/HC016/HC017 実装完了

主な変更:
-  HC011 (dead methods) 実装・テスト緑
-  HC016 (unused alias) 実装・テスト緑
-  HC017 (non-ascii quotes) 実装完了
- 🔧 tokenizer/parser_core 強化(AST優先ルート)
- 🛡️ plugin_guard.rs 追加(stderr専用出力)
- 📋 テストインフラ整備(run_tests.sh改善)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-08 00:46:34 +09:00
parent 647e15d12e
commit 58a6471883
39 changed files with 1435 additions and 283 deletions

View File

@ -12,3 +12,4 @@ pub mod resolve;
pub mod exec;
pub mod core_bridge;
pub mod hako;
pub mod plugin_guard;

View File

@ -0,0 +1,89 @@
/*!
* Plugin guard utilities
*
* Centralized helper to check required plugin providers and emit
* consistent diagnostics across runner modes.
*/
/// Build the list of required provider type names.
///
/// Priority:
/// - If env `NYASH_PLUGIN_OVERRIDE_TYPES` is set, use it (comma-separated).
/// - Otherwise, return a conservative default set used in VM paths.
pub fn gather_required_providers() -> Vec<String> {
if let Ok(list) = std::env::var("NYASH_PLUGIN_OVERRIDE_TYPES") {
let mut v: Vec<String> = list
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
v.sort();
v.dedup();
return v;
}
// Default conservative set
let mut v = vec![
"FileBox".to_string(),
"ConsoleBox".to_string(),
"ArrayBox".to_string(),
"MapBox".to_string(),
"StringBox".to_string(),
"IntegerBox".to_string(),
];
v
}
/// Return missing providers by checking the unified registry.
pub fn detect_missing_providers(required: &[String]) -> Vec<String> {
let reg = nyash_rust::runtime::get_global_registry();
let mut missing: Vec<String> = Vec::new();
for t in required {
if reg.get_provider(t).is_none() {
missing.push(t.clone());
}
}
missing
}
/// Emit hints for specific provider types.
fn emit_hints_for(missing: &[String]) {
if missing.iter().any(|t| t == "FileBox") {
eprintln!("[plugin/hint] FileBox plugin is required for file I/O (new FileBox/open/read).");
eprintln!("[plugin/hint] Build and load plugin: see tools/plugin_v2_smoke.sh or configure nyash.toml [libraries.*.FileBox].");
eprintln!("[plugin/hint] Ensure LD_LIBRARY_PATH (or platform equivalent) includes the plugin directory.");
eprintln!("[plugin/hint] For analyzer runs, you can avoid FileBox via --source-file <path> <text>.");
}
}
/// Check provider availability and emit diagnostics.
///
/// - `strict`: exit(1) when any provider is missing.
/// - `quiet_pipe`: respect quiet JSON pipelines; we still write diagnostics to stderr only.
/// - `label`: context label (e.g., "vm", "vm-fallback") for messages.
pub fn check_and_report(strict: bool, quiet_pipe: bool, label: &str) {
let required = gather_required_providers();
let missing = detect_missing_providers(&required);
if missing.is_empty() {
return;
}
if strict {
eprintln!(
"{} plugin-first strict: missing providers for: {:?}",
label, missing
);
emit_hints_for(&missing);
// Do not print anything to stdout in quiet mode; just exit with 1
std::process::exit(1);
} else {
eprintln!(
"[plugin/missing] {} providers not loaded: {:?}",
label, missing
);
emit_hints_for(&missing);
if quiet_pipe {
// In quiet JSON mode, avoid noisy stdout; hints are on stderr already.
}
}
}