[pitboss] sweep after phase 14: 5 deferred items resolved

This commit is contained in:
pitboss 2026-05-14 17:10:20 -05:00
parent bd1bd0ce84
commit 919bc4e7e2
4 changed files with 64 additions and 48 deletions

View file

@ -524,13 +524,18 @@ fn generate_harness_java(spec: &HarnessSpec, shape: JavaShape, entry_class: &str
""
};
// Reflection imports are only used by shapes whose helpers / catch
// clause reference them; emitting them for `StaticMethod` /
// `StaticMain` produces unused-import warnings under javac -Xlint.
let imports = if shape_uses_reflection(shape) {
"import java.lang.reflect.Method;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\n\n"
} else {
""
};
format!(
r#"// Nyx dynamic harness — auto-generated, do not edit (Phase 14 — JavaShape::{shape:?}).
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class NyxHarness {{
{imports}public class NyxHarness {{
{probe}
{helpers}
public static void main(String[] args) {{
@ -557,6 +562,7 @@ public class NyxHarness {{
}}
"#,
shape = shape,
imports = imports,
probe = probe,
helpers = helpers,
pre_call = pre_call,
@ -989,4 +995,53 @@ mod tests {
let harness = emit(&spec).unwrap();
assert_eq!(harness.entry_subpath, Some("Entry.java".to_owned()));
}
#[test]
fn detect_shape_reads_file_and_returns_shape() {
// Drive the public `detect_shape(spec)` wrapper end-to-end:
// write a representative source to a tempfile, then assert the
// wrapper reads it and produces the expected JavaShape variant.
let dir = std::env::temp_dir().join(format!(
"nyx_detect_shape_{}",
std::process::id()
));
let _ = std::fs::create_dir_all(&dir);
let cases: &[(&str, &str, &str, EntryKind, JavaShape)] = &[
(
"Servlet.java",
"import javax.servlet.http.HttpServletRequest;\npublic class Servlet extends HttpServlet { public void doGet(HttpServletRequest r, HttpServletResponse w) {} }",
"doGet",
EntryKind::HttpRoute,
JavaShape::ServletDoGet,
),
(
"Spring.java",
"@RestController\npublic class Spring { @GetMapping(\"/x\") public String run(String p) { return p; } }",
"run",
EntryKind::HttpRoute,
JavaShape::SpringController,
),
(
"MainClass.java",
"public class MainClass { public static void main(String[] args) {} }",
"main",
EntryKind::CliSubcommand,
JavaShape::StaticMain,
),
(
"Plain.java",
"public class Plain { public static void run(String p) {} }",
"run",
EntryKind::Function,
JavaShape::StaticMethod,
),
];
for (name, body, entry_name, kind, expected) in cases {
let path = dir.join(name);
std::fs::write(&path, body).expect("write fixture");
let spec = make_spec_with(*kind, entry_name, path.to_str().unwrap());
assert_eq!(detect_shape(&spec), *expected, "case {name}");
}
let _ = std::fs::remove_dir_all(&dir);
}
}

View file

@ -50,24 +50,6 @@ pub fn emit(spec: &HarnessSpec) -> Result<HarnessSource, UnsupportedReason> {
js_shared::emit(spec, false)
}
/// Derive the JS module name from an entry file path.
///
/// Always returns `"entry"` because the JS harness stages the entry file at
/// `workdir/entry.js` so `require('./entry')` is the only path that resolves
/// regardless of the source file's original name.
pub fn entry_module_name(_entry_file: &str) -> String {
"entry".to_owned()
}
/// Derive the entry filename from an entry file path.
///
/// Always `"entry.js"` for the JS surface; TypeScript uses `"entry.ts"` (see
/// [`crate::dynamic::lang::typescript`]) and ESM-default shapes use
/// `"entry.mjs"` (handled inside `js_shared`).
pub fn entry_module_filename(_entry_file: &str) -> String {
"entry.js".to_owned()
}
#[cfg(test)]
mod tests {
use super::*;
@ -164,11 +146,4 @@ mod tests {
assert!(hint.contains("Phase 13"));
}
#[test]
fn entry_module_name_is_always_entry_to_match_copy_destination() {
assert_eq!(entry_module_name("src/handlers/login.js"), "entry");
assert_eq!(entry_module_name("app.ts"), "entry");
assert_eq!(entry_module_name("handler.mjs"), "entry");
assert_eq!(entry_module_name("no_ext"), "entry");
}
}

View file

@ -988,7 +988,7 @@ fn finalize_spec(
sink_line: u32,
derivation: SpecDerivationStrategy,
) -> HarnessSpec {
let toolchain_id = toolchain_id_for_lang(lang).to_owned();
let toolchain_id = default_toolchain_id(lang).to_owned();
let stubs_required = StubKind::for_cap(expected_cap);
let mut spec = HarnessSpec {
finding_id: format!("{:016x}", diag.stable_hash),
@ -1031,7 +1031,7 @@ pub fn outermost_entry(steps: &[crate::evidence::FlowStep]) -> Option<EntryRef>
/// Default toolchain label for a language (informational; harness builder
/// may override for locally-installed compilers/runtimes).
fn toolchain_id_for_lang(lang: Lang) -> &'static str {
pub fn default_toolchain_id(lang: Lang) -> &'static str {
match lang {
Lang::Rust => "rust-stable",
Lang::C => "gcc-stable",