@@ -153,22 +153,146 @@ private static ImmutableArray<LocalizableString> ParseXamlFile(AdditionalText fi
153153
154154 if ( key != null )
155155 {
156- localizableStrings . Add ( ParseLocalizableString ( key , value , comment ) ) ;
156+ var formatParams = GetParameters ( value ) ;
157+ var ( summary , updatedFormatParams ) = ParseCommentAndUpdateParameters ( comment , formatParams ) ;
158+ localizableStrings . Add ( new LocalizableString ( key , value , summary , updatedFormatParams ) ) ;
157159 }
158160 }
159161
160162 return localizableStrings . ToImmutableArray ( ) ;
161163 }
162164
163- private static LocalizableString ParseLocalizableString ( string key , string value , XComment comment )
165+ /// <summary>
166+ /// Analyzes the format string and returns a list of its parameters.
167+ /// </summary>
168+ /// <param name="format"></param>
169+ /// <returns></returns>
170+ private static List < LocalizableStringParam > GetParameters ( string format )
164171 {
165- var ( summary , parameters ) = ParseComment ( comment ) ;
166- return new LocalizableString ( key , value , summary , parameters ) ;
172+ var parameters = new Dictionary < int , string > ( ) ;
173+ int maxIndex = - 1 ;
174+ int i = 0 ;
175+ int len = format . Length ;
176+
177+ while ( i < len )
178+ {
179+ if ( format [ i ] == '{' )
180+ {
181+ if ( i + 1 < len && format [ i + 1 ] == '{' )
182+ {
183+ // Escaped '{', skip both
184+ i += 2 ;
185+ continue ;
186+ }
187+ else
188+ {
189+ // Start of a format item, parse index and format
190+ i ++ ; // Move past '{'
191+ int index = 0 ;
192+ bool hasIndex = false ;
193+ // Parse index
194+ while ( i < len && char . IsDigit ( format [ i ] ) )
195+ {
196+ hasIndex = true ;
197+ index = index * 10 + ( format [ i ] - '0' ) ;
198+ i ++ ;
199+ }
200+ if ( ! hasIndex )
201+ {
202+ // Skip invalid format item
203+ while ( i < len && format [ i ] != '}' )
204+ {
205+ i ++ ;
206+ }
207+ if ( i < len )
208+ {
209+ i ++ ; // Move past '}'
210+ }
211+ continue ;
212+ }
213+ // Check for colon to parse format
214+ string formatPart = null ;
215+ if ( i < len && format [ i ] == ':' )
216+ {
217+ i ++ ; // Move past ':'
218+ int start = i ;
219+ while ( i < len && format [ i ] != '}' )
220+ {
221+ i ++ ;
222+ }
223+ formatPart = i < len ? format . Substring ( start , i - start ) : format . Substring ( start ) ;
224+ if ( i < len )
225+ {
226+ i ++ ; // Move past '}'
227+ }
228+ }
229+ else if ( i < len && format [ i ] == '}' )
230+ {
231+ // No format part
232+ i ++ ; // Move past '}'
233+ }
234+ else
235+ {
236+ // Invalid characters after index, skip to '}'
237+ while ( i < len && format [ i ] != '}' )
238+ {
239+ i ++ ;
240+ }
241+ if ( i < len )
242+ {
243+ i ++ ; // Move past '}'
244+ }
245+ }
246+ parameters [ index ] = formatPart ;
247+ if ( index > maxIndex )
248+ {
249+ maxIndex = index ;
250+ }
251+ }
252+ }
253+ else if ( format [ i ] == '}' )
254+ {
255+ // Handle possible escaped '}}'
256+ if ( i + 1 < len && format [ i + 1 ] == '}' )
257+ {
258+ i += 2 ;
259+ }
260+ else
261+ {
262+ i ++ ;
263+ }
264+ }
265+ else
266+ {
267+ i ++ ;
268+ }
269+ }
270+
271+ // Generate the result list from 0 to maxIndex
272+ var result = new List < LocalizableStringParam > ( ) ;
273+ if ( maxIndex == - 1 )
274+ {
275+ return result ;
276+ }
277+
278+ for ( int idx = 0 ; idx <= maxIndex ; idx ++ )
279+ {
280+ var formatValue = parameters . TryGetValue ( idx , out var value ) ? value : null ;
281+ result . Add ( new LocalizableStringParam { Index = idx , Format = formatValue , Name = $ "arg{ idx } ", Type = "object?" } ) ;
282+ }
283+
284+ return result ;
167285 }
168286
169- private static ( string Summary , ImmutableArray < LocalizableStringParam > Parameters ) ParseComment ( XComment comment )
287+ /// <summary>
288+ /// Parses the comment and updates the format parameter names and types.
289+ /// </summary>
290+ /// <param name="comment"></param>
291+ /// <param name="parameters"></param>
292+ /// <returns></returns>
293+ private static ( string Summary , ImmutableArray < LocalizableStringParam > Parameters ) ParseCommentAndUpdateParameters ( XComment comment , List < LocalizableStringParam > parameters )
170294 {
171- if ( comment == null || comment . Value == null )
295+ if ( comment == null || comment . Value == null || parameters . Count == 0 )
172296 {
173297 return ( null , ImmutableArray < LocalizableStringParam > . Empty ) ;
174298 }
@@ -177,13 +301,26 @@ private static (string Summary, ImmutableArray<LocalizableStringParam> Parameter
177301 {
178302 var doc = XDocument . Parse ( $ "<root>{ comment . Value } </root>") ;
179303 var summary = doc . Descendants ( "summary" ) . FirstOrDefault ( ) ? . Value . Trim ( ) ;
180- var parameters = doc . Descendants ( "param" )
181- . Select ( p => new LocalizableStringParam (
182- int . Parse ( p . Attribute ( "index" ) . Value ) ,
183- p . Attribute ( "name" ) . Value ,
184- p . Attribute ( "type" ) . Value ) )
185- . ToImmutableArray ( ) ;
186- return ( summary , parameters ) ;
304+
305+ // Update parameter names and types of the format string
306+ foreach ( var p in doc . Descendants ( "param" ) )
307+ {
308+ var index = int . TryParse ( p . Attribute ( "index" ) . Value , out var intValue ) ? intValue : - 1 ;
309+ var name = p . Attribute ( "name" ) . Value ;
310+ var type = p . Attribute ( "type" ) . Value ;
311+ if ( index >= 0 && index < parameters . Count )
312+ {
313+ if ( ! string . IsNullOrEmpty ( name ) )
314+ {
315+ parameters [ index ] . Name = name ;
316+ }
317+ if ( ! string . IsNullOrEmpty ( type ) )
318+ {
319+ parameters [ index ] . Type = type ;
320+ }
321+ }
322+ }
323+ return ( summary , parameters . ToImmutableArray ( ) ) ;
187324 }
188325 catch
189326 {
@@ -472,7 +609,7 @@ private static void GenerateLocalizationMethod(
472609 string tabString )
473610 {
474611 sb . Append ( $ "{ tabString } public static string { ls . Key } (") ;
475- var parameters = BuildParameters ( ls ) ;
612+ var parameters = ls . Params . ToList ( ) ;
476613 sb . Append ( string . Join ( ", " , parameters . Select ( p => $ "{ p . Type } { p . Name } ") ) ) ;
477614 sb . Append ( ") => " ) ;
478615
@@ -500,24 +637,6 @@ private static void GenerateLocalizationMethod(
500637 sb . AppendLine ( ) ;
501638 }
502639
503- private static List < MethodParameter > BuildParameters ( LocalizableString ls )
504- {
505- var parameters = new List < MethodParameter > ( ) ;
506- for ( var i = 0 ; i < 10 ; i ++ )
507- {
508- if ( ! ls . Value . Contains ( $ "{{{i}}}") )
509- {
510- continue ;
511- }
512-
513- var param = ls . Params . FirstOrDefault ( p => p . Index == i ) ;
514- parameters . Add ( param is null
515- ? new MethodParameter ( $ "arg{ i } ", "object?" )
516- : new MethodParameter ( param . Name , param . Type ) ) ;
517- }
518- return parameters ;
519- }
520-
521640 private static string Spacing ( int n )
522641 {
523642 Span < char > spaces = stackalloc char [ n * 4 ] ;
@@ -536,30 +655,12 @@ private static string Spacing(int n)
536655
537656 #region Classes
538657
539- public class MethodParameter
540- {
541- public string Name { get ; }
542- public string Type { get ; }
543-
544- public MethodParameter ( string name , string type )
545- {
546- Name = name ;
547- Type = type ;
548- }
549- }
550-
551658 public class LocalizableStringParam
552659 {
553- public int Index { get ; }
554- public string Name { get ; }
555- public string Type { get ; }
556-
557- public LocalizableStringParam ( int index , string name , string type )
558- {
559- Index = index ;
560- Name = name ;
561- Type = type ;
562- }
660+ public int Index { get ; set ; }
661+ public string Format { get ; set ; }
662+ public string Name { get ; set ; }
663+ public string Type { get ; set ; }
563664 }
564665
565666 public class LocalizableString
0 commit comments