Skip to content

Commit 2b01a3f

Browse files
authored
Merge pull request #166 from dtolnay/location
Expose span locations on stable
2 parents ad8e2e5 + 3b1f7d2 commit 2b01a3f

File tree

8 files changed

+91
-46
lines changed

8 files changed

+91
-46
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ matrix:
1111
script:
1212
- cargo test
1313
- cargo test --no-default-features
14+
- cargo test --features span-locations
1415
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
1516
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
1617
- cargo update -Z minimal-versions && cargo build
@@ -25,6 +26,7 @@ before_script:
2526
script:
2627
- cargo test
2728
- cargo test --no-default-features
29+
- cargo test --features span-locations
2830
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
2931
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
3032

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ quote = "0.6"
2929
proc-macro = []
3030
default = ["proc-macro"]
3131

32+
# Expose methods Span::start and Span::end which give the line/column location
33+
# of a token.
34+
span-locations = []
35+
3236
# This feature no longer means anything.
3337
nightly = []
3438

build.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
// "super_unstable"
3232
// Implement the semver exempt API in terms of the nightly-only proc_macro
3333
// API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
34+
//
35+
// "span_locations"
36+
// Provide methods Span::start and Span::end which give the line/column
37+
// location of a token. Enabled by procmacro2_semver_exempt or the
38+
// "span-locations" Cargo cfg. This is behind a cfg because tracking
39+
// location inside spans is a performance hit.
3440

3541
use std::env;
3642
use std::process::Command;
@@ -50,17 +56,22 @@ fn main() {
5056
println!("cargo:rustc-cfg=u128");
5157
}
5258

53-
if !enable_use_proc_macro(&target) {
54-
return;
55-
}
56-
println!("cargo:rustc-cfg=use_proc_macro");
57-
5859
let semver_exempt = cfg!(procmacro2_semver_exempt);
5960
if semver_exempt {
6061
// https://github.com/alexcrichton/proc-macro2/issues/147
6162
println!("cargo:rustc-cfg=procmacro2_semver_exempt");
6263
}
6364

65+
if semver_exempt || cfg!(feature = "span-locations") {
66+
println!("cargo:rustc-cfg=span_locations");
67+
}
68+
69+
if !enable_use_proc_macro(&target) {
70+
return;
71+
}
72+
73+
println!("cargo:rustc-cfg=use_proc_macro");
74+
6475
// Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
6576
if version.nightly || version.minor >= 29 && !semver_exempt {
6677
println!("cargo:rustc-cfg=wrap_proc_macro");

src/fallback.rs

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))]
2-
3-
#[cfg(procmacro2_semver_exempt)]
1+
#[cfg(span_locations)]
42
use std::cell::RefCell;
53
#[cfg(procmacro2_semver_exempt)]
64
use std::cmp;
@@ -35,7 +33,7 @@ impl TokenStream {
3533
}
3634
}
3735

