Skip to content

Commit 8b9b727

Browse files
committed
mlua_derive: Refactor Capture implementation for chunk!
1 parent 20151b0 commit 8b9b727

4 files changed

Lines changed: 53 additions & 42 deletions

File tree

mlua_derive/src/chunk.rs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
1-
use proc_macro::{TokenStream, TokenTree};
1+
use std::ops::Deref;
2+
3+
use proc_macro::TokenStream;
4+
use proc_macro2::TokenStream as TokenStream2;
5+
use quote::ToTokens;
26

37
use crate::token::{Pos, Token, Tokens};
48

59
#[derive(Debug, Clone)]
6-
pub(crate) struct Capture {
7-
key: Token,
8-
rust: TokenTree,
10+
pub(crate) struct Capture(Token);
11+
12+
impl Deref for Capture {
13+
type Target = Token;
14+
15+
fn deref(&self) -> &Self::Target {
16+
&self.0
17+
}
918
}
1019

1120
impl Capture {
12-
fn new(key: Token, rust: TokenTree) -> Self {
13-
Self { key, rust }
21+
fn new(token: &Token) -> Self {
22+
Self(token.clone())
1423
}
1524

16-
/// Token string inside `chunk!`
17-
pub(crate) fn key(&self) -> &Token {
18-
&self.key
25+
pub(crate) fn name(&self) -> String {
26+
self.0.to_string()
1927
}
28+
}
2029

21-
/// As rust variable, e.g. `x`
22-
pub(crate) fn as_rust(&self) -> &TokenTree {
23-
&self.rust
30+
impl ToTokens for Capture {
31+
fn to_tokens(&self, tokens: &mut TokenStream2) {
32+
let ts: TokenStream = self.0.tree().clone().into();
33+
tokens.extend(TokenStream2::from(ts));
2434
}
2535
}
2636

@@ -33,11 +43,10 @@ impl Captures {
3343
}
3444

3545
pub(crate) fn add(&mut self, token: &Token) {
36-
if self.0.iter().any(|arg| arg.key() == token) {
46+
if self.0.iter().any(|arg| &**arg == token) {
3747
return;
3848
}
39-
let arg = Capture::new(token.clone(), token.tree().clone());
40-
self.0.push(arg);
49+
self.0.push(Capture::new(token));
4150
}
4251

4352
pub(crate) fn captures(&self) -> &[Capture] {
@@ -58,29 +67,26 @@ impl Chunk {
5867
let mut source = String::new();
5968
let mut caps = Captures::new();
6069

61-
let mut pos: Option<Pos> = None;
70+
let mut prev_end: Option<Pos> = None;
6271
for t in tokens {
6372
if t.is_cap() {
6473
caps.add(&t);
6574
}
6675

6776
let (line, col) = (t.start().line, t.start().column);
68-
let (prev_line, prev_col) = pos
69-
.take()
70-
.map(|lc| (lc.line, lc.column))
71-
.unwrap_or_else(|| (line, col));
72-
73-
#[allow(clippy::comparison_chain)]
74-
if line > prev_line {
75-
source.push('\n');
76-
} else if line == prev_line {
77-
for _ in 0..col.saturating_sub(prev_col) {
78-
source.push(' ');
77+
if let Some(prev) = prev_end {
78+
if line > prev.line {
79+
source.push('\n');
80+
source.push_str(&" ".repeat(col.saturating_sub(1)));
81+
} else if line == prev.line {
82+
source.push_str(&" ".repeat(col.saturating_sub(prev.column)));
7983
}
84+
} else {
85+
source.push_str(&" ".repeat(col.saturating_sub(1)));
8086
}
8187
source.push_str(&t.to_string());
8288

83-
pos = Some(t.end());
89+
prev_end = Some(t.end());
8490
}
8591

8692
Self {

mlua_derive/src/lib.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ use syn::meta::ParseNestedMeta;
55
use syn::{ItemFn, LitStr, Result, parse_macro_input};
66

77
#[cfg(feature = "macros")]
8-
use {
9-
crate::chunk::Chunk, proc_macro::TokenTree, proc_macro_error2::proc_macro_error,
10-
proc_macro2::TokenStream as TokenStream2,
11-
};
8+
use {crate::chunk::Chunk, proc_macro_error2::proc_macro_error};
129

1310
#[cfg(feature = "macros")]
1411
macro_rules! try_compile {
@@ -84,12 +81,6 @@ pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream {
8481
wrapped.into()
8582
}
8683

87-
#[cfg(feature = "macros")]
88-
fn to_ident(tt: &TokenTree) -> TokenStream2 {
89-
let s: TokenStream = tt.clone().into();
90-
s.into()
91-
}
92-
9384
#[cfg(feature = "macros")]
9485
#[proc_macro]
9586
#[proc_macro_error]
@@ -100,8 +91,7 @@ pub fn chunk(input: TokenStream) -> TokenStream {
10091

10192
let caps_len = chunk.captures().len();
10293
let caps = chunk.captures().iter().map(|cap| {
103-
let cap_name = cap.as_rust().to_string();
104-
let cap = to_ident(cap.as_rust());
94+
let cap_name = cap.name();
10595
quote! { env.raw_set(#cap_name, #cap)?; }
10696
});
10797

mlua_derive/src/token.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ impl Eq for Token {}
7676
impl Token {
7777
fn new(tree: TokenTree) -> Self {
7878
let (start, end) = span_pos(&tree.span());
79+
let source = tree.span().source_text().unwrap_or_else(|| tree.to_string());
7980
Self {
80-
source: tree.to_string(),
81+
source,
8182
start,
8283
end,
8384
tree,
@@ -136,7 +137,6 @@ impl Tokens {
136137
Tokens(
137138
tt.into_iter()
138139
.flat_map(Tokens::from)
139-
.peekable()
140140
.batching(|iter| {
141141
// Find variable tokens: `$` + `ident` => `$ident`
142142
let t = iter.next()?;

tests/chunk.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ fn test_chunk_macro() -> Result<()> {
110110

111111
assert_eq!(lua.globals().get::<i32>("s")?, 321);
112112

113+
// Check line numbers in error reporting
114+
match lua
115+
.load(mlua::chunk! {
116+
local x = 1
117+
-- comment
118+
error("boom")
119+
})
120+
.exec()
121+
{
122+
Err(mlua::Error::RuntimeError(ref msg)) => {
123+
assert!(msg.contains(":3:"), "expected line 3, got: {msg}");
124+
}
125+
other => panic!("expected RuntimeError, got {other:?}"),
126+
}
127+
113128
Ok(())
114129
}
115130

0 commit comments

Comments
 (0)