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.rs | 70 |
1 files changed, 48 insertions, 22 deletions
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 3230eeb5bd..412e492176 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -69,18 +69,28 @@ pub(crate) mod dummy_test_span_utils { } } +/// Doc comment desugaring differs between mbe and proc-macros. +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum DocCommentDesugarMode { + /// Desugars doc comments as quoted raw strings + Mbe, + /// Desugars doc comments as quoted strings + ProcMacro, +} + /// Converts a syntax tree to a [`tt::Subtree`] using the provided span map to populate the /// subtree's spans. pub fn syntax_node_to_token_tree<Ctx, SpanMap>( node: &SyntaxNode, map: SpanMap, span: SpanData<Ctx>, + mode: DocCommentDesugarMode, ) -> tt::Subtree<SpanData<Ctx>> where SpanData<Ctx>: Copy + fmt::Debug, SpanMap: SpanMapper<SpanData<Ctx>>, { - let mut c = Converter::new(node, map, Default::default(), Default::default(), span); + let mut c = Converter::new(node, map, Default::default(), Default::default(), span, mode); convert_tokens(&mut c) } @@ -93,12 +103,13 @@ pub fn syntax_node_to_token_tree_modified<Ctx, SpanMap>( append: FxHashMap<SyntaxElement, Vec<tt::Leaf<SpanData<Ctx>>>>, remove: FxHashSet<SyntaxElement>, call_site: SpanData<Ctx>, + mode: DocCommentDesugarMode, ) -> tt::Subtree<SpanData<Ctx>> where SpanMap: SpanMapper<SpanData<Ctx>>, SpanData<Ctx>: Copy + fmt::Debug, { - let mut c = Converter::new(node, map, append, remove, call_site); + let mut c = Converter::new(node, map, append, remove, call_site, mode); convert_tokens(&mut c) } @@ -165,7 +176,8 @@ where if lexed.errors().next().is_some() { return None; } - let mut conv = RawConverter { lexed, anchor, pos: 0, ctx }; + let mut conv = + RawConverter { lexed, anchor, pos: 0, ctx, mode: DocCommentDesugarMode::ProcMacro }; Some(convert_tokens(&mut conv)) } @@ -178,7 +190,8 @@ where if lexed.errors().next().is_some() { return None; } - let mut conv = StaticRawConverter { lexed, pos: 0, span }; + let mut conv = + StaticRawConverter { lexed, pos: 0, span, mode: DocCommentDesugarMode::ProcMacro }; Some(convert_tokens(&mut conv)) } @@ -405,7 +418,7 @@ fn is_single_token_op(kind: SyntaxKind) -> bool { /// That is, strips leading `///` (or `/**`, etc) /// and strips the ending `*/` /// And then quote the string, which is needed to convert to `tt::Literal` -fn doc_comment_text(comment: &ast::Comment) -> SmolStr { +fn doc_comment_text(comment: &ast::Comment, mode: DocCommentDesugarMode) -> SmolStr { let prefix_len = comment.prefix().len(); let mut text = &comment.text()[prefix_len..]; @@ -414,26 +427,34 @@ fn doc_comment_text(comment: &ast::Comment) -> SmolStr { text = &text[0..text.len() - 2]; } - let mut num_of_hashes = 0; - let mut count = 0; - for ch in text.chars() { - count = match ch { - '"' => 1, - '#' if count > 0 => count + 1, - _ => 0, - }; - num_of_hashes = num_of_hashes.max(count); - } + let text = match mode { + DocCommentDesugarMode::Mbe => { + let mut num_of_hashes = 0; + let mut count = 0; + for ch in text.chars() { + count = match ch { + '"' => 1, + '#' if count > 0 => count + 1, + _ => 0, + }; + num_of_hashes = num_of_hashes.max(count); + } - // Quote raw string with delimiters - // Note that `tt::Literal` expect an escaped string - let text = format!("r{delim}\"{text}\"{delim}", delim = "#".repeat(num_of_hashes)); + // Quote raw string with delimiters + // Note that `tt::Literal` expect an escaped string + format!(r#"r{delim}"{text}"{delim}"#, delim = "#".repeat(num_of_hashes)) + } + // Quote string with delimiters + // Note that `tt::Literal` expect an escaped string + DocCommentDesugarMode::ProcMacro => format!(r#""{}""#, text.escape_debug()), + }; text.into() } fn convert_doc_comment<S: Copy>( token: &syntax::SyntaxToken, span: S, + mode: DocCommentDesugarMode, ) -> Option<Vec<tt::TokenTree<S>>> { cov_mark::hit!(test_meta_doc_comments); let comment = ast::Comment::cast(token.clone())?; @@ -451,7 +472,7 @@ fn convert_doc_comment<S: Copy>( }; let mk_doc_literal = |comment: &ast::Comment| { - let lit = tt::Literal { text: doc_comment_text(comment), span }; + let lit = tt::Literal { text: doc_comment_text(comment, mode), span }; tt::TokenTree::from(tt::Leaf::from(lit)) }; @@ -479,12 +500,14 @@ struct RawConverter<'a, Ctx> { pos: usize, anchor: SpanAnchor, ctx: Ctx, + mode: DocCommentDesugarMode, } /// 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, + mode: DocCommentDesugarMode, } trait SrcToken<Ctx, S> { @@ -553,7 +576,7 @@ where span: SpanData<Ctx>, ) -> Option<Vec<tt::TokenTree<SpanData<Ctx>>>> { let text = self.lexed.text(token); - convert_doc_comment(&doc_comment(text), span) + convert_doc_comment(&doc_comment(text), span, self.mode) } fn bump(&mut self) -> Option<(Self::Token, TextRange)> { @@ -592,7 +615,7 @@ where 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) + convert_doc_comment(&doc_comment(text), span, self.mode) } fn bump(&mut self) -> Option<(Self::Token, TextRange)> { @@ -634,6 +657,7 @@ struct Converter<SpanMap, S> { append: FxHashMap<SyntaxElement, Vec<tt::Leaf<S>>>, remove: FxHashSet<SyntaxElement>, call_site: S, + mode: DocCommentDesugarMode, } impl<SpanMap, S> Converter<SpanMap, S> { @@ -643,6 +667,7 @@ impl<SpanMap, S> Converter<SpanMap, S> { append: FxHashMap<SyntaxElement, Vec<tt::Leaf<S>>>, remove: FxHashSet<SyntaxElement>, call_site: S, + mode: DocCommentDesugarMode, ) -> Self { let mut this = Converter { current: None, @@ -654,6 +679,7 @@ impl<SpanMap, S> Converter<SpanMap, S> { remove, call_site, current_leaves: vec![], + mode, }; let first = this.next_token(); this.current = first; @@ -755,7 +781,7 @@ where { type Token = SynToken<S>; fn convert_doc_comment(&self, token: &Self::Token, span: S) -> Option<Vec<tt::TokenTree<S>>> { - convert_doc_comment(token.token(), span) + convert_doc_comment(token.token(), span, self.mode) } fn bump(&mut self) -> Option<(Self::Token, TextRange)> { |