Expose span locations on stable
diff --git a/.travis.yml b/.travis.yml
index c3bfa6c..89da724 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,7 @@
script:
- cargo test
- cargo test --no-default-features
+ - cargo test --features span-locations
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
- cargo update -Z minimal-versions && cargo build
@@ -25,6 +26,7 @@
script:
- cargo test
- cargo test --no-default-features
+ - cargo test --features span-locations
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features
diff --git a/Cargo.toml b/Cargo.toml
index 929314e..4d48b66 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,10 @@
proc-macro = []
default = ["proc-macro"]
+# Expose methods Span::start and Span::end which give the line/column location
+# of a token.
+span-locations = []
+
# This feature no longer means anything.
nightly = []
diff --git a/build.rs b/build.rs
index 6973ca7..6c01121 100644
--- a/build.rs
+++ b/build.rs
@@ -31,6 +31,12 @@
// "super_unstable"
// Implement the semver exempt API in terms of the nightly-only proc_macro
// API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
+//
+// "span_locations"
+// Provide methods Span::start and Span::end which give the line/column
+// location of a token. Enabled by procmacro2_semver_exempt or the
+// "span-locations" Cargo cfg. This is behind a cfg because tracking
+// location inside spans is a performance hit.
use std::env;
use std::process::Command;
@@ -50,17 +56,22 @@
println!("cargo:rustc-cfg=u128");
}
- if !enable_use_proc_macro(&target) {
- return;
- }
- println!("cargo:rustc-cfg=use_proc_macro");
-
let semver_exempt = cfg!(procmacro2_semver_exempt);
if semver_exempt {
// https://github.com/alexcrichton/proc-macro2/issues/147
println!("cargo:rustc-cfg=procmacro2_semver_exempt");
}
+ if semver_exempt || cfg!(feature = "span-locations") {
+ println!("cargo:rustc-cfg=span_locations");
+ }
+
+ if !enable_use_proc_macro(&target) {
+ return;
+ }
+
+ println!("cargo:rustc-cfg=use_proc_macro");
+
// Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
if version.nightly || version.minor >= 29 && !semver_exempt {
println!("cargo:rustc-cfg=wrap_proc_macro");
diff --git a/src/fallback.rs b/src/fallback.rs
index 7f3cc4e..928c747 100644
--- a/src/fallback.rs
+++ b/src/fallback.rs
@@ -1,6 +1,4 @@
-#![cfg_attr(not(procmacro2_semver_exempt), allow(dead_code))]
-
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
use std::cell::RefCell;
#[cfg(procmacro2_semver_exempt)]
use std::cmp;
@@ -35,7 +33,7 @@
}
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
fn get_cursor(src: &str) -> Cursor {
// Create a dummy file & add it to the codemap
CODEMAP.with(|cm| {
@@ -49,7 +47,7 @@
})
}
-#[cfg(not(procmacro2_semver_exempt))]
+#[cfg(not(span_locations))]
fn get_cursor(src: &str) -> Cursor {
Cursor { rest: src }
}
@@ -225,27 +223,41 @@
pub column: usize,
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
thread_local! {
static CODEMAP: RefCell<Codemap> = RefCell::new(Codemap {
// NOTE: We start with a single dummy file which all call_site() and
// def_site() spans reference.
- files: vec![FileInfo {
- name: "<unspecified>".to_owned(),
- span: Span { lo: 0, hi: 0 },
- lines: vec![0],
+ files: vec![{
+ #[cfg(procmacro2_semver_exempt)]
+ {
+ FileInfo {
+ name: "<unspecified>".to_owned(),
+ span: Span { lo: 0, hi: 0 },
+ lines: vec![0],
+ }
+ }
+
+ #[cfg(not(procmacro2_semver_exempt))]
+ {
+ FileInfo {
+ span: Span { lo: 0, hi: 0 },
+ lines: vec![0],
+ }
+ }
}],
});
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
struct FileInfo {
+ #[cfg(procmacro2_semver_exempt)]
name: String,
span: Span,
lines: Vec<usize>,
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
impl FileInfo {
fn offset_line_column(&self, offset: usize) -> LineColumn {
assert!(self.span_within(Span {
@@ -271,7 +283,7 @@
}
/// Computesthe offsets of each line in the given source string.
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
fn lines_offsets(s: &str) -> Vec<usize> {
let mut lines = vec![0];
let mut prev = 0;
@@ -282,12 +294,12 @@
lines
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
struct Codemap {
files: Vec<FileInfo>,
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
impl Codemap {
fn next_start_pos(&self) -> u32 {
// Add 1 so there's always space between files.
@@ -306,12 +318,20 @@
hi: lo + (src.len() as u32),
};
+ #[cfg(procmacro2_semver_exempt)]
self.files.push(FileInfo {
name: name.to_owned(),
span: span,
lines: lines,
});
+ #[cfg(not(procmacro2_semver_exempt))]
+ self.files.push(FileInfo {
+ span: span,
+ lines: lines,
+ });
+ let _ = name;
+
span
}
@@ -327,27 +347,29 @@
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Span {
- #[cfg(procmacro2_semver_exempt)]
+ #[cfg(span_locations)]
lo: u32,
- #[cfg(procmacro2_semver_exempt)]
+ #[cfg(span_locations)]
hi: u32,
}
impl Span {
- #[cfg(not(procmacro2_semver_exempt))]
+ #[cfg(not(span_locations))]
pub fn call_site() -> Span {
Span {}
}
- #[cfg(procmacro2_semver_exempt)]
+ #[cfg(span_locations)]
pub fn call_site() -> Span {
Span { lo: 0, hi: 0 }
}
+ #[cfg(procmacro2_semver_exempt)]
pub fn def_site() -> Span {
Span::call_site()
}
+ #[cfg(procmacro2_semver_exempt)]
pub fn resolved_at(&self, _other: Span) -> Span {
// Stable spans consist only of line/column information, so
// `resolved_at` and `located_at` only select which span the
@@ -355,6 +377,7 @@
*self
}
+ #[cfg(procmacro2_semver_exempt)]
pub fn located_at(&self, other: Span) -> Span {
other
}
@@ -370,7 +393,7 @@
})
}
- #[cfg(procmacro2_semver_exempt)]
+ #[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
CODEMAP.with(|cm| {
let cm = cm.borrow();
@@ -379,7 +402,7 @@
})
}
- #[cfg(procmacro2_semver_exempt)]
+ #[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
CODEMAP.with(|cm| {
let cm = cm.borrow();
@@ -448,10 +471,12 @@
self.span
}
+ #[cfg(procmacro2_semver_exempt)]
pub fn span_open(&self) -> Span {
self.span
}
+ #[cfg(procmacro2_semver_exempt)]
pub fn span_close(&self) -> Span {
self.span
}
@@ -788,16 +813,16 @@
Ok((input, TokenStream { inner: trees }))
}
-#[cfg(not(procmacro2_semver_exempt))]
+#[cfg(not(span_locations))]
fn spanned<'a, T>(
input: Cursor<'a>,
f: fn(Cursor<'a>) -> PResult<'a, T>,
) -> PResult<'a, (T, ::Span)> {
let (a, b) = f(skip_whitespace(input))?;
- Ok((a, ((b, ::Span::_new_stable(Span {})))))
+ Ok((a, ((b, ::Span::_new_stable(Span::call_site())))))
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
fn spanned<'a, T>(
input: Cursor<'a>,
f: fn(Cursor<'a>) -> PResult<'a, T>,
diff --git a/src/lib.rs b/src/lib.rs
index 70b25e9..5b96ad3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -80,10 +80,8 @@
// Proc-macro2 types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.26")]
-#![cfg_attr(
- super_unstable,
- feature(proc_macro_raw_ident, proc_macro_span, proc_macro_def_site)
-)]
+#![cfg_attr(nightly, feature(proc_macro_span))]
+#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))]
#[cfg(use_proc_macro)]
extern crate proc_macro;
@@ -302,7 +300,7 @@
/// A line-column pair representing the start or end of a `Span`.
///
/// This type is semver exempt and not exposed by default.
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
pub struct LineColumn {
/// The 1-indexed line in the source file on which the span starts or ends
/// (inclusive).
@@ -401,8 +399,8 @@
/// Get the starting line/column in the source file for this span.
///
- /// This method is semver exempt and not exposed by default.
- #[cfg(procmacro2_semver_exempt)]
+ /// This method requires the `"span-locations"` feature to be enabled.
+ #[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
let imp::LineColumn { line, column } = self.inner.start();
LineColumn {
@@ -413,8 +411,8 @@
/// Get the ending line/column in the source file for this span.
///
- /// This method is semver exempt and not exposed by default.
- #[cfg(procmacro2_semver_exempt)]
+ /// This method requires the `"span-locations"` feature to be enabled.
+ #[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
let imp::LineColumn { line, column } = self.inner.end();
LineColumn {
diff --git a/src/strnom.rs b/src/strnom.rs
index 6f32062..96789d5 100644
--- a/src/strnom.rs
+++ b/src/strnom.rs
@@ -9,18 +9,18 @@
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Cursor<'a> {
pub rest: &'a str,
- #[cfg(procmacro2_semver_exempt)]
+ #[cfg(span_locations)]
pub off: u32,
}
impl<'a> Cursor<'a> {
- #[cfg(not(procmacro2_semver_exempt))]
+ #[cfg(not(span_locations))]
pub fn advance(&self, amt: usize) -> Cursor<'a> {
Cursor {
rest: &self.rest[amt..],
}
}
- #[cfg(procmacro2_semver_exempt)]
+ #[cfg(span_locations)]
pub fn advance(&self, amt: usize) -> Cursor<'a> {
Cursor {
rest: &self.rest[amt..],
diff --git a/src/wrapper.rs b/src/wrapper.rs
index 11d1a3b..c45dff8 100644
--- a/src/wrapper.rs
+++ b/src/wrapper.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(not(super_unstable), allow(dead_code))]
-
use std::fmt;
use std::iter;
use std::panic::{self, PanicInfo};
@@ -413,6 +411,7 @@
}
}
+#[cfg(any(super_unstable, feature = "span-locations"))]
pub struct LineColumn {
pub line: usize,
pub column: usize,
@@ -475,13 +474,16 @@
}
}
- #[cfg(super_unstable)]
+ #[cfg(any(super_unstable, feature = "span-locations"))]
pub fn start(&self) -> LineColumn {
match self {
+ #[cfg(nightly)]
Span::Compiler(s) => {
let proc_macro::LineColumn { line, column } = s.start();
LineColumn { line, column }
}
+ #[cfg(not(nightly))]
+ Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => {
let fallback::LineColumn { line, column } = s.start();
LineColumn { line, column }
@@ -489,13 +491,16 @@
}
}
- #[cfg(super_unstable)]
+ #[cfg(any(super_unstable, feature = "span-locations"))]
pub fn end(&self) -> LineColumn {
match self {
+ #[cfg(nightly)]
Span::Compiler(s) => {
let proc_macro::LineColumn { line, column } = s.end();
LineColumn { line, column }
}
+ #[cfg(not(nightly))]
+ Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => {
let fallback::LineColumn { line, column } = s.end();
LineColumn { line, column }
diff --git a/tests/test.rs b/tests/test.rs
index 6da1283..055ebfd 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -137,7 +137,7 @@
fail("r#_");
}
-#[cfg(procmacro2_semver_exempt)]
+#[cfg(span_locations)]
#[test]
fn span_test() {
use proc_macro2::TokenTree;