@@ -47,6 +47,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
4747 using System;
4848 using System.Collections.Generic;
4949 using System.Diagnostics.CodeAnalysis;
50+ using System.Globalization;
5051 using System.Linq;
5152 using System.Reflection;
5253 using System.Text;
@@ -137,7 +138,15 @@ public static string CreateDocumentationId(this PropertyInfo property)
137138 if (indexParams.Length > 0)
138139 {
139140 sb.Append('(');
140- sb.Append(string.Join(",", indexParams.Select(p => GetTypeDocId(p.ParameterType, includeGenericArguments: true, omitGenericArity: false))));
141+ for (int i = 0; i < indexParams.Length; i++)
142+ {
143+ if (i > 0)
144+ {
145+ sb.Append(',');
146+ }
147+
148+ sb.Append(GetTypeDocId(indexParams[i].ParameterType, includeGenericArguments: true, omitGenericArity: false));
149+ }
141150 sb.Append(')');
142151 }
143152
@@ -152,7 +161,6 @@ public static string CreateDocumentationId(this PropertyInfo property)
152161 /// </summary>
153162 public static string CreateDocumentationId(this MethodInfo method)
154163 {
155- System.Diagnostics.Debugger.Break();
156164 if (method == null)
157165 {
158166 throw new ArgumentNullException(nameof(method));
@@ -180,7 +188,7 @@ public static string CreateDocumentationId(this MethodInfo method)
180188 if (method.IsGenericMethod)
181189 {
182190 sb.Append("``");
183- sb.Append( method.GetGenericArguments().Length);
191+ sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", method.GetGenericArguments().Length);
184192 }
185193 }
186194
@@ -189,7 +197,16 @@ public static string CreateDocumentationId(this MethodInfo method)
189197 if (parameters.Length > 0)
190198 {
191199 sb.Append('(');
192- sb.Append(string.Join(",", parameters.Select(p => GetTypeDocId(p.ParameterType, includeGenericArguments: true, omitGenericArity: true))));
200+ for (int i = 0; i < parameters.Length; i++)
201+ {
202+ if (i > 0)
203+ {
204+ sb.Append(',');
205+ }
206+
207+ // Omit the generic arity for the parameter type.
208+ sb.Append(GetTypeDocId(parameters[i].ParameterType, includeGenericArguments: true, omitGenericArity: true));
209+ }
193210 sb.Append(')');
194211 }
195212
@@ -234,40 +251,70 @@ private static string GetTypeDocId(Type type, bool includeGenericArguments, bool
234251 if (type.IsArray && type.GetElementType() is { } elementType)
235252 {
236253 int rank = type.GetArrayRank();
237- string elementTypeId = GetTypeDocId(elementType, includeGenericArguments, omitGenericArity);
238- return rank == 1 ? elementTypeId + "[]" : elementTypeId + "[" + new string(',', rank - 1) + "]";
254+ var sb = new StringBuilder(GetTypeDocId(elementType, includeGenericArguments, omitGenericArity));
255+ if (rank > 1)
256+ {
257+ sb.Append('[');
258+ sb.Append(',', rank - 1);
259+ sb.Append(']');
260+ }
261+ else
262+ {
263+ sb.Append("[]");
264+ }
239265 }
240266
241267 if (type.IsGenericType)
242268 {
243- // Get the generic type definition.
244269 Type genericDef = type.GetGenericTypeDefinition();
245- string defName = genericDef.FullName != null
246- ? genericDef.FullName.Replace('+', '.')
247- : genericDef.Name ;
248- // Remove any existing generic arity marker.
249- int backtickIndex = defName.IndexOf('`');
250- if (backtickIndex > = 0)
270+ string fullName = genericDef.FullName ?? genericDef.Name;
271+
272+ var sb = new StringBuilder(fullName.Length) ;
273+
274+ // Replace '+' with '.' for nested types
275+ for (var i = 0; i < fullName.Length; i++ )
251276 {
252- defName = defName.Substring(0, backtickIndex);
277+ char c = fullName[i];
278+ if (c == '+')
279+ {
280+ sb.Append('.');
281+ }
282+ else if (c == '`')
283+ {
284+ break;
285+ }
286+ else
287+ {
288+ sb.Append(c);
289+ }
253290 }
254- // Append the generic arity unless omitted.
291+
255292 if (!omitGenericArity)
256293 {
257294 int arity = genericDef.GetGenericArguments().Length;
258- defName += "`" + arity;
295+ sb.Append('`');
296+ sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", arity);
259297 }
260- // If requested, append the constructed generic arguments.
298+
261299 if (includeGenericArguments && !type.IsGenericTypeDefinition)
262300 {
263- Type[] typeArgs = type.GetGenericArguments();
264- string args = string.Join(",", typeArgs.Select(t => GetTypeDocId(t, includeGenericArguments, omitGenericArity)));
265- return defName + "{" + args + "}";
266- }
267- else
268- {
269- return defName;
301+ var typeArgs = type.GetGenericArguments();
302+ sb.Append('{');
303+
304+ for (int i = 0; i < typeArgs.Length; i++)
305+ {
306+ if (i > 0)
307+ {
308+ sb.Append(',');
309+ }
310+
311+ sb.Append(GetTypeDocId(typeArgs[i], includeGenericArguments, omitGenericArity));
312+ }
313+
314+ sb.Append('}');
270315 }
316+
317+ return sb.ToString();
271318 }
272319
273320 // For non-generic types, use FullName (if available) and replace nested type separators.
0 commit comments