Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose span locations on stable #166

Merged
merged 1 commit into from
Jan 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ matrix:
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
Expand All @@ -25,6 +26,7 @@ before_script:
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

Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ quote = "0.6"
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 = []

Expand Down
21 changes: 16 additions & 5 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -50,17 +56,22 @@ fn main() {
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");
Expand Down
73 changes: 49 additions & 24 deletions src/fallback.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -35,7 +33,7 @@ impl TokenStream {
}
}

#[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| {
Expand All @@ -49,7 +47,7 @@ fn get_cursor(src: &str) -> Cursor {
})
}

#[cfg(not(procmacro2_semver_exempt))]
#[cfg(not(span_locations))]
fn get_cursor(src: &str) -> Cursor {
Cursor { rest: src }
}
Expand Down Expand Up @@ -225,27 +223,41 @@ pub struct LineColumn {
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 {
Expand All @@ -271,7 +283,7 @@ impl FileInfo {
}

/// 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;
Expand All @@ -282,12 +294,12 @@ fn lines_offsets(s: &str) -> Vec<usize> {
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.
Expand All @@ -306,12 +318,20 @@ impl Codemap {
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
}

Expand All @@ -327,34 +347,37 @@ impl Codemap {

#[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
// caller wants line/column information from.
*self
}

#[cfg(procmacro2_semver_exempt)]
pub fn located_at(&self, other: Span) -> Span {
other
}
Expand All @@ -370,7 +393,7 @@ impl Span {
})
}

#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
CODEMAP.with(|cm| {
let cm = cm.borrow();
Expand All @@ -379,7 +402,7 @@ impl Span {
})
}

#[cfg(procmacro2_semver_exempt)]
#[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
CODEMAP.with(|cm| {
let cm = cm.borrow();
Expand Down Expand Up @@ -448,10 +471,12 @@ impl Group {
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
}
Expand Down Expand Up @@ -788,16 +813,16 @@ fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
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>,
Expand Down
16 changes: 7 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -302,7 +300,7 @@ impl fmt::Debug for SourceFile {
/// 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).
Expand Down Expand Up @@ -401,8 +399,8 @@ impl Span {

/// 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 {
Expand All @@ -413,8 +411,8 @@ impl Span {

/// 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 {
Expand Down
6 changes: 3 additions & 3 deletions src/strnom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ use fallback::LexError;
#[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..],
Expand Down
13 changes: 9 additions & 4 deletions src/wrapper.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![cfg_attr(not(super_unstable), allow(dead_code))]

use std::fmt;
use std::iter;
use std::panic::{self, PanicInfo};
Expand Down Expand Up @@ -413,6 +411,7 @@ impl fmt::Debug for SourceFile {
}
}

#[cfg(any(super_unstable, feature = "span-locations"))]
pub struct LineColumn {
pub line: usize,
pub column: usize,
Expand Down Expand Up @@ -475,27 +474,33 @@ impl Span {
}
}

#[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 }
}
}
}

#[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 }
Expand Down
Loading