Reserve retained parser entries at private producer boundaries
This commit is contained in:
@@ -1028,6 +1028,18 @@ fn edit_positions_from_tokens_with_text(
|
||||
count: usize,
|
||||
value_ends: Option<&BTreeMap<usize, usize>>,
|
||||
text: impl FnMut(usize, Span) -> Result<(), Box<Diagnostic>>,
|
||||
) -> Result<Vec<(Id, EditDeclaration)>, Box<Diagnostic>> {
|
||||
edit_positions_from_tokens_with_producers(source, unit, token, count, value_ends, None, text)
|
||||
}
|
||||
|
||||
fn edit_positions_from_tokens_with_producers(
|
||||
source: &str,
|
||||
unit: &SourceUnit,
|
||||
token: impl Fn(usize) -> Lexeme,
|
||||
count: usize,
|
||||
value_ends: Option<&BTreeMap<usize, usize>>,
|
||||
mut quota: Option<usize>,
|
||||
text: impl FnMut(usize, Span) -> Result<(), Box<Diagnostic>>,
|
||||
) -> Result<Vec<(Id, EditDeclaration)>, Box<Diagnostic>> {
|
||||
let mut ends: Vec<_> = (0..count).map(|at| token(at).span.end).collect();
|
||||
let mut stack = Vec::new();
|
||||
@@ -1044,10 +1056,27 @@ fn edit_positions_from_tokens_with_text(
|
||||
ends: Vec<usize>,
|
||||
value_ends: Option<&'a BTreeMap<usize, usize>>,
|
||||
text: H,
|
||||
source: &'a str,
|
||||
quota: &'a mut Option<usize>,
|
||||
}
|
||||
impl<F: Fn(usize) -> Lexeme, H: FnMut(usize, Span) -> Result<(), Box<Diagnostic>>>
|
||||
Positions<'_, F, H>
|
||||
{
|
||||
fn consume(&mut self, slots: usize, offset: usize) -> Result<(), Box<Diagnostic>> {
|
||||
if let Some(remaining) = self.quota {
|
||||
*remaining = remaining.checked_sub(slots).ok_or_else(|| {
|
||||
Box::new(diagnostic(
|
||||
self.source,
|
||||
Error {
|
||||
code: "invalid_source",
|
||||
offset,
|
||||
message: "Source8 projection quota underflow.".into(),
|
||||
},
|
||||
))
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn token(&self, start: usize) -> usize {
|
||||
let mut low = 0;
|
||||
let mut high = self.ends.len();
|
||||
@@ -1068,6 +1097,7 @@ fn edit_positions_from_tokens_with_text(
|
||||
fields
|
||||
.iter()
|
||||
.map(|(key, ast)| {
|
||||
self.consume(1, ast.offset())?;
|
||||
let value = self.value(ast)?;
|
||||
let start = (self.token_at)(self.token(value.span.start) - 1).span.start;
|
||||
let end = (self.token_at)(self.token(value.span.end)).span.end;
|
||||
@@ -1083,6 +1113,7 @@ fn edit_positions_from_tokens_with_text(
|
||||
.collect()
|
||||
}
|
||||
fn value(&mut self, ast: &Ast) -> Result<EditValue, Box<Diagnostic>> {
|
||||
self.consume(1, ast.offset())?;
|
||||
let index = self.token(ast.offset());
|
||||
let span = Span {
|
||||
start: ast.offset(),
|
||||
@@ -1119,8 +1150,11 @@ fn edit_positions_from_tokens_with_text(
|
||||
ends,
|
||||
value_ends,
|
||||
text,
|
||||
source,
|
||||
quota: &mut quota,
|
||||
};
|
||||
unit.declarations
|
||||
let result = unit
|
||||
.declarations
|
||||
.iter()
|
||||
.map(|declaration| {
|
||||
if declaration.id_insertion.is_some() {
|
||||
@@ -1133,6 +1167,7 @@ fn edit_positions_from_tokens_with_text(
|
||||
},
|
||||
)));
|
||||
}
|
||||
positions.consume(7, declaration.span.start)?;
|
||||
let roles: &[&str] = if matches!(declaration.kind, DeclKind::Node) {
|
||||
&["kind", "alias", "id_keyword", "id"]
|
||||
} else {
|
||||
@@ -1161,7 +1196,18 @@ fn edit_positions_from_tokens_with_text(
|
||||
},
|
||||
))
|
||||
})
|
||||
.collect()
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
if quota.is_some_and(|remaining| remaining != 0) {
|
||||
return Err(Box::new(diagnostic(
|
||||
source,
|
||||
Error {
|
||||
code: "invalid_source",
|
||||
offset: 0,
|
||||
message: "Source8 projection quota leftover.".into(),
|
||||
},
|
||||
)));
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
struct Parser<'a> {
|
||||
source: &'a str,
|
||||
@@ -1337,6 +1383,10 @@ impl Parser<'_> {
|
||||
.span
|
||||
.end;
|
||||
self.take(";")?;
|
||||
#[cfg(test)]
|
||||
if let Some(mixed) = &mut self.mixed {
|
||||
mixed.projection(1, Span { start, end })?;
|
||||
}
|
||||
Ok((key, value, Span { start, end }))
|
||||
}
|
||||
|
||||
@@ -1370,7 +1420,12 @@ impl Parser<'_> {
|
||||
.span
|
||||
.end;
|
||||
if let Some(mixed) = &mut self.mixed {
|
||||
mixed.value_ends.insert(ast.offset(), end);
|
||||
let span = Span {
|
||||
start: ast.offset(),
|
||||
end,
|
||||
};
|
||||
mixed.value_end(span)?;
|
||||
mixed.projection(1, span)?;
|
||||
}
|
||||
}
|
||||
result
|
||||
@@ -1697,7 +1752,12 @@ impl Parser<'_> {
|
||||
let lexical_owner = open.last().map(|&owner| declarations[owner].id);
|
||||
#[cfg(test)]
|
||||
if let Some(mixed) = &mut self.mixed {
|
||||
mixed.lexical_owners.push(open.last().copied());
|
||||
let span = Span {
|
||||
start: offset,
|
||||
end: body_start,
|
||||
};
|
||||
mixed.lexical_owner(open.last().copied(), span)?;
|
||||
mixed.projection(7, span)?;
|
||||
}
|
||||
declarations.push(Declaration {
|
||||
kind,
|
||||
|
||||
Reference in New Issue
Block a user