Skip to content

Commit 81861fc

Browse files
committed
Diagnostics 增加更多的错误信息, 支持提示信息
1 parent 393207c commit 81861fc

File tree

4 files changed

+112
-46
lines changed

4 files changed

+112
-46
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/bangls/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bangls"
3-
version = "0.1.5"
3+
version = "0.1.6"
44
edition = "2024"
55

66
[features]

tools/bangls/src/main.rs

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,10 @@ impl Ctx {
192192
None
193193
}
194194

195-
fn parse_for_parse_error(&self, file: &str) -> Option<((usize, usize), String)> {
195+
fn parse_for_parse_error(&self, file: &str) -> Result<Expand, ((usize, usize), String)> {
196196
let parser = parser::TopLevelParser::new();
197197
match parser.parse(&mut syntax::Meta::new(), file) {
198-
Ok(_) => None,
198+
Ok(top) => Ok(top),
199199
Err(e) => {
200200
let loc = match e {
201201
parser::lalrpop_util::ParseError::InvalidToken { location } |
@@ -209,7 +209,7 @@ impl Ctx {
209209
},
210210
};
211211
let fmtted_err = parser::format_parse_err::<5>(e, file);
212-
Some((loc, fmtted_err))
212+
Err((loc, fmtted_err))
213213
},
214214
}
215215
}
@@ -245,14 +245,7 @@ impl RequestHandler for request::Completion {
245245
let Some((top, src)) = ctx.try_parse_for_complete((line, col), &file) else {
246246
return Ok(None);
247247
};
248-
let mut meta = CompileMeta::with_source(src.into());
249-
meta.is_emulated = true;
250-
251-
let assert_meta = std::panic::AssertUnwindSafe(&mut meta);
252-
let _ = std::panic::catch_unwind(|| {
253-
top.compile(&mut {assert_meta}.0);
254-
});
255-
let infos = meta.emulate_infos;
248+
let infos = emulate(top, src);
256249

257250
let completes = generate_completes(&infos);
258251
let completes = lsp_types::CompletionResponse::Array(completes);
@@ -353,16 +346,49 @@ fn tigger_diagnostics(ctx: &mut Ctx, uri: &Uri) -> Vec<Diagnostic> {
353346
let Some(file) = ctx.open_files.get(uri) else { return vec![] };
354347
let mut diags = vec![];
355348

356-
if let Some(((sindex, eindex), error)) = ctx.parse_for_parse_error(file) {
357-
let start = rgpos(line_column(file, sindex));
358-
let end = rgpos(line_column(file, eindex));
359-
diags.push(Diagnostic {
360-
message: error,
361-
range: lsp_types::Range { start, end },
362-
severity: Some(DiagnosticSeverity::ERROR),
363-
..Default::default()
364-
});
349+
match ctx.parse_for_parse_error(file) {
350+
Err(((sindex, eindex), error)) => {
351+
let start = rgpos(line_column(file, sindex));
352+
let end = rgpos(line_column(file, eindex));
353+
diags.push(Diagnostic {
354+
message: error,
355+
range: lsp_types::Range { start, end },
356+
severity: Some(DiagnosticSeverity::ERROR),
357+
..Default::default()
358+
});
359+
}
360+
Ok(top) => {
361+
let infos = emulate(top, file.clone());
362+
for info in infos {
363+
let Some(diagnostic) = info.diagnostic else { continue };
364+
let Some(loc) = info.location.or_else(|| info.is_error.then(|| {
365+
(1, 1)
366+
})) else { continue };
367+
let start = rgpos(loc);
368+
diags.push(Diagnostic {
369+
range: lsp_types::Range { start, end: start },
370+
severity: Some(if info.is_error {
371+
DiagnosticSeverity::ERROR
372+
} else {
373+
DiagnosticSeverity::HINT
374+
}),
375+
message: diagnostic,
376+
..Default::default()
377+
});
378+
}
379+
},
365380
}
366381

367382
diags
368383
}
384+
385+
fn emulate(top: Expand, src: String) -> Vec<EmulateInfo> {
386+
let mut meta = CompileMeta::with_source(src.into());
387+
meta.is_emulated = true;
388+
389+
let assert_meta = std::panic::AssertUnwindSafe(&mut meta);
390+
let _ = std::panic::catch_unwind(|| {
391+
top.compile(&mut {assert_meta}.0);
392+
});
393+
meta.emulate_infos.take()
394+
}

tools/syntax/src/lib.rs

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,17 @@ pub enum Errors {
159159
/// 带有错误前缀, 并且文本为红色的eprintln
160160
macro_rules! err {
161161
( $fmtter:expr $(, $args:expr)* $(,)? ) => {
162-
eprintln!(concat!("\x1b[1;31m", "CompileError:\n", $fmtter, "\x1b[22;39m"), $($args),*);
162+
err!(None => $fmtter $(, $args)*);
163163
};
164+
( $loc:expr => $fmtter:expr $(, $args:expr)* $(,)? ) => {
165+
let err = format!(concat!("CompileError:\n", $fmtter), $($args),*);
166+
eprintln!("\x1b[1;31m{err}\x1b[22;39m");
167+
$crate::LAST_ERR.replace(($loc.into(), err));
168+
};
169+
}
170+
thread_local! {
171+
static LAST_ERR: Cell<(Option<(u32, u32)>, String)>
172+
= Cell::new((None, String::new()));
164173
}
165174

166175
pub type Location = usize;
@@ -322,7 +331,7 @@ impl TakeHandle for Value {
322331
},
323332
ref cmp @ Self::Cmper(Cmper(ref loc)) => {
324333
let loc = loc.location(&meta.source);
325-
err!(
334+
err!(loc =>
326335
"{}\n最终未被展开的 Cmper, 位于: {}:{}\n{}",
327336
meta.err_info().join("\n"),
328337
loc.0,
@@ -3015,31 +3024,31 @@ impl Compile for ArgsRepeat {
30153024
Either::Left(count) => count,
30163025
Either::Right(value) => {
30173026
let Some((n, _)) = value.try_eval_const_num(meta) else {
3018-
let (line, col) = loc.location(&meta.source);
3019-
err!(
3027+
let loc = loc.location(&meta.source);
3028+
err!(loc =>
30203029
"{}\n重复块次数不是数字, 位于: {}:{}\n{}",
30213030
meta.err_info().join("\n"),
3022-
line, col,
3031+
loc.0, loc.1,
30233032
value.display_src(meta),
30243033
);
30253034
meta.exit(6)
30263035
};
30273036
let n = n.round();
30283037
if n < 0.0 || !n.is_finite() {
3029-
let (line, col) = loc.location(&meta.source);
3030-
err!(
3038+
let loc = loc.location(&meta.source);
3039+
err!(loc =>
30313040
"{}\n重复块次数必须不小于0 ({}), 位于: {}:{}",
30323041
meta.err_info().join("\n"),
3033-
n, line, col,
3042+
n, loc.0, loc.1
30343043
);
30353044
meta.exit(6)
30363045
}
30373046
if n > 512.0 {
3038-
let (line, col) = loc.location(&meta.source);
3039-
err!(
3047+
let loc = loc.location(&meta.source);
3048+
err!(loc =>
30403049
"{}\n重复块次数过大 ({}), 位于: {}:{}",
30413050
meta.err_info().join("\n"),
3042-
n, line, col,
3051+
n, loc.0, loc.1
30433052
);
30443053
meta.exit(6)
30453054
}
@@ -3066,7 +3075,7 @@ impl Compile for ArgsRepeat {
30663075

30673076
if !meta.args_repeat_flags.last().unwrap() { break }
30683077
if i >= meta.args_repeat_limit {
3069-
err!(
3078+
err!(loc.location(&meta.source) =>
30703079
"Maximum repeat limit exceeded ({})",
30713080
meta.args_repeat_limit,
30723081
);
@@ -4175,9 +4184,12 @@ pub enum Emulate {
41754184
NakedBind(Var),
41764185
}
41774186

4178-
#[derive(Debug)]
4187+
#[derive(Debug, Default)]
41794188
pub struct EmulateInfo {
41804189
pub exist_vars: Vec<(Emulate, Var)>,
4190+
pub location: Option<(u32, u32)>,
4191+
pub diagnostic: Option<String>,
4192+
pub is_error: bool,
41814193
}
41824194

41834195
pub struct CompileMeta {
@@ -4213,7 +4225,7 @@ pub struct CompileMeta {
42134225
log_count: usize,
42144226
source: Rc<String>,
42154227
pub is_emulated: bool,
4216-
pub emulate_infos: Vec<EmulateInfo>,
4228+
pub emulate_infos: Cell<Vec<EmulateInfo>>,
42174229
}
42184230
impl Debug for CompileMeta {
42194231
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -4286,7 +4298,7 @@ impl CompileMeta {
42864298
log_count: 0,
42874299
source,
42884300
is_emulated: false,
4289-
emulate_infos: vec![],
4301+
emulate_infos: vec![].into(),
42904302
};
42914303
let builtin = Var::from(Self::BUILTIN_FUNCS_BINDER);
42924304
for builtin_func in build_builtins() {
@@ -4434,8 +4446,25 @@ impl CompileMeta {
44344446
&mut self.parse_lines
44354447
}
44364448

4449+
fn emulate(&self, emulate_info: EmulateInfo) {
4450+
if self.is_emulated {
4451+
let mut infos = self.emulate_infos.take();
4452+
infos.push(emulate_info);
4453+
self.emulate_infos.set(infos);
4454+
}
4455+
}
4456+
44374457
fn exit(&self, code: i32) -> ! {
44384458
if self.is_emulated {
4459+
let (location, error) = LAST_ERR.take();
4460+
if !error.is_empty() {
4461+
self.emulate(EmulateInfo {
4462+
location,
4463+
diagnostic: Some(error),
4464+
is_error: true,
4465+
..Default::default()
4466+
});
4467+
}
44394468
panic!("exit code {code}");
44404469
} else {
44414470
std::process::exit(code)
@@ -4457,7 +4486,7 @@ impl CompileMeta {
44574486
.for_each(|(kind, var)| if printed.insert(var) {
44584487
vars.push((kind, var.clone()));
44594488
});
4460-
self.emulate_infos.push(EmulateInfo { exist_vars: vars });
4489+
self.emulate(EmulateInfo { exist_vars: vars, ..Default::default() });
44614490
}
44624491

44634492
fn debug_binds_status(&mut self, handle: &Var, name: &mut Var) {
@@ -4481,7 +4510,7 @@ impl CompileMeta {
44814510
}
44824511
bind_vars
44834512
});
4484-
self.emulate_infos.push(EmulateInfo { exist_vars: bind_vars });
4513+
self.emulate(EmulateInfo { exist_vars: bind_vars, ..Default::default() });
44854514
}
44864515

44874516
/// 进入一个拥有子命名空间的子块
@@ -4805,11 +4834,13 @@ impl CompileMeta {
48054834
pub fn err_info(&self) -> Vec<String> {
48064835
let mut res = Vec::new();
48074836

4808-
let mut tag_lines = self.debug_tag_codes();
4809-
line_first_add(&mut tag_lines, "\t");
4837+
if !self.is_emulated {
4838+
let mut tag_lines = self.debug_tag_codes();
4839+
line_first_add(&mut tag_lines, "\t");
48104840

4811-
res.push("已生成代码:".into());
4812-
res.extend(tag_lines);
4841+
res.push("已生成代码:".into());
4842+
res.extend(tag_lines);
4843+
}
48134844
res
48144845
}
48154846

@@ -4908,6 +4939,17 @@ impl CompileMeta {
49084939
self.env_args.pop().unwrap()
49094940
}
49104941

4942+
pub fn log_info_at(&mut self, line: u32, column: u32, s: impl std::fmt::Display) {
4943+
if self.is_emulated {
4944+
self.emulate(EmulateInfo {
4945+
location: Some((line, column)),
4946+
diagnostic: Some(s.to_string()),
4947+
..Default::default()
4948+
});
4949+
}
4950+
self.log_info(format_args!("{line}:{column} {s}"));
4951+
}
4952+
49114953
pub fn log_info(&mut self, s: impl std::fmt::Display) {
49124954
self.log_count += 1;
49134955
eprintln!("{}", csi!(1; 22; "[I] {}",
@@ -5078,9 +5120,7 @@ impl CompileMeta {
50785120
} else {
50795121
format!("{no_effect:#?}")
50805122
};
5081-
self.log_info(format_args!(
5082-
"{line}:{column} Take no effect: {no_effect}",
5083-
));
5123+
self.log_info_at(line, column, format_args!("Take no effect: {no_effect}"));
50845124
}
50855125
}
50865126
}

0 commit comments

Comments
 (0)