@@ -35,27 +35,22 @@ function generateFunctionDoc(line, includeExamples, examplesOnlyForPublicOrExter
3535 const hasExtern = ! ! modifierMatch ?. [ 3 ] ;
3636
3737 // Attempt to match a Rust function signature.
38- const fnMatch = cleanLine . match ( / f n \s + ( \w + ) \s * \( ( [ ^ ) ] * ) \) \s * (?: - > \s * ( [ ^ ; { ] + ) ) ? / ) ;
38+ const fnMatch = cleanLine . match ( / f n \s + ( \w + ) \s * ( < [ ^ > ] * > ) ? \s * \( ( [ ^ ) ] * ) \) \s * (?: - > \s * ( [ ^ ; { ] + ) ) ? / ) ;
3939 if ( ! fnMatch ) return null ; // If no match, return nothing (unsupported line)
4040
4141 // Destructure the match results: function name, arguments, and optional return type.
42- const [ , name , args , returnType ] = fnMatch ;
42+ const [ , name , _generics , args , returnType ] = fnMatch ;
4343
4444 // Gets the return type.
4545 const cleanedReturn = returnType ? returnType . trim ( ) : null ;
4646
4747 // Sets the tab stop count for the parameter. Description is always 1.
4848 let currentTabStop = 2 ;
4949
50- // Parse and format each function argument into a markdown line with snippet placeholder.
51- const params = args
52- . split ( ',' )
53- . map ( p => p . trim ( ) )
54- . filter ( Boolean ) // Remove empty strings
55- . map ( param => {
56- const [ argName , argType ] = param . split ( ':' ) . map ( s => s . trim ( ) ) ;
57- return `- \`${ argName } \` (\`${ argType } \`) - \${${ currentTabStop ++ } :Describe this parameter.}` ;
58- } ) ;
50+ const params = splitFunctionArgs ( args ) . map ( p => p . trim ( ) ) . filter ( Boolean ) . map ( param => {
51+ const [ argName , argType ] = param . split ( ':' ) . map ( s => s . trim ( ) ) ;
52+ return `- \`${ argName } \` (\`${ argType } \`) - \${${ currentTabStop ++ } :Describe this parameter.}` ;
53+ } ) ;
5954
6055 // Build the full documentation block line by line.
6156 const docLines = [ ] ;
@@ -117,6 +112,47 @@ function generateFunctionDoc(line, includeExamples, examplesOnlyForPublicOrExter
117112 ] . join ( '\n' ) ;
118113}
119114
115+ /**
116+ * Splits a Rust function's argument list into individual parameters,
117+ * correctly handling nested generics and parentheses.
118+ *
119+ * This function is necessary because Rust function arguments may contain nested
120+ * angle brackets (e.g., `HashMap<String, Vec<u8>>`) or tuples
121+ * (e.g., `(i32, f64)`), which would cause a naive `.split(',')` to fail.
122+ *
123+ * It performs a linear scan of the argument string, tracking nesting levels of
124+ * `< >` and `( )`, and only splits on commas that are outside these constructs.
125+ *
126+ * @param {string } argString - The comma-separated argument list from a Rust function signature.
127+ * @returns {string[] } - An array of individual argument strings.
128+ *
129+ * @example
130+ * splitFunctionArgs("x: u32, y: HashMap<String, Vec<u8>>")
131+ * // returns: ["x: u32", "y: HashMap<String, Vec<u8>>"]
132+ */
133+ function splitFunctionArgs ( argString ) {
134+ const args = [ ] ;
135+ let current = '' ;
136+ let angle = 0 , paren = 0 ;
137+
138+ for ( let char of argString ) {
139+ if ( char === '<' ) angle ++ ;
140+ else if ( char === '>' ) angle -- ;
141+ else if ( char === '(' ) paren ++ ;
142+ else if ( char === ')' ) paren -- ;
143+
144+ if ( char === ',' && angle === 0 && paren === 0 ) {
145+ args . push ( current . trim ( ) ) ;
146+ current = '' ;
147+ } else {
148+ current += char ;
149+ }
150+ }
151+
152+ if ( current . trim ( ) ) args . push ( current . trim ( ) ) ;
153+ return args ;
154+ }
155+
120156/**
121157 * Generates the Rust documentation example section based on the function's modifiers.
122158 *
0 commit comments