Guess semicolon span for macro statements
This commit is contained in:
parent
1333ae67f4
commit
f005e9fe96
2 changed files with 45 additions and 2 deletions
|
@ -653,6 +653,18 @@ impl SourceMap {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extends the given `Span` while the next character matches the predicate
|
||||||
|
pub fn span_extend_while(
|
||||||
|
&self,
|
||||||
|
span: Span,
|
||||||
|
f: impl Fn(char) -> bool,
|
||||||
|
) -> Result<Span, SpanSnippetError> {
|
||||||
|
self.span_to_source(span, |s, _start, end| {
|
||||||
|
let n = s[end..].char_indices().find(|&(_, c)| !f(c)).map_or(s.len() - end, |(i, _)| i);
|
||||||
|
Ok(span.with_hi(span.hi() + BytePos(n as u32)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Extends the given `Span` to just after the next occurrence of `c`.
|
/// Extends the given `Span` to just after the next occurrence of `c`.
|
||||||
pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
|
pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
|
||||||
if let Ok(next_source) = self.span_to_next_source(sp) {
|
if let Ok(next_source) = self.span_to_next_source(sp) {
|
||||||
|
@ -1013,6 +1025,32 @@ impl SourceMap {
|
||||||
let source_file = &self.files()[source_file_index];
|
let source_file = &self.files()[source_file_index];
|
||||||
source_file.is_imported()
|
source_file.is_imported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the span of a statement. If the statement is a macro expansion, the
|
||||||
|
/// span in the context of the block span is found. The trailing semicolon is included
|
||||||
|
/// on a best-effort basis.
|
||||||
|
pub fn stmt_span(&self, stmt_span: Span, block_span: Span) -> Span {
|
||||||
|
if !stmt_span.from_expansion() {
|
||||||
|
return stmt_span;
|
||||||
|
}
|
||||||
|
let mac_call = original_sp(stmt_span, block_span);
|
||||||
|
self.mac_call_stmt_semi_span(mac_call).map_or(mac_call, |s| mac_call.with_hi(s.hi()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to find the span of the semicolon of a macro call statement.
|
||||||
|
/// The input must be the *call site* span of a statement from macro expansion.
|
||||||
|
///
|
||||||
|
/// v output
|
||||||
|
/// mac!();
|
||||||
|
/// ^^^^^^ input
|
||||||
|
pub fn mac_call_stmt_semi_span(&self, mac_call: Span) -> Option<Span> {
|
||||||
|
let span = self.span_extend_while(mac_call, char::is_whitespace).ok()?;
|
||||||
|
let span = span.shrink_to_hi().with_hi(BytePos(span.hi().0.checked_add(1)?));
|
||||||
|
if self.span_to_snippet(span).as_deref() != Ok(";") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(span)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -1171,8 +1171,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let original_span = original_sp(last_stmt.span, blk.span);
|
let span = if last_stmt.span.from_expansion() {
|
||||||
Some((original_span.with_lo(original_span.hi() - BytePos(1)), needs_box))
|
let mac_call = original_sp(last_stmt.span, blk.span);
|
||||||
|
self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
|
||||||
|
} else {
|
||||||
|
last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
|
||||||
|
};
|
||||||
|
Some((span, needs_box))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiates the given path, which must refer to an item with the given
|
// Instantiates the given path, which must refer to an item with the given
|
||||||
|
|
Loading…
Reference in a new issue