From 67c6cbaf162f6244dbf4a87dc829975278590df9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Sep 2022 15:20:56 -0700 Subject: [PATCH 1/2] Expose proc_macro's source_text() on Span --- build.rs | 4 ++++ src/fallback.rs | 19 +++++++++++++++++++ src/lib.rs | 11 +++++++++++ src/wrapper.rs | 10 ++++++++++ 4 files changed, 44 insertions(+) diff --git a/build.rs b/build.rs index b69d813f..59505a50 100644 --- a/build.rs +++ b/build.rs @@ -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; diff --git a/src/fallback.rs b/src/fallback.rs index fc3cd515..36064cef 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -342,6 +342,7 @@ thread_local! { files: vec![FileInfo { #[cfg(procmacro2_semver_exempt)] name: "".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, } @@ -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 { + None + } + + #[cfg(span_locations)] + pub fn source_text(&self) -> Option { + SOURCE_MAP.with(|cm| Some(cm.borrow().fileinfo(*self).source_text(*self))) + } + #[cfg(not(span_locations))] pub(crate) fn first_byte(self) -> Self { self diff --git a/src/lib.rs b/src/lib.rs index 4eb756bc..83e99ce4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { + self.inner.source_text() + } } /// Prints a span in a form convenient for debugging. diff --git a/src/wrapper.rs b/src/wrapper.rs index 720dcdd3..00f67cd6 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -530,6 +530,16 @@ impl Span { } } + pub fn source_text(&self) -> Option { + 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, From efeb5eceb10e7a0a501f7f3f43d7ba06c1d23d2a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 21 Mar 2023 22:44:33 -0700 Subject: [PATCH 2/2] Call site has no source text --- src/fallback.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/fallback.rs b/src/fallback.rs index 36064cef..b0ed7b06 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -570,7 +570,11 @@ impl Span { #[cfg(span_locations)] pub fn source_text(&self) -> Option { - SOURCE_MAP.with(|cm| Some(cm.borrow().fileinfo(*self).source_text(*self))) + if self.is_call_site() { + None + } else { + Some(SOURCE_MAP.with(|cm| cm.borrow().fileinfo(*self).source_text(*self))) + } } #[cfg(not(span_locations))] @@ -598,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 { @@ -613,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; } }