38-
#[cfg(procmacro2_semver_exempt)]
36+
#[cfg(span_locations)]
3937
fn get_cursor(src: &str) -> Cursor {
4038
// Create a dummy file & add it to the codemap
4139
CODEMAP.with(|cm| {
@@ -49,7 +47,7 @@ fn get_cursor(src: &str) -> Cursor {
4947
})
5048
}
5149

52-
#[cfg(not(procmacro2_semver_exempt))]
50+
#[cfg(not(span_locations))]
5351
fn get_cursor(src: &str) -> Cursor {
5452
Cursor { rest: src }
5553
}
@@ -225,27 +223,41 @@ pub struct LineColumn {
225223
pub column: usize,
226224
}
227225

228-
#[cfg(procmacro2_semver_exempt)]
226+
#[cfg(span_locations)]
229227
thread_local! {
230228
static CODEMAP: RefCell<Codemap> = RefCell::new(Codemap {
231229
// NOTE: We start with a single dummy file which all call_site() and
232230
// def_site() spans reference.
233-
files: vec![FileInfo {
234-
name: "<unspecified>".to_owned(),
235-
span: Span { lo: 0, hi: 0 },
236-
lines: vec![0],
231+
files: vec![{
232+
#[cfg(procmacro2_semver_exempt)]
233+
{
234+
FileInfo {
235+
name: "<unspecified>".to_owned(),
236+
span: Span { lo: 0, hi: 0 },
237+
lines: vec![0],
238+
}
239+
}
240+
241+
#[cfg(not(procmacro2_semver_exempt))]
242+
{
243+
FileInfo {
244+
span: Span { lo: 0, hi: 0 },
245+
lines: vec![0],
246+
}
247+
}
237248
}],
238249
});
239250
}
240251

241-
#[cfg(procmacro2_semver_exempt)]
252+
#[cfg(span_locations)]
242253
struct FileInfo {
254+
#[cfg(procmacro2_semver_exempt)]
243255
name: String,
244256
span: Span,
245257
lines: Vec<usize>,
246258
}
247259

248-
#[cfg(procmacro2_semver_exempt)]
260+
#[cfg(span_locations)]
249261
impl FileInfo {
250262
fn offset_line_column(&self, offset: usize) -> LineColumn {
251263
assert!(self.span_within(Span {
@@ -271,7 +283,7 @@ impl FileInfo {
271283
}
272284

273285
/// Computesthe offsets of each line in the given source string.
274-
#[cfg(procmacro2_semver_exempt)]
286+
#[cfg(span_locations)]
275287
fn lines_offsets(s: &str) -> Vec<usize> {
276288
let mut lines = vec![0];
277289
let mut prev = 0;
@@ -282,12 +294,12 @@ fn lines_offsets(s: &str) -> Vec<usize> {
282294
lines
283295
}
284296

285-
#[cfg(procmacro2_semver_exempt)]
297+
#[cfg(span_locations)]
286298
struct Codemap {
287299
files: Vec<FileInfo>,
288300
}
289301

290-
#[cfg(procmacro2_semver_exempt)]
302+
#[cfg(span_locations)]
291303
impl Codemap {
292304
fn next_start_pos(&self) -> u32 {
293305
// Add 1 so there's always space between files.
@@ -306,12 +318,20 @@ impl Codemap {
306318
hi: lo + (src.len() as u32),
307319
};
308320

321+
#[cfg(procmacro2_semver_exempt)]
309322
self.files.push(FileInfo {
310323
name: name.to_owned(),
311324
span: span,
312325
lines: lines,
313326
});
314327

328+
#[cfg(not(procmacro2_semver_exempt))]
329+
self.files.push(FileInfo {
330+
span: span,
331+
lines: lines,
332+
});
333+
let _ = name;
334+
315335
span
316336
}
317337

@@ -327,34 +347,37 @@ impl Codemap {
327347

328348
#[derive(Clone, Copy, PartialEq, Eq)]
329349
pub struct Span {
330-
#[cfg(procmacro2_semver_exempt)]
350+
#[cfg(span_locations)]
331351
lo: u32,
332-
#[cfg(procmacro2_semver_exempt)]
352+
#[cfg(span_locations)]
333353
hi: u32,
334354
}
335355

336356
impl Span {
337-
#[cfg(not(procmacro2_semver_exempt))]
357+
#[cfg(not(span_locations))]
338358
pub fn call_site() -> Span {
339359
Span {}
340360
}
341361

342-
#[cfg(procmacro2_semver_exempt)]
362+
#[cfg(span_locations)]
343363
pub fn call_site() -> Span {
344364
Span { lo: 0, hi: 0 }
345365
}
346366

367+
#[cfg(procmacro2_semver_exempt)]
347368
pub fn def_site() -> Span {
348369
Span::call_site()
349370
}
350371

372+
#[cfg(procmacro2_semver_exempt)]
351373
pub fn resolved_at(&self, _other: Span) -> Span {
352374
// Stable spans consist only of line/column information, so
353375
// `resolved_at` and `located_at` only select which span the
354376
// caller wants line/column information from.
355377
*self
356378
}
357379

380+
#[cfg(procmacro2_semver_exempt)]
358381
pub fn located_at(&self, other: Span) -> Span {
359382
other
360383
}
@@ -370,7 +393,7 @@ impl Span {
370393
})
371394
}
372395

373-
#[cfg(procmacro2_semver_exempt)]
396+
#[cfg(span_locations)]
374397
pub fn start(&self) -> LineColumn {
375398
CODEMAP.with(|cm| {
376399
let cm = cm.borrow();
@@ -379,7 +402,7 @@ impl Span {
379402
})
380403
}
381404

382-
#[cfg(procmacro2_semver_exempt)]
405+
#[cfg(span_locations)]
383406
pub fn end(&self) -> LineColumn {
384407
CODEMAP.with(|cm| {
385408
let cm = cm.borrow();
@@ -448,10 +471,12 @@ impl Group {
448471
self.span
449472
}
450473

474+
#[cfg(procmacro2_semver_exempt)]
451475
pub fn span_open(&self) -> Span {
452476
self.span
453477
}
454478

479+
#[cfg(procmacro2_semver_exempt)]
455480
pub fn span_close(&self) -> Span {
456481
self.span
457482
}
@@ -788,16 +813,16 @@ fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
788813
Ok((input, TokenStream { inner: trees }))
789814
}
790815

791-
#[cfg(not(procmacro2_semver_exempt))]
816+
#[cfg(not(span_locations))]
792817
fn spanned<'a, T>(
793818
input: Cursor<'a>,
794819
f: fn(Cursor<'a>) -> PResult<'a, T>,
795820
) -> PResult<'a, (T, ::Span)> {
796821
let (a, b) = f(skip_whitespace(input))?;
797-
Ok((a, ((b, ::Span::_new_stable(Span {})))))
822+
Ok((a, ((b, ::Span::_new_stable(Span::call_site())))))
798823
}
799824

800-
#[cfg(procmacro2_semver_exempt)]
825+
#[cfg(span_locations)]
801826
fn spanned<'a, T>(
802827
input: Cursor<'a>,
803828
f: fn(Cursor<'a>) -> PResult<'a, T>,

src/lib.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,8 @@
8080
8181
// Proc-macro2 types in rustdoc of other crates get linked to here.
8282
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.26")]
83-
#![cfg_attr(
84-
super_unstable,
85-
feature(proc_macro_raw_ident, proc_macro_span, proc_macro_def_site)
86-
)]
83+
#![cfg_attr(nightly, feature(proc_macro_span))]
84+
#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))]
8785

8886
#[cfg(use_proc_macro)]
8987
extern crate proc_macro;
@@ -302,7 +300,7 @@ impl fmt::Debug for SourceFile {
302300
/// A line-column pair representing the start or end of a `Span`.
303301
///
304302
/// This type is semver exempt and not exposed by default.
305-
#[cfg(procmacro2_semver_exempt)]
303+
#[cfg(span_locations)]
306304
pub struct LineColumn {
307305
/// The 1-indexed line in the source file on which the span starts or ends
308306
/// (inclusive).
@@ -401,8 +399,8 @@ impl Span {
401399

402400
/// Get the starting line/column in the source file for this span.
403401
///
404-
/// This method is semver exempt and not exposed by default.
405-
#[cfg(procmacro2_semver_exempt)]
402+
/// This method requires the `"span-locations"` feature to be enabled.
403+
#[cfg(span_locations)]
406404
pub fn start(&self) -> LineColumn {
407405
let imp::LineColumn { line, column } = self.inner.start();
408406
LineColumn {
@@ -413,8 +411,8 @@ impl Span {
413411

414412
/// Get the ending line/column in the source file for this span.
415413
///
416-
/// This method is semver exempt and not exposed by default.
417-
#[cfg(procmacro2_semver_exempt)]
414+
/// This method requires the `"span-locations"` feature to be enabled.
415+
#[cfg(span_locations)]
418416
pub fn end(&self) -> LineColumn {
419417
let imp::LineColumn { line, column } = self.inner.end();
420418
LineColumn {

src/strnom.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ use fallback::LexError;
99
#[derive(Copy, Clone, Eq, PartialEq)]
1010
pub struct Cursor<'a> {
1111
pub rest: &'a str,
12-
#[cfg(procmacro2_semver_exempt)]
12+
#[cfg(span_locations)]
1313
pub off: u32,
1414
}
1515

1616
impl<'a> Cursor<'a> {
17-
#[cfg(not(procmacro2_semver_exempt))]
17+
#[cfg(not(span_locations))]
1818
pub fn advance(&self, amt: usize) -> Cursor<'a> {
1919
Cursor {
2020
rest: &self.rest[amt..],
2121
}
2222
}
23-
#[cfg(procmacro2_semver_exempt)]
23+
#[cfg(span_locations)]
2424
pub fn advance(&self, amt: usize) -> Cursor<'a> {
2525
Cursor {
2626
rest: &self.rest[amt..],

src/wrapper.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![cfg_attr(not(super_unstable), allow(dead_code))]
2-
31
use std::fmt;
42
use std::iter;
53
use std::panic::{self, PanicInfo};
@@ -413,6 +411,7 @@ impl fmt::Debug for SourceFile {
413411
}
414412
}
415413

414+
#[cfg(any(super_unstable, feature = "span-locations"))]
416415
pub struct LineColumn {
417416
pub line: usize,
418417
pub column: usize,
@@ -475,27 +474,33 @@ impl Span {
475474
}
476475
}
477476

478-
#[cfg(super_unstable)]
477+
#[cfg(any(super_unstable, feature = "span-locations"))]
479478
pub fn start(&self) -> LineColumn {
480479
match self {
480+
#[cfg(nightly)]
481481
Span::Compiler(s) => {
482482
let proc_macro::LineColumn { line, column } = s.start();
483483
LineColumn { line, column }
484484
}
485+
#[cfg(not(nightly))]
486+
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
485487
Span::Fallback(s) => {
486488
let fallback::LineColumn { line, column } = s.start();
487489
LineColumn { line, column }
488490
}
489491
}
490492
}
491493

492-
#[cfg(super_unstable)]
494+
#[cfg(any(super_unstable, feature = "span-locations"))]
493495
pub fn end(&self) -> LineColumn {
494496
match self {
497+
#[cfg(nightly)]
495498
Span::Compiler(s) => {
496499
let proc_macro::LineColumn { line, column } = s.end();
497500
LineColumn { line, column }
498501
}
502+
#[cfg(not(nightly))]
503+
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
499504
Span::Fallback(s) => {
500505
let fallback::LineColumn { line, column } = s.end();
501506
LineColumn { line, column }

0 commit comments

Comments
 (0)