From 4be5c7e758521c1e27f9f747a48d916fbb77957f Mon Sep 17 00:00:00 2001 From: pjsier Date: Sun, 10 Oct 2021 13:43:17 -0500 Subject: [PATCH 1/3] feat: WIP detect padding in doc comments --- src/documentation/literal.rs | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/documentation/literal.rs b/src/documentation/literal.rs index 53cf4cd1..b95963eb 100644 --- a/src/documentation/literal.rs +++ b/src/documentation/literal.rs @@ -111,6 +111,18 @@ impl CommentVariant { } } +#[derive(Clone, Hash, PartialEq)] +pub enum Padding { + Padding(String), + NoPadding, +} + +impl Default for Padding { + fn default() -> Self { + Padding::NoPadding + } +} + /// A literal with meta info where the first and list whitespace may be found. #[derive(Clone)] pub struct TrimmedLiteral { @@ -118,6 +130,7 @@ pub struct TrimmedLiteral { variant: CommentVariant, /// The span of rendered content, minus pre and post already applied. span: Span, + padding: Padding, /// the complete rendered string including post and pre. rendered: String, /// Literal prefix length. @@ -146,6 +159,9 @@ impl std::cmp::PartialEq for TrimmedLiteral { if self.span != other.span { return false; } + if self.padding != other.padding { + return false; + } if self.variant != other.variant { return false; } @@ -161,6 +177,7 @@ impl std::hash::Hash for TrimmedLiteral { self.variant.hash(hasher); self.rendered.hash(hasher); self.span.hash(hasher); + self.padding.hash(hasher); self.pre.hash(hasher); self.post.hash(hasher); self.len_in_bytes.hash(hasher); @@ -313,6 +330,19 @@ fn detect_comment_variant( Ok((variant, span, pre, post)) } +fn detect_padding(content: &str) -> Padding { + lazy_static! { + static ref PADDING_STR: Regex = + Regex::new(r##"(?m)^\s\*\s"##).expect("PADDING_STR regex compiles"); + }; + + if let Ok(Some(pad)) = PADDING_STR.find(content) { + return Padding::Padding(pad.as_str().to_string()); + } + + Padding::NoPadding +} + impl TryFrom<(&str, proc_macro2::Literal)> for TrimmedLiteral { type Error = Error; fn try_from((content, literal): (&str, proc_macro2::Literal)) -> Result { @@ -352,6 +382,7 @@ impl TryFrom<(&str, proc_macro2::Literal)> for TrimmedLiteral { let rendered_len = rendered.chars().count(); log::trace!("extracted from source: >{}< @ {:?}", rendered, span); + let padding = detect_padding(content); let (variant, span, pre, post) = detect_comment_variant(content, &rendered, span)?; let len_in_chars = rendered_len.saturating_sub(post + pre); @@ -372,6 +403,7 @@ impl TryFrom<(&str, proc_macro2::Literal)> for TrimmedLiteral { len_in_bytes, rendered, span, + padding, pre, post, }; @@ -403,11 +435,14 @@ impl TrimmedLiteral { }, }; + let padding = detect_padding(content); + trim_span(content, &mut span, pre, post + 1); Ok(TrimmedLiteral { variant, span, + padding, rendered: content.to_string(), pre, post, @@ -471,6 +506,10 @@ impl TrimmedLiteral { self.span.clone() } + pub fn padding(&self) -> Padding { + self.padding.clone() + } + /// Access the characters via an iterator. pub fn chars<'a>(&'a self) -> impl Iterator + 'a { self.as_str().chars() From c59e6b4fe5ed099d48834f426ec6fb5b41e682b5 Mon Sep 17 00:00:00 2001 From: pjsier Date: Mon, 11 Oct 2021 09:39:18 -0500 Subject: [PATCH 2/3] refactor: updates from review comments --- src/documentation/literal.rs | 46 ++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/documentation/literal.rs b/src/documentation/literal.rs index b95963eb..39dc21b5 100644 --- a/src/documentation/literal.rs +++ b/src/documentation/literal.rs @@ -111,15 +111,21 @@ impl CommentVariant { } } -#[derive(Clone, Hash, PartialEq)] -pub enum Padding { - Padding(String), +/// Track the style of padding for multiline comments +#[derive(Clone, Debug, Hash, PartialEq)] +pub enum CommentPaddingStyle { + /// " * ", with container for number of spaces + AsteriskSpace { + /// Number of leading spaces + leading_spaces: usize, + }, + /// Absence of padding NoPadding, } -impl Default for Padding { +impl Default for CommentPaddingStyle { fn default() -> Self { - Padding::NoPadding + Self::NoPadding } } @@ -130,7 +136,8 @@ pub struct TrimmedLiteral { variant: CommentVariant, /// The span of rendered content, minus pre and post already applied. span: Span, - padding: Padding, + /// The style of the padding for comments, if present + padding: CommentPaddingStyle, /// the complete rendered string including post and pre. rendered: String, /// Literal prefix length. @@ -330,17 +337,17 @@ fn detect_comment_variant( Ok((variant, span, pre, post)) } -fn detect_padding(content: &str) -> Padding { +fn detect_padding(content: &str) -> CommentPaddingStyle { lazy_static! { static ref PADDING_STR: Regex = Regex::new(r##"(?m)^\s\*\s"##).expect("PADDING_STR regex compiles"); }; - if let Ok(Some(pad)) = PADDING_STR.find(content) { - return Padding::Padding(pad.as_str().to_string()); + if let Ok(Some(_)) = PADDING_STR.find(content) { + return CommentPaddingStyle::AsteriskSpace { leading_spaces: 1 }; } - Padding::NoPadding + CommentPaddingStyle::NoPadding } impl TryFrom<(&str, proc_macro2::Literal)> for TrimmedLiteral { @@ -435,10 +442,10 @@ impl TrimmedLiteral { }, }; - let padding = detect_padding(content); - trim_span(content, &mut span, pre, post + 1); + let padding = detect_padding(content); + Ok(TrimmedLiteral { variant, span, @@ -506,7 +513,8 @@ impl TrimmedLiteral { self.span.clone() } - pub fn padding(&self) -> Padding { + /// The padding style for this literal. + pub fn padding(&self) -> CommentPaddingStyle { self.padding.clone() } @@ -665,6 +673,18 @@ mod tests { }); } + #[test] + fn padding_style_detect() { + assert_matches!( + detect_padding("/**\n * doc\n * doc\n */"), + CommentPaddingStyle::AsteriskSpace { leading_spaces: 1 } + ); + assert_matches!( + detect_padding("/**\n doc\n doc\n */"), + CommentPaddingStyle::NoPadding + ); + } + macro_rules! block_comment_test { ($name:ident, $content:literal) => { #[test] From 03b0d5a2418c442233e456c96713fee46d73ae3e Mon Sep 17 00:00:00 2001 From: pjsier Date: Wed, 13 Oct 2021 16:57:48 -0500 Subject: [PATCH 3/3] wip updates --- src/documentation/literal.rs | 53 +++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/documentation/literal.rs b/src/documentation/literal.rs index 39dc21b5..ea895a00 100644 --- a/src/documentation/literal.rs +++ b/src/documentation/literal.rs @@ -137,14 +137,14 @@ pub struct TrimmedLiteral { /// The span of rendered content, minus pre and post already applied. span: Span, /// The style of the padding for comments, if present - padding: CommentPaddingStyle, + padding_style: CommentPaddingStyle, /// the complete rendered string including post and pre. rendered: String, /// Literal prefix length. pre: usize, /// Literal postfix length. post: usize, - /// Length of rendered **minus** `pre` and `post` in UTF-8 characters. + /// Length of rendered **minus** `pre`, `post`, and `padding` in UTF-8 characters. len_in_chars: usize, len_in_bytes: usize, } @@ -166,7 +166,7 @@ impl std::cmp::PartialEq for TrimmedLiteral { if self.span != other.span { return false; } - if self.padding != other.padding { + if self.padding_style != other.padding_style { return false; } if self.variant != other.variant { @@ -184,7 +184,7 @@ impl std::hash::Hash for TrimmedLiteral { self.variant.hash(hasher); self.rendered.hash(hasher); self.span.hash(hasher); - self.padding.hash(hasher); + self.padding_style.hash(hasher); self.pre.hash(hasher); self.post.hash(hasher); self.len_in_bytes.hash(hasher); @@ -337,17 +337,22 @@ fn detect_comment_variant( Ok((variant, span, pre, post)) } -fn detect_padding(content: &str) -> CommentPaddingStyle { +fn detect_and_remove_padding(content: &str) -> (CommentPaddingStyle, usize) { lazy_static! { static ref PADDING_STR: Regex = Regex::new(r##"(?m)^\s\*\s"##).expect("PADDING_STR regex compiles"); }; if let Ok(Some(_)) = PADDING_STR.find(content) { - return CommentPaddingStyle::AsteriskSpace { leading_spaces: 1 }; + let padding = CommentPaddingStyle::AsteriskSpace { leading_spaces: 1 }; + let clean_content = PADDING_STR.replace_all(content, ""); + return ( + padding, + content.chars().count() - clean_content.chars().count(), + ); } - CommentPaddingStyle::NoPadding + (CommentPaddingStyle::NoPadding, content.len()) } impl TryFrom<(&str, proc_macro2::Literal)> for TrimmedLiteral { @@ -389,9 +394,16 @@ impl TryFrom<(&str, proc_macro2::Literal)> for TrimmedLiteral { let rendered_len = rendered.chars().count(); log::trace!("extracted from source: >{}< @ {:?}", rendered, span); - let padding = detect_padding(content); let (variant, span, pre, post) = detect_comment_variant(content, &rendered, span)?; + let (padding_style, padding) = match variant { + CommentVariant::SlashStar + | CommentVariant::SlashAsterisk + | CommentVariant::SlashAsteriskEM + | CommentVariant::SlashAsteriskAsterisk => detect_and_remove_padding(content), + _ => (CommentPaddingStyle::NoPadding, 0), + }; + let len_in_chars = rendered_len.saturating_sub(post + pre); if let Some(span_len) = span.one_line_len() { @@ -410,7 +422,7 @@ impl TryFrom<(&str, proc_macro2::Literal)> for TrimmedLiteral { len_in_bytes, rendered, span, - padding, + padding_style, pre, post, }; @@ -444,12 +456,10 @@ impl TrimmedLiteral { trim_span(content, &mut span, pre, post + 1); - let padding = detect_padding(content); - Ok(TrimmedLiteral { variant, span, - padding, + padding_style: CommentPaddingStyle::NoPadding, rendered: content.to_string(), pre, post, @@ -514,8 +524,8 @@ impl TrimmedLiteral { } /// The padding style for this literal. - pub fn padding(&self) -> CommentPaddingStyle { - self.padding.clone() + pub fn padding_style(&self) -> CommentPaddingStyle { + self.padding_style.clone() } /// Access the characters via an iterator. @@ -675,13 +685,18 @@ mod tests { #[test] fn padding_style_detect() { + let result = "/**\ndoc\ndoc\n */".to_string(); assert_matches!( - detect_padding("/**\n * doc\n * doc\n */"), - CommentPaddingStyle::AsteriskSpace { leading_spaces: 1 } + detect_and_remove_padding("/**\n * doc\n * doc\n */"), + ( + CommentPaddingStyle::AsteriskSpace { leading_spaces: 1 }, + result + ) ); + let content = "/**\n doc\n doc\n */".to_string(); assert_matches!( - detect_padding("/**\n doc\n doc\n */"), - CommentPaddingStyle::NoPadding + detect_and_remove_padding(&content), + (CommentPaddingStyle::NoPadding, content) ); } @@ -715,7 +730,7 @@ mod tests { block_comment_test!( trimmed_multi_doc, "/** -mood + * mood */" ); block_comment_test!(