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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
use rslint_errors::Diagnostic;
use crate::syntax::expr::EXPR_RECOVERY_SET;
use crate::{CompletedMarker, Parser, SyntaxKind, TokenSet};
use std::collections::HashMap;
use std::ops::{Deref, DerefMut, Range};
#[derive(Debug, Clone, PartialEq)]
pub struct ParserState {
pub allow_object_expr: bool,
pub include_in: bool,
pub continue_allowed: bool,
pub break_allowed: bool,
pub labels: HashMap<String, Range<usize>>,
pub in_generator: bool,
pub in_function: bool,
pub potential_arrow_start: bool,
pub in_async: bool,
pub strict: Option<StrictMode>,
pub is_module: bool,
pub default_item: Option<Range<usize>>,
pub expr_recovery_set: TokenSet,
pub should_record_names: bool,
pub name_map: HashMap<String, Range<usize>>,
pub in_cond_expr: bool,
pub in_case_cond: bool,
pub(crate) no_recovery: bool,
pub in_declare: bool,
pub in_binding_list_for_signature: bool,
pub decorators_were_valid: bool,
pub in_default: bool,
pub for_head_error: Option<Diagnostic>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StrictMode {
Module,
Explicit(Range<usize>),
Class(Range<usize>),
}
impl Default for ParserState {
fn default() -> Self {
Self {
allow_object_expr: true,
include_in: true,
continue_allowed: false,
break_allowed: false,
labels: HashMap::new(),
in_generator: false,
in_function: false,
potential_arrow_start: false,
in_async: false,
strict: None,
is_module: false,
default_item: None,
expr_recovery_set: EXPR_RECOVERY_SET,
name_map: HashMap::with_capacity(3),
should_record_names: false,
in_cond_expr: false,
in_case_cond: false,
no_recovery: false,
in_declare: false,
in_binding_list_for_signature: false,
decorators_were_valid: false,
in_default: false,
for_head_error: None,
}
}
}
impl ParserState {
pub fn check_default(
&mut self,
p: &mut Parser,
mut marker: CompletedMarker,
) -> CompletedMarker {
if let Some(range) = self.default_item.as_ref().filter(|_| self.is_module) {
let err = p
.err_builder("Illegal duplicate default export declarations")
.secondary(
range.to_owned(),
"the module's default export is first defined here",
)
.primary(marker.range(p), "multiple default exports are erroneous");
p.error(err);
marker.change_kind(p, SyntaxKind::ERROR);
} else if self.is_module {
self.default_item = Some(marker.range(p).into());
}
marker
}
pub fn strict(&mut self, p: &mut Parser, range: Range<usize>) {
if let Some(strict) = self.strict.to_owned() {
let mut err = p.warning_builder("Redundant strict mode declaration");
match strict {
StrictMode::Explicit(prev_range) => {
err = err.secondary(prev_range, "strict mode is previous declared here");
}
StrictMode::Module => {
err = err.footer_note("modules are always strict mode");
}
StrictMode::Class(prev_range) => {
err = err.secondary(prev_range, "class bodies are always strict mode");
}
}
err = err.primary(range, "this declaration is redundant");
p.error(err);
} else {
self.strict = Some(StrictMode::Explicit(range));
}
}
}
impl<'t> Parser<'t> {
pub fn with_state<'a>(&'a mut self, state: ParserState) -> StateGuard<'a, 't> {
let original_state = self.state.clone();
self.state = state;
StateGuard {
original_state,
inner: self,
}
}
}
pub struct StateGuard<'p, 't> {
inner: &'p mut Parser<'t>,
original_state: ParserState,
}
impl<'p, 't> Deref for StateGuard<'p, 't> {
type Target = Parser<'t>;
fn deref(&self) -> &Parser<'t> {
self.inner
}
}
impl<'p, 't> DerefMut for StateGuard<'p, 't> {
fn deref_mut(&mut self) -> &mut Parser<'t> {
&mut self.inner
}
}
impl<'p, 't> Drop for StateGuard<'p, 't> {
fn drop(&mut self) {
std::mem::swap(&mut self.inner.state, &mut self.original_state);
}
}