Skip to content

Commit

Permalink
Merge pull request #350 from dtolnay/sourcetext
Browse files Browse the repository at this point in the history
Expose proc_macro's source_text() on Span
  • Loading branch information
dtolnay committed Mar 22, 2023
2 parents ab25487 + efeb5ec commit b88dc25
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 1 deletion.
4 changes: 4 additions & 0 deletions build.rs
Expand Up @@ -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;
Expand Down
30 changes: 29 additions & 1 deletion src/fallback.rs
Expand Up @@ -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],
}],
Expand All @@ -352,6 +353,7 @@ thread_local! {
struct FileInfo {
#[cfg(procmacro2_semver_exempt)]
name: String,
source_text: String,
span: Span,
lines: Vec<usize>,
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
});
Expand Down Expand Up @@ -554,6 +563,20 @@ impl Span {
})
}

#[cfg(not(span_locations))]
pub fn source_text(&self) -> Option<String> {
None
}

#[cfg(span_locations)]
pub fn source_text(&self) -> Option<String> {
if self.is_call_site() {
None
} else {
Some(SOURCE_MAP.with(|cm| cm.borrow().fileinfo(*self).source_text(*self)))
}
}

#[cfg(not(span_locations))]
pub(crate) fn first_byte(self) -> Self {
self
Expand All @@ -579,6 +602,11 @@ impl Span {
hi: self.hi,
}
}

#[cfg(span_locations)]
fn is_call_site(&self) -> bool {
self.lo == 0 && self.hi == 0
}
}

impl Debug for Span {
Expand All @@ -594,7 +622,7 @@ impl Debug for Span {
pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
#[cfg(span_locations)]
{
if span.lo == 0 && span.hi == 0 {
if span.is_call_site() {
return;
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/lib.rs
Expand Up @@ -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.
Expand Down
10 changes: 10 additions & 0 deletions src/wrapper.rs
Expand Up @@ -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,
Expand Down

0 comments on commit b88dc25

Please sign in to comment.