1use quote::ToTokens;
2use serde::Serialize;
3use syn::{Expr, File, Item, Lit, Pat, Stmt, visit::Visit};
4
5#[derive(Serialize, Debug, Default)]
10pub struct AstJson {
11 #[serde(skip_serializing_if = "Vec::is_empty")]
12 pub items: Vec<ItemJson>,
13}
14
15#[derive(Serialize, Debug)]
21#[serde(tag = "type")]
22pub enum ItemJson {
23 Function {
24 name: String,
25 parameters: Vec<ParameterJson>,
26 return_type: Option<String>,
27 body: Vec<StmtJson>,
28 },
29 Struct {
30 name: String,
31 fields: Vec<FieldJson>,
32 },
33 Enum {
34 name: String,
35 variants: Vec<VariantJson>,
36 },
37 Other {
38 description: String,
39 },
40}
41
42#[derive(Serialize, Debug)]
46pub struct ParameterJson {
47 pub name: String,
48 pub type_info: String,
49}
50
51#[derive(Serialize, Debug)]
55pub struct FieldJson {
56 pub name: Option<String>,
57 pub type_info: String,
58}
59
60#[derive(Serialize, Debug)]
63pub struct VariantJson {
64 pub name: String,
65}
66
67#[derive(Serialize, Debug)]
71#[serde(tag = "type")]
72pub enum StmtJson {
73 VariableDeclaration {
74 name: String,
75 initializer: Option<Box<ExprJson>>,
76 },
77 Expression {
78 expr: Box<ExprJson>,
79 },
80 Other {
81 description: String,
82 },
83}
84
85#[derive(Serialize, Debug)]
88#[serde(tag = "type")]
89pub enum ExprJson {
90 IntLiteral {
91 value: String,
92 },
93 FloatLiteral {
94 value: String,
95 },
96 StringLiteral {
97 value: String,
98 },
99 BoolLiteral {
100 value: bool,
101 },
102 Binary {
103 operator: String,
104 left: Box<ExprJson>,
105 right: Box<ExprJson>,
106 },
107 FunctionCall {
108 function: Box<ExprJson>,
109 arguments: Vec<ExprJson>,
110 },
111 Identifier {
112 name: String,
113 },
114 If {
115 condition: Box<ExprJson>,
116 then_branch: Vec<StmtJson>,
117 else_branch: Option<Box<ExprJson>>,
118 },
119 Loop {
120 body: Vec<StmtJson>,
121 },
122 While {
123 condition: Box<ExprJson>,
124 body: Vec<StmtJson>,
125 },
126 Return {
127 value: Option<Box<ExprJson>>,
128 },
129 Other {
130 description: String,
131 },
132}
133
134pub struct JsonVisitor {
139 pub ast: AstJson,
140}
141
142impl Default for JsonVisitor {
148 fn default() -> Self {
149 Self::new()
150 }
151}
152
153impl JsonVisitor {
154 pub fn new() -> Self {
162 JsonVisitor {
163 ast: AstJson::default(),
164 }
165 }
166
167 pub fn to_json(&self) -> String {
175 match serde_json::to_string_pretty(&self.ast) {
176 Ok(json) => json,
177 Err(_) => String::from("{}"),
178 }
179 }
180
181 pub fn process_file(&mut self, file: &File) {
190 for item in &file.items {
191 self.process_item(item);
192 }
193 }
194
195 fn process_item(&mut self, item: &Item) {
204 match item {
205 Item::Fn(item_fn) => {
206 let mut parameters = Vec::new();
207 for param in &item_fn.sig.inputs {
208 match param {
209 syn::FnArg::Typed(pat_type) => {
210 if let Pat::Ident(pat_ident) = &*pat_type.pat {
211 parameters.push(ParameterJson {
212 name: pat_ident.ident.to_string(),
213 type_info: format!("{}", (*pat_type.ty).to_token_stream()),
214 });
215 }
216 }
217 syn::FnArg::Receiver(receiver) => {
218 parameters.push(ParameterJson {
219 name: "self".to_string(),
220 type_info: format!("{}", receiver.to_token_stream()),
221 });
222 }
223 }
224 }
225
226 let return_type = match &item_fn.sig.output {
227 syn::ReturnType::Default => None,
228 syn::ReturnType::Type(_, return_type) => {
229 Some(format!("{}", return_type.to_token_stream()))
230 }
231 };
232
233 let mut statements = Vec::new();
234 for stmt in &item_fn.block.stmts {
235 statements.push(self.visit_stmt_json(stmt));
236 }
237
238 self.ast.items.push(ItemJson::Function {
239 name: item_fn.sig.ident.to_string(),
240 parameters,
241 return_type,
242 body: statements,
243 });
244 }
245 Item::Struct(item_struct) => {
246 let mut fields = Vec::new();
247 for field in &item_struct.fields {
248 fields.push(FieldJson {
249 name: field.ident.as_ref().map(|ident| ident.to_string()),
250 type_info: format!("{}", field.ty.to_token_stream()),
251 });
252 }
253
254 self.ast.items.push(ItemJson::Struct {
255 name: item_struct.ident.to_string(),
256 fields,
257 });
258 }
259 Item::Enum(item_enum) => {
260 let mut variants = Vec::new();
261 for variant in &item_enum.variants {
262 variants.push(VariantJson {
263 name: variant.ident.to_string(),
264 });
265 }
266
267 self.ast.items.push(ItemJson::Enum {
268 name: item_enum.ident.to_string(),
269 variants,
270 });
271 }
272 _ => {
273 self.ast.items.push(ItemJson::Other {
274 description: format!("{}", item.to_token_stream()),
275 });
276 }
277 }
278 }
279}
280
281impl<'ast> Visit<'ast> for JsonVisitor {
284 fn visit_file(&mut self, file: &'ast File) {
293 self.process_file(file);
294 }
295}
296
297impl JsonVisitor {
300 fn visit_stmt_json(&mut self, stmt: &Stmt) -> StmtJson {
308 match stmt {
309 Stmt::Local(local) => {
310 let name = if let Pat::Ident(pat_ident) = &local.pat {
311 pat_ident.ident.to_string()
312 } else {
313 "unknown".to_string()
314 };
315
316 let initializer = local.init.as_ref().map(|init| Box::new(self.visit_expr_json(&init.expr)));
317
318 StmtJson::VariableDeclaration { name, initializer }
319 }
320 Stmt::Expr(expr, _) => StmtJson::Expression {
321 expr: Box::new(self.visit_expr_json(expr)),
322 },
323 _ => StmtJson::Other {
324 description: format!("{}", stmt.to_token_stream()),
325 },
326 }
327 }
328
329 fn visit_expr_json(&mut self, expr: &Expr) -> ExprJson {
338 match expr {
339 Expr::Lit(expr_lit) => match &expr_lit.lit {
340 Lit::Int(lit_int) => ExprJson::IntLiteral {
341 value: lit_int.base10_digits().to_string(),
342 },
343 Lit::Float(lit_float) => ExprJson::FloatLiteral {
344 value: lit_float.base10_digits().to_string(),
345 },
346 Lit::Str(lit_str) => ExprJson::StringLiteral {
347 value: lit_str.value(),
348 },
349 Lit::Bool(lit_bool) => ExprJson::BoolLiteral {
350 value: lit_bool.value,
351 },
352 _ => ExprJson::Other {
353 description: format!("{}", expr_lit.to_token_stream()),
354 },
355 },
356 Expr::Binary(expr_bin) => {
357 let op = match expr_bin.op {
358 syn::BinOp::Add(_) => "+",
359 syn::BinOp::Sub(_) => "-",
360 syn::BinOp::Mul(_) => "*",
361 syn::BinOp::Div(_) => "/",
362 syn::BinOp::Eq(_) => "==",
363 syn::BinOp::Lt(_) => "<",
364 syn::BinOp::Le(_) => "<=",
365 syn::BinOp::Ne(_) => "!=",
366 syn::BinOp::Ge(_) => ">=",
367 syn::BinOp::Gt(_) => ">",
368 _ => "other_operator",
369 };
370
371 ExprJson::Binary {
372 operator: op.to_string(),
373 left: Box::new(self.visit_expr_json(&expr_bin.left)),
374 right: Box::new(self.visit_expr_json(&expr_bin.right)),
375 }
376 }
377 Expr::Call(expr_call) => ExprJson::FunctionCall {
378 function: Box::new(self.visit_expr_json(&expr_call.func)),
379 arguments: expr_call
380 .args
381 .iter()
382 .map(|arg| self.visit_expr_json(arg))
383 .collect(),
384 },
385 Expr::Path(expr_path) => ExprJson::Identifier {
386 name: format!("{}", expr_path.to_token_stream()),
387 },
388 Expr::If(expr_if) => {
389 let mut then_stmts = Vec::new();
390 for stmt in &expr_if.then_branch.stmts {
391 then_stmts.push(self.visit_stmt_json(stmt));
392 }
393
394 let else_branch = if let Some((_, else_expr)) = &expr_if.else_branch {
395 Some(Box::new(self.visit_expr_json(else_expr)))
396 } else {
397 None
398 };
399
400 ExprJson::If {
401 condition: Box::new(self.visit_expr_json(&expr_if.cond)),
402 then_branch: then_stmts,
403 else_branch,
404 }
405 }
406 Expr::Loop(expr_loop) => {
407 let mut stmts = Vec::new();
408 for stmt in &expr_loop.body.stmts {
409 stmts.push(self.visit_stmt_json(stmt));
410 }
411
412 ExprJson::Loop { body: stmts }
413 }
414 Expr::While(expr_while) => {
415 let mut stmts = Vec::new();
416 for stmt in &expr_while.body.stmts {
417 stmts.push(self.visit_stmt_json(stmt));
418 }
419
420 ExprJson::While {
421 condition: Box::new(self.visit_expr_json(&expr_while.cond)),
422 body: stmts,
423 }
424 }
425 Expr::Return(expr_return) => ExprJson::Return {
426 value: expr_return
427 .expr
428 .as_ref()
429 .map(|e| Box::new(self.visit_expr_json(e))),
430 },
431 _ => ExprJson::Other {
432 description: format!("{}", expr.to_token_stream()),
433 },
434 }
435 }
436}
437
438#[cfg(test)]
439mod tests {
440 use super::*;
441 use crate::parse_rust_source;
442 use serde_json::Value;
443
444 #[test]
445 fn test_json_serialization_function() {
446 let source = r#"
447 fn add(a: i32, b: i32) -> i32 {
448 a + b
449 }
450 "#;
451
452 let file = parse_rust_source(source).unwrap();
453 let mut visitor = JsonVisitor::new();
454 visitor.process_file(&file);
455
456 let json = visitor.to_json();
457
458 let parsed: Value = serde_json::from_str(&json).expect("JSONのパースに失敗");
460
461 assert!(parsed["items"].is_array());
463
464 let first_item = &parsed["items"][0];
466
467 assert_eq!(first_item["type"], "Function");
469 assert_eq!(first_item["name"], "add");
470
471 assert!(first_item["parameters"].is_array());
473 assert_eq!(first_item["parameters"][0]["name"], "a");
474 assert_eq!(first_item["parameters"][1]["name"], "b");
475
476 assert_eq!(first_item["return_type"], "i32");
478 }
479
480 #[test]
481 fn test_json_serialization_struct() {
482 let source = r#"
483 struct Point {
484 x: f64,
485 y: f64,
486 }
487 "#;
488
489 let file = parse_rust_source(source).unwrap();
490 let mut visitor = JsonVisitor::new();
491 visitor.process_file(&file);
492
493 let json = visitor.to_json();
494
495 let parsed: Value = serde_json::from_str(&json).expect("JSONのパースに失敗");
497
498 assert!(parsed["items"].is_array());
500
501 let first_item = &parsed["items"][0];
503
504 assert_eq!(first_item["type"], "Struct");
506 assert_eq!(first_item["name"], "Point");
507
508 assert!(first_item["fields"].is_array());
510 assert_eq!(first_item["fields"][0]["name"], "x");
511 assert_eq!(first_item["fields"][1]["name"], "y");
512 }
513
514 #[test]
515 fn test_json_serialization_enum() {
516 let source = r#"
517 enum Direction {
518 North,
519 East,
520 South,
521 West,
522 }
523 "#;
524
525 let file = parse_rust_source(source).unwrap();
526 let mut visitor = JsonVisitor::new();
527 visitor.process_file(&file);
528
529 let json = visitor.to_json();
530
531 let parsed: Value = serde_json::from_str(&json).expect("JSONのパースに失敗");
533
534 assert!(parsed["items"].is_array());
536
537 let first_item = &parsed["items"][0];
539
540 assert_eq!(first_item["type"], "Enum");
542 assert_eq!(first_item["name"], "Direction");
543
544 assert!(first_item["variants"].is_array());
546 assert_eq!(first_item["variants"][0]["name"], "North");
547 assert_eq!(first_item["variants"][1]["name"], "East");
548 assert_eq!(first_item["variants"][2]["name"], "South");
549 assert_eq!(first_item["variants"][3]["name"], "West");
550 }
551
552 #[test]
553 fn test_json_serialization_complex() {
554 let source = r#"
555 fn complex_expr() {
556 let result = (10 + 20) * 30 / (5 - 2);
557 if result > 100 {
558 println!("Large result: {}", result);
559 } else {
560 println!("Small result: {}", result);
561 }
562 }
563 "#;
564
565 let file = parse_rust_source(source).unwrap();
566 let mut visitor = JsonVisitor::new();
567 visitor.process_file(&file);
568
569 let json = visitor.to_json();
570
571 let parsed: Value = serde_json::from_str(&json).expect("JSONのパースに失敗");
573
574 assert!(parsed["items"].is_array());
576
577 let first_item = &parsed["items"][0];
579
580 assert_eq!(first_item["type"], "Function");
582 assert_eq!(first_item["name"], "complex_expr");
583
584 assert!(first_item["body"].is_array());
586 assert_eq!(first_item["body"][0]["type"], "VariableDeclaration");
587 assert_eq!(first_item["body"][0]["name"], "result");
588
589 assert_eq!(first_item["body"][1]["type"], "Expression");
591 assert_eq!(first_item["body"][1]["expr"]["type"], "If");
592 }
593
594 #[test]
596 fn test_debug_json_output() {
597 let source = r#"
598 fn test_func() {
599 println!("Hello");
600 }
601 "#;
602
603 let file = parse_rust_source(source).unwrap();
604 let mut visitor = JsonVisitor::new();
605 visitor.process_file(&file);
606
607 let json = visitor.to_json();
609
610 assert!(!visitor.ast.items.is_empty(), "AST項目が空です!");
612
613 let parsed: Value = serde_json::from_str(&json).expect("JSONのパースに失敗");
615
616 assert!(parsed["items"].is_array());
618
619 let first_item = &parsed["items"][0];
621
622 assert_eq!(first_item["type"], "Function");
624 assert_eq!(first_item["name"], "test_func");
625 }
626
627 #[test]
629 fn test_basic_serialization() {
630 let mut ast = AstJson::default();
632
633 ast.items.push(ItemJson::Function {
635 name: "manual_func".to_string(),
636 parameters: vec![],
637 return_type: Some("i32".to_string()),
638 body: vec![],
639 });
640
641 let json = serde_json::to_string_pretty(&ast).unwrap();
643
644 let parsed: Value = serde_json::from_str(&json).expect("JSONのパースに失敗");
646
647 assert!(parsed["items"].is_array());
649
650 let first_item = &parsed["items"][0];
652
653 assert_eq!(first_item["type"], "Function");
655 assert_eq!(first_item["name"], "manual_func");
656 }
657}