resolve_and_dump/
resolve_and_dump.rs1use std::io::Write;
25use std::process::ExitCode;
26
27use hermes_parser::{parse_named, ParseFlags};
28use hermes_sema::{resolve_for_compile, CompileOptions, ResolvedJS};
29
30fn main() -> ExitCode {
31 let mut args = std::env::args().skip(1);
32 let mut summary = false;
33 let mut path = None;
34 for arg in args.by_ref() {
35 match arg.as_str() {
36 "--summary" => summary = true,
37 _ => path = Some(arg),
38 }
39 }
40 let Some(path) = path else {
41 eprintln!("usage: resolve_and_dump [--summary] <file.js>");
42 return ExitCode::from(1);
43 };
44
45 let source = match std::fs::read_to_string(&path) {
46 Ok(s) => s,
47 Err(e) => {
48 eprintln!("resolve_and_dump: cannot read '{path}': {e}");
49 return ExitCode::from(1);
50 }
51 };
52
53 let parsed = match parse_named(&source, &path, ParseFlags::default()) {
56 Ok(parsed) => parsed,
57 Err(e) => {
58 for m in e.messages() {
59 eprint!("{m}");
60 }
61 return ExitCode::from(2);
62 }
63 };
64
65 let options = CompileOptions::default();
69 let mut resolved = match resolve_for_compile(parsed, &options) {
70 Ok(resolved) => resolved,
71 Err(e) => {
72 for m in e.messages() {
73 eprint!("{m}");
74 }
75 return ExitCode::from(2);
76 }
77 };
78
79 for d in resolved.diagnostics() {
81 eprintln!("{}:{}:{}: {}", d.file_name, d.line, d.col, d.message);
82 }
83
84 if summary {
86 print_summary(&mut resolved);
87 } else {
88 let dump = resolved.to_sema_dump();
91 std::io::stdout().write_all(&dump).expect("write failed");
92 }
93 ExitCode::SUCCESS
94}
95
96fn print_summary(resolved: &mut ResolvedJS) {
99 use hermes_parser::ast::node::Node;
100 use hermes_parser::ast::visitor::Visitor;
101
102 struct Counter<'a> {
104 sem: &'a hermes_sema::sem_context::SemContext,
105 resolved: usize,
106 unresolved: usize,
107 }
108 impl<'gc> Visitor<'gc> for Counter<'_> {
109 fn visit_node(&mut self, node: &'gc Node<'gc>) {
110 if let Node::Identifier(id) = node {
111 match self.sem.get_expression_decl(id) {
112 Some(_) => self.resolved += 1,
113 None => self.unresolved += 1,
114 }
115 }
116 node.visit_children(self);
117 }
118 }
119
120 let (resolved_ids, unresolved_ids) =
121 resolved.with_program(|_gc, root, sem| {
122 let mut c = Counter {
123 sem,
124 resolved: 0,
125 unresolved: 0,
126 };
127 c.visit_node(root);
128 (c.resolved, c.unresolved)
129 });
130
131 let sem = resolved.sem_context();
132 println!("functions: {}", sem.functions_len());
133 println!("resolved references: {resolved_ids}");
134 println!("other identifiers: {unresolved_ids}");
135}