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
use crate::ast::Range;
use crate::rules;
use serde_derive::Serialize;
#[derive(Serialize, Clone, Debug, PartialEq)]
pub struct Diagnostic {
pub kind: DiagnosticKind,
pub range: Range,
pub message: String,
pub context_message: Option<String>,
pub hint: Option<String>,
pub related_infos: Vec<RelatedInfo>,
}
#[derive(Serialize, Clone, Debug, PartialEq)]
pub enum DiagnosticKind {
Error,
Warning,
}
#[derive(Serialize, Clone, Debug, PartialEq)]
pub struct RelatedInfo {
pub range: Range,
pub message: String,
}
pub type ErrorRecovery<'input> =
lalrpop_util::ErrorRecovery<usize, rules::aidl::Token<'input>, &'static str>;
pub type ParseError<'input> =
lalrpop_util::ParseError<usize, rules::aidl::Token<'input>, &'static str>;
impl Diagnostic {
pub(crate) fn from_error_recovery<'input>(
msg: &'static str,
lookup: &line_col::LineColLookup,
error_recovery: ErrorRecovery<'input>,
) -> Option<Diagnostic> {
Self::from_parse_error(lookup, error_recovery.error).map(|d| Diagnostic {
message: format!("{} - {}", msg, d.message),
..d
})
}
pub(crate) fn from_parse_error(
lookup: &line_col::LineColLookup,
e: ParseError,
) -> Option<Diagnostic> {
match e {
lalrpop_util::ParseError::InvalidToken { location } => Some(Diagnostic {
kind: DiagnosticKind::Error,
message: "Invalid token".to_owned(),
context_message: Some("invalid token".to_owned()),
range: Range::new(lookup, location, location),
hint: None,
related_infos: Vec::new(),
}),
lalrpop_util::ParseError::UnrecognizedEOF { location, expected } => Some(Diagnostic {
kind: DiagnosticKind::Error,
message: format!("Unrecognized EOF{}", expected_token_str(&expected)),
context_message: Some("unrecognized EOF".to_owned()),
range: Range::new(lookup, location, location),
hint: None,
related_infos: Vec::new(),
}),
lalrpop_util::ParseError::UnrecognizedToken { token, expected } => Some(Diagnostic {
kind: DiagnosticKind::Error,
message: format!(
"Unrecognized token `{}`{}",
token.1,
expected_token_str(&expected)
),
context_message: Some("unrecognized token".to_owned()),
range: Range::new(lookup, token.0, token.2),
hint: None,
related_infos: Vec::new(),
}),
lalrpop_util::ParseError::ExtraToken { token } => Some(Diagnostic {
kind: DiagnosticKind::Error,
message: format!("Extra token `{}`", token.1,),
context_message: Some("extra token".to_owned()),
range: Range::new(lookup, token.0, token.2),
hint: None,
related_infos: Vec::new(),
}),
lalrpop_util::ParseError::User { error: _ } => None,
}
}
}
fn expected_token_str(v: &[String]) -> String {
match v.len() {
0 => String::new(),
1 => format!("\nExpected one of {}", v[0]),
_ => format!(
"\nExpected one of {} or {}",
v[0..v.len() - 2].join(", "),
v[v.len() - 1]
),
}
}