big_code_analysis/
function.rs1#![allow(
8 clippy::enum_glob_use,
9 clippy::needless_pass_by_value,
10 clippy::wildcard_imports
11)]
12
13use std::io::Write;
14use std::path::PathBuf;
15
16use serde::Serialize;
17use termcolor::{Color, ColorChoice, StandardStream, StandardStreamLock};
18
19use crate::traits::*;
20
21use crate::checker::Checker;
22use crate::getter::Getter;
23
24use crate::tools::{color, intense_color};
25
26#[derive(Debug, Serialize)]
28pub struct FunctionSpan {
29 pub name: String,
31 pub start_line: usize,
33 pub end_line: usize,
35 pub error: bool,
38}
39
40#[doc(hidden)]
44pub fn function<T: ParserTrait>(parser: &T) -> Vec<FunctionSpan> {
50 let root = parser.get_root();
51 let code = parser.get_code();
52 let mut spans = Vec::new();
53 root.act_on_node(&mut |n| {
54 if T::Checker::is_func(n) {
55 let start_line = n.start_row() + 1;
56 let end_line = n.end_row() + 1;
57 if let Some(name) = T::Getter::get_func_name(n, code) {
58 spans.push(FunctionSpan {
59 name: name.to_string(),
60 start_line,
61 end_line,
62 error: false,
63 });
64 } else {
65 spans.push(FunctionSpan {
66 name: String::new(),
67 start_line,
68 end_line,
69 error: true,
70 });
71 }
72 }
73 });
74
75 spans
76}
77
78fn dump_span(
79 span: FunctionSpan,
80 stdout: &mut StandardStreamLock,
81 last: bool,
82) -> std::io::Result<()> {
83 let pref = if last { " `- " } else { " |- " };
88
89 color(stdout, Color::Blue)?;
90 write!(stdout, "{pref}")?;
91
92 if span.error {
93 intense_color(stdout, Color::Red)?;
94 write!(stdout, "error: ")?;
95 } else {
96 intense_color(stdout, Color::Magenta)?;
97 write!(stdout, "{}: ", span.name)?;
98 }
99
100 color(stdout, Color::Green)?;
101 write!(stdout, "from line ")?;
102
103 color(stdout, Color::White)?;
104 write!(stdout, "{}", span.start_line)?;
105
106 color(stdout, Color::Green)?;
107 write!(stdout, " to line ")?;
108
109 color(stdout, Color::White)?;
110 writeln!(stdout, "{}.", span.end_line)
111}
112
113fn dump_spans(mut spans: Vec<FunctionSpan>, path: PathBuf) -> std::io::Result<()> {
114 if !spans.is_empty() {
115 let stdout = StandardStream::stdout(ColorChoice::Always);
116 let mut stdout = stdout.lock();
117
118 intense_color(&mut stdout, Color::Yellow)?;
119 writeln!(&mut stdout, "In file {}", path.to_str().unwrap_or("..."))?;
120
121 for span in spans.drain(..spans.len() - 1) {
122 dump_span(span, &mut stdout, false)?;
123 }
124 dump_span(spans.pop().unwrap(), &mut stdout, true)?;
125 color(&mut stdout, Color::White)?;
126 }
127 Ok(())
128}
129
130#[derive(Debug)]
133pub struct FunctionCfg {
134 pub path: PathBuf,
136}
137
138pub struct Function {
140 _guard: (),
141}
142
143impl Callback for Function {
144 type Res = std::io::Result<()>;
145 type Cfg = FunctionCfg;
146
147 fn call<T: ParserTrait>(cfg: Self::Cfg, parser: &T) -> Self::Res {
148 dump_spans(function(parser), cfg.path)
149 }
150}