rust_code_analysis/
function.rs1use std::io::Write;
2use std::path::PathBuf;
3
4use serde::Serialize;
5use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, StandardStreamLock, WriteColor};
6
7use crate::traits::*;
8
9use crate::checker::Checker;
10use crate::getter::Getter;
11
12#[derive(Debug, Serialize)]
14pub struct FunctionSpan {
15 pub name: String,
17 pub start_line: usize,
19 pub end_line: usize,
21 pub error: bool,
24}
25
26pub fn function<T: ParserTrait>(parser: &T) -> Vec<FunctionSpan> {
32 let root = parser.get_root();
33 let code = parser.get_code();
34 let mut spans = Vec::new();
35 root.act_on_node(&mut |n| {
36 if T::Checker::is_func(n) {
37 let start_line = n.object().start_position().row + 1;
38 let end_line = n.object().end_position().row + 1;
39 if let Some(name) = T::Getter::get_func_name(n, code) {
40 spans.push(FunctionSpan {
41 name: name.to_string(),
42 start_line,
43 end_line,
44 error: false,
45 });
46 } else {
47 spans.push(FunctionSpan {
48 name: "".to_string(),
49 start_line,
50 end_line,
51 error: true,
52 });
53 }
54 }
55 });
56
57 spans
58}
59
60fn dump_span(
61 span: FunctionSpan,
62 stdout: &mut StandardStreamLock,
63 last: bool,
64) -> std::io::Result<()> {
65 let pref = if last { " `- " } else { " |- " };
70
71 color!(stdout, Blue);
72 write!(stdout, "{}", pref)?;
73
74 if span.error {
75 color!(stdout, Red, true);
76 write!(stdout, "error: ")?;
77 } else {
78 color!(stdout, Magenta, true);
79 write!(stdout, "{}: ", span.name)?;
80 }
81
82 color!(stdout, Green);
83 write!(stdout, "from line ")?;
84
85 color!(stdout, White);
86 write!(stdout, "{}", span.start_line)?;
87
88 color!(stdout, Green);
89 write!(stdout, " to line ")?;
90
91 color!(stdout, White);
92 writeln!(stdout, "{}.", span.end_line)
93}
94
95fn dump_spans(mut spans: Vec<FunctionSpan>, path: PathBuf) -> std::io::Result<()> {
96 if !spans.is_empty() {
97 let stdout = StandardStream::stdout(ColorChoice::Always);
98 let mut stdout = stdout.lock();
99
100 color!(stdout, Yellow, true);
101 writeln!(&mut stdout, "In file {}", path.to_str().unwrap_or("..."))?;
102
103 for span in spans.drain(..spans.len() - 1) {
104 dump_span(span, &mut stdout, false)?;
105 }
106 dump_span(spans.pop().unwrap(), &mut stdout, true)?;
107 color!(stdout, White);
108 }
109 Ok(())
110}
111
112pub struct FunctionCfg {
115 pub path: PathBuf,
117}
118
119pub struct Function {
120 _guard: (),
121}
122
123impl Callback for Function {
124 type Res = std::io::Result<()>;
125 type Cfg = FunctionCfg;
126
127 fn call<T: ParserTrait>(cfg: Self::Cfg, parser: &T) -> Self::Res {
128 dump_spans(function(parser), cfg.path)
129 }
130}