Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/syntax_bridge.rs')
-rw-r--r--crates/mbe/src/syntax_bridge.rs105
1 files changed, 82 insertions, 23 deletions
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 5d802ba86c..c61c526286 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -63,7 +63,7 @@ pub(crate) mod dummy_test_span_utils {
/// Convert the syntax node to a `TokenTree` (what macro
/// will consume).
-/// TODO: Flesh out the doc comment more thoroughly
+/// FIXME: Flesh out the doc comment more thoroughly
pub fn syntax_node_to_token_tree<Anchor, Ctx, SpanMap>(
node: &SyntaxNode,
map: SpanMap,
@@ -179,6 +179,19 @@ where
Some(convert_tokens(&mut conv))
}
+/// Convert a string to a `TokenTree`
+pub fn parse_to_token_tree_static_span<S>(span: S, text: &str) -> Option<tt::Subtree<S>>
+where
+ S: Span,
+{
+ let lexed = parser::LexedStr::new(text);
+ if lexed.errors().next().is_some() {
+ return None;
+ }
+ let mut conv = StaticRawConverter { lexed, pos: 0, span };
+ Some(convert_tokens(&mut conv))
+}
+
/// Split token tree with separate expr: $($e:expr)SEP*
pub fn parse_exprs_with_sep<S: Span>(tt: &tt::Subtree<S>, sep: char) -> Vec<tt::Subtree<S>> {
if tt.token_trees.is_empty() {
@@ -213,12 +226,10 @@ pub fn parse_exprs_with_sep<S: Span>(tt: &tt::Subtree<S>, sep: char) -> Vec<tt::
res
}
-fn convert_tokens<Anchor, Ctx, C>(conv: &mut C) -> tt::Subtree<SpanData<Anchor, Ctx>>
+fn convert_tokens<S, C>(conv: &mut C) -> tt::Subtree<S>
where
- C: TokenConverter<Anchor, Ctx>,
- Ctx: SyntaxContext,
- SpanData<Anchor, Ctx>: Span,
- Anchor: Copy,
+ C: TokenConverter<S>,
+ S: Span,
{
let entry = tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: vec![] };
let mut stack = NonEmptyVec::new(entry);
@@ -452,6 +463,12 @@ struct RawConverter<'a, Anchor> {
pos: usize,
anchor: Anchor,
}
+/// A raw token (straight from lexer) converter that gives every token the same span.
+struct StaticRawConverter<'a, S> {
+ lexed: parser::LexedStr<'a>,
+ pos: usize,
+ span: S,
+}
trait SrcToken<Ctx>: std::fmt::Debug {
fn kind(&self, ctx: &Ctx) -> SyntaxKind;
@@ -461,20 +478,16 @@ trait SrcToken<Ctx>: std::fmt::Debug {
fn to_text(&self, ctx: &Ctx) -> SmolStr;
}
-trait TokenConverter<Anchor, Ctx>: Sized {
+trait TokenConverter<S>: Sized {
type Token: SrcToken<Self>;
- fn convert_doc_comment(
- &self,
- token: &Self::Token,
- span: SpanData<Anchor, Ctx>,
- ) -> Option<Vec<tt::TokenTree<SpanData<Anchor, Ctx>>>>;
+ fn convert_doc_comment(&self, token: &Self::Token, span: S) -> Option<Vec<tt::TokenTree<S>>>;
fn bump(&mut self) -> Option<(Self::Token, TextRange)>;
fn peek(&self) -> Option<Self::Token>;
- fn span_for(&self, range: TextRange) -> SpanData<Anchor, Ctx>;
+ fn span_for(&self, range: TextRange) -> S;
}
impl<Anchor> SrcToken<RawConverter<'_, Anchor>> for usize {
@@ -491,7 +504,22 @@ impl<Anchor> SrcToken<RawConverter<'_, Anchor>> for usize {
}
}
-impl<Anchor: Copy, Ctx: SyntaxContext> TokenConverter<Anchor, Ctx> for RawConverter<'_, Anchor>
+impl<S: Span> SrcToken<StaticRawConverter<'_, S>> for usize {
+ fn kind(&self, ctx: &StaticRawConverter<'_, S>) -> SyntaxKind {
+ ctx.lexed.kind(*self)
+ }
+
+ fn to_char(&self, ctx: &StaticRawConverter<'_, S>) -> Option<char> {
+ ctx.lexed.text(*self).chars().next()
+ }
+
+ fn to_text(&self, ctx: &StaticRawConverter<'_, S>) -> SmolStr {
+ ctx.lexed.text(*self).into()
+ }
+}
+
+impl<Anchor: Copy, Ctx: SyntaxContext> TokenConverter<SpanData<Anchor, Ctx>>
+ for RawConverter<'_, Anchor>
where
SpanData<Anchor, Ctx>: Span,
{
@@ -530,6 +558,41 @@ where
}
}
+impl<S> TokenConverter<S> for StaticRawConverter<'_, S>
+where
+ S: Span,
+{
+ type Token = usize;
+
+ fn convert_doc_comment(&self, &token: &usize, span: S) -> Option<Vec<tt::TokenTree<S>>> {
+ let text = self.lexed.text(token);
+ convert_doc_comment(&doc_comment(text), span)
+ }
+
+ fn bump(&mut self) -> Option<(Self::Token, TextRange)> {
+ if self.pos == self.lexed.len() {
+ return None;
+ }
+ let token = self.pos;
+ self.pos += 1;
+ let range = self.lexed.text_range(token);
+ let range = TextRange::new(range.start.try_into().ok()?, range.end.try_into().ok()?);
+
+ Some((token, range))
+ }
+
+ fn peek(&self) -> Option<Self::Token> {
+ if self.pos == self.lexed.len() {
+ return None;
+ }
+ Some(self.pos)
+ }
+
+ fn span_for(&self, _: TextRange) -> S {
+ self.span
+ }
+}
+
struct Converter<SpanMap> {
current: Option<SyntaxToken>,
preorder: PreorderWithTokens,
@@ -596,17 +659,13 @@ impl<SpanMap> SrcToken<Converter<SpanMap>> for SynToken {
}
}
-impl<Anchor: Copy, Ctx, SpanMap> TokenConverter<Anchor, Ctx> for Converter<SpanMap>
+impl<S, SpanMap> TokenConverter<S> for Converter<SpanMap>
where
- SpanData<Anchor, Ctx>: Span,
- SpanMap: SpanMapper<SpanData<Anchor, Ctx>>,
+ S: Span,
+ SpanMap: SpanMapper<S>,
{
type Token = SynToken;
- fn convert_doc_comment(
- &self,
- token: &Self::Token,
- span: SpanData<Anchor, Ctx>,
- ) -> Option<Vec<tt::TokenTree<SpanData<Anchor, Ctx>>>> {
+ fn convert_doc_comment(&self, token: &Self::Token, span: S) -> Option<Vec<tt::TokenTree<S>>> {
convert_doc_comment(token.token(), span)
}
@@ -661,7 +720,7 @@ where
Some(token)
}
- fn span_for(&self, range: TextRange) -> SpanData<Anchor, Ctx> {
+ fn span_for(&self, range: TextRange) -> S {
self.map.span_for(range)
}
}