From ef1b10a21d44f12e72f57b88d9d60e1e6cee6655 Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Thu, 31 Jul 2025 20:41:04 +0900 Subject: [PATCH] Escape bracket in generated docs --- CHANGELOG.md | 1 + Cargo.lock | 6 +++-- Cargo.toml | 2 ++ src/generator.rs | 40 ++++++++++++++++++++++++++++--- src/generator/codegen_register.rs | 14 ++++++++--- 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2168620..64c7248 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Use `u8` and `u16` for `T` of registers when the mask is 0xff or 0xffff, instead of defining new tuple struct. - Use `Mmapped` instead of `RegisterSpec` !21 - Remove empty doc generation !23 +- Added escape to brackets of form `[numbers]` in docs. (e.g., `a[1]` to `a\[1\]`, `b[1:2]` to `b\[1:2\]`) !24 ## [0.3.1] - 2025-04-11 diff --git a/Cargo.lock b/Cargo.lock index 5a855cc..18eb2de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,9 +385,11 @@ dependencies = [ "hex", "itertools", "log", + "once_cell", "prettyplease", "proc-macro2", "quote", + "regex", "roxmltree", "sha2", "syn", @@ -565,9 +567,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "powerfmt" diff --git a/Cargo.toml b/Cargo.toml index ed00b05..a3e8ef3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,9 +26,11 @@ heck = "0.5" hex = "0.4" itertools = "0.14" log = "0.4" +once_cell = "1.21.3" prettyplease = "0.2" proc-macro2 = "1.0" quote = "1.0" +regex = "1.11.1" roxmltree = "0.20" sha2 = "0.10" syn = "2.0" diff --git a/src/generator.rs b/src/generator.rs index b5c2111..23eee54 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -41,6 +41,9 @@ pub enum CodeGenError { } mod util { + use once_cell::sync::Lazy; + use regex::Regex; + use crate::types::DataType; use super::CodeGenError; @@ -115,9 +118,17 @@ mod util { } } + static RE_BRACKET_WITH_NUM: Lazy = + Lazy::new(|| Regex::new(r"\[(?[\d:]+)\]").unwrap()); + pub(super) fn escape_brackets_with_numbers(s: &str) -> String { + RE_BRACKET_WITH_NUM + .replace_all(s, "\\[$inner\\]") + .into_owned() + } + #[cfg(test)] mod test { - use super::RustUxTypes; + use super::{RustUxTypes, escape_brackets_with_numbers}; #[test] fn rustuxtypes_from_mask() { @@ -148,6 +159,23 @@ mod util { proc_macro2::Ident::new("u8", proc_macro2::Span::call_site()) ) } + + #[test] + fn test_regex() { + assert_eq!(escape_brackets_with_numbers("abc"), "abc".to_string()); + assert_eq!( + escape_brackets_with_numbers("abc[1]"), + r"abc\[1\]".to_string() + ); + assert_eq!( + escape_brackets_with_numbers("abc[12:34]"), + r"abc\[12:34\]".to_string() + ); + assert_eq!( + escape_brackets_with_numbers("abc[12:34], def[1]"), + r"abc\[12:34\], def\[1\]".to_string() + ); + } } } @@ -312,7 +340,10 @@ impl CodeGen for Block { let desc = match self.desc { None => quote! {}, Some(ref s) if s.is_empty() => quote! {}, - Some(ref desc) => quote! { #![doc = #desc] }, + Some(ref desc) => { + let desc = util::escape_brackets_with_numbers(desc); + quote! { #![doc = #desc] } + } }; let accessors_methods = self.elements.iter().map(|e| { @@ -474,7 +505,10 @@ impl CodeGen for Register { let doc = match self.desc { None => quote! {}, Some(ref s) if s.is_empty() => quote! {}, - Some(ref desc) => quote! { #![doc = #desc] }, + Some(ref desc) => { + let desc = util::escape_brackets_with_numbers(desc); + quote! { #![doc = #desc] } + } }; let out = quote! { diff --git a/src/generator/codegen_register.rs b/src/generator/codegen_register.rs index 79aad52..b888689 100644 --- a/src/generator/codegen_register.rs +++ b/src/generator/codegen_register.rs @@ -190,6 +190,11 @@ fn generate_field( true => FieldType::RustType(util::RustUxTypes::from_mask(field.mask)), false => FieldType::CustomValue(&field.elements), }; + let desc = match field.desc.clone() { + None => "".to_string(), + Some(s) if s.is_empty() => s, + Some(desc) => util::escape_brackets_with_numbers(&desc), + }; let (code_mask, code_getter, code_setter) = match &field.multiple { Some(multiple_params) => generate_multiple_field( @@ -199,7 +204,7 @@ fn generate_field( field_type, snake_case_name, multiple_params, - &field.desc.clone().unwrap_or("".to_string()), + &desc, ), None => generate_single_field( mask_name, @@ -207,7 +212,7 @@ fn generate_field( field.mask, field_type, snake_case_name, - &field.desc.clone().unwrap_or("".to_string()), + &desc, ), }; @@ -352,7 +357,10 @@ fn generate_custom_values_const_enumdef( let doc = match value.desc { None => quote! {}, Some(ref s) if s.is_empty() => quote! {}, - Some(ref desc) => quote! { #[doc = #desc] }, + Some(ref desc) => { + let desc = util::escape_brackets_with_numbers(desc); + quote! { #![doc = #desc] } + } }; let variant_name = util::parse_to_ident(&value.name.to_upper_camel_case()).unwrap(); quote! {