Skip to content

Commit 6cefaec

Browse files
authored
Merge pull request dtolnay#442 from dtolnay/byterange
Expose Span::byte_range
2 parents da1be4d + 1082767 commit 6cefaec

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

build/probe.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66

77
extern crate proc_macro;
88

9-
use core::ops::RangeBounds;
9+
use core::ops::{Range, RangeBounds};
1010
use proc_macro::{Literal, Span};
1111

12+
pub fn byte_range(this: &Span) -> Range<usize> {
13+
this.byte_range()
14+
}
15+
1216
pub fn join(this: &Span, other: Span) -> Option<Span> {
1317
this.join(other)
1418
}

src/fallback.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use core::cell::RefCell;
1111
use core::cmp;
1212
use core::fmt::{self, Debug, Display, Write};
1313
use core::mem::ManuallyDrop;
14+
#[cfg(span_locations)]
15+
use core::ops::Range;
1416
use core::ops::RangeBounds;
1517
use core::ptr;
1618
use core::str::FromStr;
@@ -372,7 +374,7 @@ impl FileInfo {
372374
span.lo >= self.span.lo && span.hi <= self.span.hi
373375
}
374376

375-
fn source_text(&mut self, span: Span) -> String {
377+
fn byte_range(&mut self, span: Span) -> Range<usize> {
376378
let lo_char = (span.lo - self.span.lo) as usize;
377379

378380
// Look up offset of the largest already-computed char index that is
@@ -401,11 +403,15 @@ impl FileInfo {
401403

402404
let trunc_lo = &self.source_text[lo_byte..];
403405
let char_len = (span.hi - span.lo) as usize;
404-
let source_text = match trunc_lo.char_indices().nth(char_len) {
405-
Some((offset, _ch)) => &trunc_lo[..offset],
406-
None => trunc_lo,
407-
};
408-
source_text.to_owned()
406+
lo_byte..match trunc_lo.char_indices().nth(char_len) {
407+
Some((offset, _ch)) => lo_byte + offset,
408+
None => self.source_text.len(),
409+
}
410+
}
411+
412+
fn source_text(&mut self, span: Span) -> String {
413+
let byte_range = self.byte_range(span);
414+
self.source_text[byte_range].to_owned()
409415
}
410416
}
411417

@@ -547,6 +553,21 @@ impl Span {
547553
})
548554
}
549555

556+
#[cfg(span_locations)]
557+
pub fn byte_range(&self) -> Range<usize> {
558+
#[cfg(fuzzing)]
559+
return 0..0;
560+
561+
#[cfg(not(fuzzing))]
562+
{
563+
if self.is_call_site() {
564+
0..0
565+
} else {
566+
SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self))
567+
}
568+
}
569+
}
570+
550571
#[cfg(span_locations)]
551572
pub fn start(&self) -> LineColumn {
552573
#[cfg(fuzzing)]

src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ use crate::marker::{ProcMacroAutoTraits, MARKER};
164164
use core::cmp::Ordering;
165165
use core::fmt::{self, Debug, Display};
166166
use core::hash::{Hash, Hasher};
167+
#[cfg(span_locations)]
168+
use core::ops::Range;
167169
use core::ops::RangeBounds;
168170
use core::str::FromStr;
169171
use std::error::Error;
@@ -472,6 +474,21 @@ impl Span {
472474
SourceFile::_new(self.inner.source_file())
473475
}
474476

477+
/// Returns the span's byte position range in the source file.
478+
///
479+
/// This method requires the `"span-locations"` feature to be enabled.
480+
///
481+
/// When executing in a procedural macro context, the returned range is only
482+
/// accurate if compiled with a nightly toolchain. The stable toolchain does
483+
/// not have this information available. When executing outside of a
484+
/// procedural macro, such as main.rs or build.rs, the byte range is always
485+
/// accurate regardless of toolchain.
486+
#[cfg(span_locations)]
487+
#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))]
488+
pub fn byte_range(&self) -> Range<usize> {
489+
self.inner.byte_range()
490+
}
491+
475492
/// Get the starting line/column in the source file for this span.
476493
///
477494
/// This method requires the `"span-locations"` feature to be enabled.

src/wrapper.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use crate::detection::inside_proc_macro;
33
use crate::location::LineColumn;
44
use crate::{fallback, Delimiter, Punct, Spacing, TokenTree};
55
use core::fmt::{self, Debug, Display};
6+
#[cfg(span_locations)]
7+
use core::ops::Range;
68
use core::ops::RangeBounds;
79
use core::str::FromStr;
810
use std::panic;
@@ -460,6 +462,17 @@ impl Span {
460462
}
461463
}
462464

465+
#[cfg(span_locations)]
466+
pub fn byte_range(&self) -> Range<usize> {
467+
match self {
468+
#[cfg(proc_macro_span)]
469+
Span::Compiler(s) => s.byte_range(),
470+
#[cfg(not(proc_macro_span))]
471+
Span::Compiler(_) => 0..0,
472+
Span::Fallback(s) => s.byte_range(),
473+
}
474+
}
475+
463476
#[cfg(span_locations)]
464477
pub fn start(&self) -> LineColumn {
465478
match self {

0 commit comments

Comments
 (0)