From 50fcd454c71084cb682f4d908b06cdd3eddacaf9 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 3 Aug 2021 00:46:10 +0200 Subject: [PATCH 1/3] Make columns 1 based --- library/proc_macro/src/lib.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 8138c3882fc14..793d35a28a2c0 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -348,13 +348,13 @@ impl Span { /// Gets the starting line/column in the source file for this span. #[unstable(feature = "proc_macro_span", issue = "54725")] pub fn start(&self) -> LineColumn { - self.0.start() + self.0.start().add_1_to_column() } /// Gets the ending line/column in the source file for this span. #[unstable(feature = "proc_macro_span", issue = "54725")] pub fn end(&self) -> LineColumn { - self.0.end() + self.0.end().add_1_to_column() } /// Creates a new span encompassing `self` and `other`. @@ -432,12 +432,18 @@ pub struct LineColumn { /// The 1-indexed line in the source file on which the span starts or ends (inclusive). #[unstable(feature = "proc_macro_span", issue = "54725")] pub line: usize, - /// The 0-indexed column (in UTF-8 characters) in the source file on which + /// The 1-indexed column (in UTF-8 characters) in the source file on which /// the span starts or ends (inclusive). #[unstable(feature = "proc_macro_span", issue = "54725")] pub column: usize, } +impl LineColumn { + fn add_1_to_column(self) -> Self { + LineColumn { line: self.line, column: self.column + 1 } + } +} + #[unstable(feature = "proc_macro_span", issue = "54725")] impl !Send for LineColumn {} #[unstable(feature = "proc_macro_span", issue = "54725")] From 5d7b6595ceed4edb77a558a340f73120610d76fe Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 3 Aug 2021 02:41:39 +0200 Subject: [PATCH 2/3] Add tests --- .../proc-macro/auxiliary/assert-span-pos.rs | 37 +++++++++++++++++++ .../proc-macro/span-absolute-posititions.rs | 16 ++++++++ .../span-absolute-posititions.stderr | 14 +++++++ 3 files changed, 67 insertions(+) create mode 100644 src/test/ui/proc-macro/auxiliary/assert-span-pos.rs create mode 100644 src/test/ui/proc-macro/span-absolute-posititions.rs create mode 100644 src/test/ui/proc-macro/span-absolute-posititions.stderr diff --git a/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs b/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs new file mode 100644 index 0000000000000..455c5c7c380af --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs @@ -0,0 +1,37 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_diagnostic, proc_macro_span)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span}; + +fn lit_span(tt: TokenTree) -> (Span, String) { + match tt { + TokenTree::Literal(..) | + TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()), + _ => panic!("expected a literal in token tree, got: {:?}", tt) + } +} + +#[proc_macro] +pub fn assert_span_pos(input: TokenStream) -> TokenStream { + let mut tokens = input.into_iter(); + let (sp1, str1) = lit_span(tokens.next().expect("first argument")); + let _ = tokens.next(); + let (_sp2, str2) = lit_span(tokens.next().expect("second argument")); + + let line: usize = str1.parse().unwrap(); + let col: usize = str2.parse().unwrap(); + + let sp1s = sp1.start(); + if (line, col) != (sp1s.line, sp1s.column) { + let msg = format!("line/column mismatch: ({}, {}) != ({}, {})", line, col, + sp1s.line, sp1s.column); + sp1.error(msg).emit(); + } + + "".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/span-absolute-posititions.rs b/src/test/ui/proc-macro/span-absolute-posititions.rs new file mode 100644 index 0000000000000..7fc3f6b5793bc --- /dev/null +++ b/src/test/ui/proc-macro/span-absolute-posititions.rs @@ -0,0 +1,16 @@ +// aux-build:assert-span-pos.rs +// ignore-tidy-tab +extern crate assert_span_pos; + +assert_span_pos::assert_span_pos!(5, 35); + +// Test space indentation + assert_span_pos::assert_span_pos!(8, 39); +// Test tab indentation + assert_span_pos::assert_span_pos!(10, 36); + +// Test that the macro actually emits an error on a mismatch: +assert_span_pos::assert_span_pos!(0, 35); //~ ERROR line/column mismatch: (0, 35) != (13, 35) +assert_span_pos::assert_span_pos!(14, 0); //~ ERROR line/column mismatch: (14, 0) != (14, 35) + +fn main() {} diff --git a/src/test/ui/proc-macro/span-absolute-posititions.stderr b/src/test/ui/proc-macro/span-absolute-posititions.stderr new file mode 100644 index 0000000000000..ade66417520d6 --- /dev/null +++ b/src/test/ui/proc-macro/span-absolute-posititions.stderr @@ -0,0 +1,14 @@ +error: line/column mismatch: (0, 35) != (13, 35) + --> $DIR/span-absolute-posititions.rs:13:35 + | +LL | assert_span_pos::assert_span_pos!(0, 35); + | ^ + +error: line/column mismatch: (14, 0) != (14, 35) + --> $DIR/span-absolute-posititions.rs:14:35 + | +LL | assert_span_pos::assert_span_pos!(14, 0); + | ^^ + +error: aborting due to 2 previous errors + From 7d20789c0225160e99267b81c5431e3f75cf5421 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 3 Aug 2021 03:33:05 +0200 Subject: [PATCH 3/3] Make the UTF-8 statement more explicit and explicitly test for it --- library/proc_macro/src/lib.rs | 4 ++-- src/test/ui/proc-macro/span-absolute-posititions.rs | 12 ++++++++++-- .../ui/proc-macro/span-absolute-posititions.stderr | 10 +++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 793d35a28a2c0..22a67c450a66d 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -432,8 +432,8 @@ pub struct LineColumn { /// The 1-indexed line in the source file on which the span starts or ends (inclusive). #[unstable(feature = "proc_macro_span", issue = "54725")] pub line: usize, - /// The 1-indexed column (in UTF-8 characters) in the source file on which - /// the span starts or ends (inclusive). + /// The 1-indexed column (number of bytes in UTF-8 encoding) in the source + /// file on which the span starts or ends (inclusive). #[unstable(feature = "proc_macro_span", issue = "54725")] pub column: usize, } diff --git a/src/test/ui/proc-macro/span-absolute-posititions.rs b/src/test/ui/proc-macro/span-absolute-posititions.rs index 7fc3f6b5793bc..6d70fe611c47e 100644 --- a/src/test/ui/proc-macro/span-absolute-posititions.rs +++ b/src/test/ui/proc-macro/span-absolute-posititions.rs @@ -9,8 +9,16 @@ assert_span_pos::assert_span_pos!(5, 35); // Test tab indentation assert_span_pos::assert_span_pos!(10, 36); +// Two tests to ensure the promise of the docs that the column is the number +// of UTF-8 bytes instead of some other number like number of code points. + +// Test that multi byte UTF-8 characters indeed count as multiple bytes +/*🌈*/assert_span_pos::assert_span_pos!(16, 40); +// Test with a complete grapheme cluster +/*🏳️‍🌈*/assert_span_pos::assert_span_pos!(18, 43); + // Test that the macro actually emits an error on a mismatch: -assert_span_pos::assert_span_pos!(0, 35); //~ ERROR line/column mismatch: (0, 35) != (13, 35) -assert_span_pos::assert_span_pos!(14, 0); //~ ERROR line/column mismatch: (14, 0) != (14, 35) +assert_span_pos::assert_span_pos!(0, 35); //~ ERROR line/column mismatch: (0, 35) != (21, 35) +assert_span_pos::assert_span_pos!(22, 0); //~ ERROR line/column mismatch: (22, 0) != (22, 35) fn main() {} diff --git a/src/test/ui/proc-macro/span-absolute-posititions.stderr b/src/test/ui/proc-macro/span-absolute-posititions.stderr index ade66417520d6..6aca44a6b57a6 100644 --- a/src/test/ui/proc-macro/span-absolute-posititions.stderr +++ b/src/test/ui/proc-macro/span-absolute-posititions.stderr @@ -1,13 +1,13 @@ -error: line/column mismatch: (0, 35) != (13, 35) - --> $DIR/span-absolute-posititions.rs:13:35 +error: line/column mismatch: (0, 35) != (21, 35) + --> $DIR/span-absolute-posititions.rs:21:35 | LL | assert_span_pos::assert_span_pos!(0, 35); | ^ -error: line/column mismatch: (14, 0) != (14, 35) - --> $DIR/span-absolute-posititions.rs:14:35 +error: line/column mismatch: (22, 0) != (22, 35) + --> $DIR/span-absolute-posititions.rs:22:35 | -LL | assert_span_pos::assert_span_pos!(14, 0); +LL | assert_span_pos::assert_span_pos!(22, 0); | ^^ error: aborting due to 2 previous errors