Expose proc_macro's source_text() on Span

This commit is contained in:
David Tolnay 2022-09-24 15:20:56 -07:00
parent ab254879e7
commit 67c6cbaf16
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
4 changed files with 44 additions and 0 deletions

View File

@ -100,6 +100,10 @@ fn main() {
println!("cargo:rustc-cfg=no_is_available");
}
if version.minor < 66 {
println!("cargo:rustc-cfg=no_source_text");
}
let target = env::var("TARGET").unwrap();
if !enable_use_proc_macro(&target) {
return;

View File

@ -342,6 +342,7 @@ thread_local! {
files: vec![FileInfo {
#[cfg(procmacro2_semver_exempt)]
name: "<unspecified>".to_owned(),
source_text: String::new(),
span: Span { lo: 0, hi: 0 },
lines: vec![0],
}],
@ -352,6 +353,7 @@ thread_local! {
struct FileInfo {
#[cfg(procmacro2_semver_exempt)]
name: String,
source_text: String,
span: Span,
lines: Vec<usize>,
}
@ -379,6 +381,12 @@ impl FileInfo {
fn span_within(&self, span: Span) -> bool {
span.lo >= self.span.lo && span.hi <= self.span.hi
}
fn source_text(&self, span: Span) -> String {
let lo = (span.lo - self.span.lo) as usize;
let hi = (span.hi - self.span.lo) as usize;
self.source_text[lo..hi].to_owned()
}
}
/// Computes the offsets of each line in the given source string
@ -425,6 +433,7 @@ impl SourceMap {
self.files.push(FileInfo {
#[cfg(procmacro2_semver_exempt)]
name: name.to_owned(),
source_text: src.to_owned(),
span,
lines,
});
@ -554,6 +563,16 @@ impl Span {
})
}
#[cfg(not(span_locations))]
pub fn source_text(&self) -> Option<String> {
None
}
#[cfg(span_locations)]
pub fn source_text(&self) -> Option<String> {
SOURCE_MAP.with(|cm| Some(cm.borrow().fileinfo(*self).source_text(*self)))
}
#[cfg(not(span_locations))]
pub(crate) fn first_byte(self) -> Self {
self

View File

@ -528,6 +528,17 @@ impl Span {
pub fn eq(&self, other: &Span) -> bool {
self.inner.eq(&other.inner)
}
/// Returns the source text behind a span. This preserves the original
/// source code, including spaces and comments. It only returns a result if
/// the span corresponds to real source code.
///
/// Note: The observable result of a macro should only rely on the tokens
/// and not on this source text. The result of this function is a best
/// effort to be used for diagnostics only.
pub fn source_text(&self) -> Option<String> {
self.inner.source_text()
}
}
/// Prints a span in a form convenient for debugging.

View File

@ -530,6 +530,16 @@ impl Span {
}
}
pub fn source_text(&self) -> Option<String> {
match self {
#[cfg(not(no_source_text))]
Span::Compiler(s) => s.source_text(),
#[cfg(no_source_text)]
Span::Compiler(_) => None,
Span::Fallback(s) => s.source_text(),
}
}
fn unwrap_nightly(self) -> proc_macro::Span {
match self {
Span::Compiler(s) => s,