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
macro_rules! check_mods {
($errors:ident, $context:expr, $actual:ident, [$($allowed:ident),*] ) => {{
let allowed_mods = [$(Keyword::$allowed),*];
$errors.extend_from_slice(
&check_allowed_modifier(&$actual, &allowed_mods, $context)
);
}}
}
pub mod java8;
use ast;
use lex;
use base::diag::Report;
use base::code::{Span, BytePos};
type Mods = [ast::Spanned<lex::Keyword>];
fn check_allowed_modifier(actual: &Mods, allowed: &[lex::Keyword], ctx: &str)
-> Vec<Report>
{
let mut seen: Vec<ast::Spanned<lex::Keyword>> = Vec::new();
actual.iter().flat_map(|&m| {
let mut reps = Vec::new();
let dupe = seen
.iter()
.find(|hay| hay.inner == m.inner)
.map(|m| m.span);
if let Some(prev_span) = dupe {
reps.push(Report::simple_error(
format!("duplicate `{:?}` modifier", m.inner),
m.span,
).with_span_note(
format!("the first `{:?}` modifier is already here", m.inner),
prev_span,
));
} else {
seen.push(m);
}
if !allowed.contains(&m.inner) {
let msg = format!("modifier `{}` is illegal in this context", m.inner);
let note = format!("valid `{}` modifier are: {:?}", ctx, allowed);
reps.push(Report::simple_error(msg, m.span).with_note(note));
}
reps.into_iter()
}).collect()
}
fn get_visibility(mods: &Mods, errors: &mut Vec<Report>)
-> Option<ast::Visibility>
{
use lex::Keyword;
let mut vis = None;
let mut first_vis = None;
for &ast::Spanned { inner: modifier, span } in mods {
match modifier {
Keyword::Public | Keyword::Private | Keyword::Protected => {
if let Some(prev_span) = first_vis {
let e = Report::simple_error(
"duplicate visibility modifier",
span
).with_span_note(
"the first visibility modifier is already here",
prev_span
);
errors.push(e);
} else {
first_vis = Some(span);
vis = Some(match modifier {
Keyword::Public => ast::Visibility::Public,
Keyword::Private => ast::Visibility::Private,
Keyword::Protected => ast::Visibility::Protected,
_ => unreachable!(),
});
}
},
_ => {},
}
}
vis
}
macro_rules! gen_finder {
($name:ident, $keyword:ident) => {
fn $name(mods: &Mods) -> Option<Span> {
mods.iter()
.find(|m| m.inner == lex::Keyword::$keyword)
.map(|m| m.span)
}
}
}
gen_finder!(get_abstract, Abstract);
gen_finder!(get_default, Default);
gen_finder!(get_final, Final);
gen_finder!(get_native, Native);
gen_finder!(get_static, Static);
gen_finder!(get_strictfp, Strictfp);
gen_finder!(get_synchronized, Synchronized);
fn unwrap_keyword(tok: &lex::Token) -> lex::Keyword {
if let &lex::Token::KeyW(kw) = tok { kw } else { unreachable!() }
}