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