2022-07-20 11:27:58 -05:00
|
|
|
//! proc-macro server implementation
|
|
|
|
//!
|
|
|
|
//! Based on idea from <https://github.com/fedochet/rust-proc-macro-expander>
|
|
|
|
//! The lib-proc-macro server backend is `TokenStream`-agnostic, such that
|
|
|
|
//! we could provide any TokenStream implementation.
|
|
|
|
//! The original idea from fedochet is using proc-macro2 as backend,
|
|
|
|
//! we use tt instead for better integration with RA.
|
|
|
|
//!
|
|
|
|
//! FIXME: No span and source file information is implemented yet
|
|
|
|
|
2023-12-11 05:16:12 -06:00
|
|
|
use proc_macro::bridge;
|
2022-07-20 11:27:58 -05:00
|
|
|
|
2022-07-20 11:32:27 -05:00
|
|
|
mod token_stream;
|
2022-07-20 11:43:59 -05:00
|
|
|
pub use token_stream::TokenStream;
|
2022-07-20 11:32:27 -05:00
|
|
|
|
2023-12-11 05:16:12 -06:00
|
|
|
pub mod rust_analyzer_span;
|
2022-07-20 11:36:10 -05:00
|
|
|
mod symbol;
|
2024-01-26 13:08:10 -06:00
|
|
|
pub mod token_id;
|
2022-07-20 11:36:10 -05:00
|
|
|
pub use symbol::*;
|
2023-12-11 05:16:12 -06:00
|
|
|
use tt::Spacing;
|
2022-07-20 11:36:10 -05:00
|
|
|
|
2023-12-11 05:16:12 -06:00
|
|
|
fn delim_to_internal<S>(d: proc_macro::Delimiter, span: bridge::DelimSpan<S>) -> tt::Delimiter<S> {
|
2022-07-20 11:27:58 -05:00
|
|
|
let kind = match d {
|
2022-07-20 11:36:10 -05:00
|
|
|
proc_macro::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
|
|
|
|
proc_macro::Delimiter::Brace => tt::DelimiterKind::Brace,
|
|
|
|
proc_macro::Delimiter::Bracket => tt::DelimiterKind::Bracket,
|
2023-02-13 05:55:14 -06:00
|
|
|
proc_macro::Delimiter::None => tt::DelimiterKind::Invisible,
|
2022-07-20 11:27:58 -05:00
|
|
|
};
|
2023-06-19 01:14:04 -05:00
|
|
|
tt::Delimiter { open: span.open, close: span.close, kind }
|
2022-07-20 11:27:58 -05:00
|
|
|
}
|
|
|
|
|
2023-12-11 05:16:12 -06:00
|
|
|
fn delim_to_external<S>(d: tt::Delimiter<S>) -> proc_macro::Delimiter {
|
2023-02-13 05:55:14 -06:00
|
|
|
match d.kind {
|
|
|
|
tt::DelimiterKind::Parenthesis => proc_macro::Delimiter::Parenthesis,
|
|
|
|
tt::DelimiterKind::Brace => proc_macro::Delimiter::Brace,
|
|
|
|
tt::DelimiterKind::Bracket => proc_macro::Delimiter::Bracket,
|
|
|
|
tt::DelimiterKind::Invisible => proc_macro::Delimiter::None,
|
2022-07-20 11:27:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-05 04:04:23 -05:00
|
|
|
#[allow(unused)]
|
2022-07-20 11:36:10 -05:00
|
|
|
fn spacing_to_internal(spacing: proc_macro::Spacing) -> Spacing {
|
2022-07-20 11:27:58 -05:00
|
|
|
match spacing {
|
2022-07-20 11:36:10 -05:00
|
|
|
proc_macro::Spacing::Alone => Spacing::Alone,
|
|
|
|
proc_macro::Spacing::Joint => Spacing::Joint,
|
2022-07-20 11:27:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-05 04:04:23 -05:00
|
|
|
#[allow(unused)]
|
2022-07-20 11:36:10 -05:00
|
|
|
fn spacing_to_external(spacing: Spacing) -> proc_macro::Spacing {
|
2022-07-20 11:27:58 -05:00
|
|
|
match spacing {
|
2022-07-20 11:36:10 -05:00
|
|
|
Spacing::Alone => proc_macro::Spacing::Alone,
|
|
|
|
Spacing::Joint => proc_macro::Spacing::Joint,
|
2022-07-20 11:27:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-11 05:16:12 -06:00
|
|
|
struct LiteralFormatter<S>(bridge::Literal<S, Symbol>);
|
2022-07-21 11:44:41 -05:00
|
|
|
|
2023-12-11 05:16:12 -06:00
|
|
|
impl<S> LiteralFormatter<S> {
|
2022-07-21 11:44:41 -05:00
|
|
|
/// Invokes the callback with a `&[&str]` consisting of each part of the
|
|
|
|
/// literal's representation. This is done to allow the `ToString` and
|
|
|
|
/// `Display` implementations to borrow references to symbol values, and
|
|
|
|
/// both be optimized to reduce overhead.
|
2023-06-05 04:04:23 -05:00
|
|
|
fn with_stringify_parts<R>(
|
|
|
|
&self,
|
|
|
|
interner: SymbolInternerRef,
|
|
|
|
f: impl FnOnce(&[&str]) -> R,
|
|
|
|
) -> R {
|
2022-07-21 11:44:41 -05:00
|
|
|
/// Returns a string containing exactly `num` '#' characters.
|
|
|
|
/// Uses a 256-character source string literal which is always safe to
|
|
|
|
/// index with a `u8` index.
|
|
|
|
fn get_hashes_str(num: u8) -> &'static str {
|
|
|
|
const HASHES: &str = "\
|
|
|
|
################################################################\
|
|
|
|
################################################################\
|
|
|
|
################################################################\
|
|
|
|
################################################################\
|
|
|
|
";
|
|
|
|
const _: () = assert!(HASHES.len() == 256);
|
|
|
|
&HASHES[..num as usize]
|
|
|
|
}
|
|
|
|
|
2023-06-05 04:04:23 -05:00
|
|
|
self.with_symbol_and_suffix(interner, |symbol, suffix| match self.0.kind {
|
2022-07-21 11:44:41 -05:00
|
|
|
bridge::LitKind::Byte => f(&["b'", symbol, "'", suffix]),
|
|
|
|
bridge::LitKind::Char => f(&["'", symbol, "'", suffix]),
|
|
|
|
bridge::LitKind::Str => f(&["\"", symbol, "\"", suffix]),
|
|
|
|
bridge::LitKind::StrRaw(n) => {
|
|
|
|
let hashes = get_hashes_str(n);
|
|
|
|
f(&["r", hashes, "\"", symbol, "\"", hashes, suffix])
|
|
|
|
}
|
|
|
|
bridge::LitKind::ByteStr => f(&["b\"", symbol, "\"", suffix]),
|
|
|
|
bridge::LitKind::ByteStrRaw(n) => {
|
|
|
|
let hashes = get_hashes_str(n);
|
|
|
|
f(&["br", hashes, "\"", symbol, "\"", hashes, suffix])
|
|
|
|
}
|
2024-02-22 15:25:55 -06:00
|
|
|
bridge::LitKind::CStr => f(&["c\"", symbol, "\"", suffix]),
|
|
|
|
bridge::LitKind::CStrRaw(n) => {
|
|
|
|
let hashes = get_hashes_str(n);
|
|
|
|
f(&["cr", hashes, "\"", symbol, "\"", hashes, suffix])
|
|
|
|
}
|
|
|
|
bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::ErrWithGuar => {
|
|
|
|
f(&[symbol, suffix])
|
|
|
|
}
|
2022-07-21 11:44:41 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-06-05 04:04:23 -05:00
|
|
|
fn with_symbol_and_suffix<R>(
|
|
|
|
&self,
|
|
|
|
interner: SymbolInternerRef,
|
|
|
|
f: impl FnOnce(&str, &str) -> R,
|
|
|
|
) -> R {
|
|
|
|
let symbol = self.0.symbol.text(interner);
|
|
|
|
let suffix = self.0.suffix.map(|s| s.text(interner)).unwrap_or_default();
|
2022-07-21 14:32:46 -05:00
|
|
|
f(symbol.as_str(), suffix.as_str())
|
2022-07-21 11:44:41 -05:00
|
|
|
}
|
|
|
|
}
|