|
6 | 6 | using System.Collections.Immutable; |
7 | 7 | using System; |
8 | 8 | using System.Collections.Generic; |
| 9 | +using System.Globalization; |
9 | 10 |
|
10 | 11 | namespace AutoRegisterInject; |
11 | 12 |
|
@@ -271,9 +272,118 @@ private static string GetInterfaceMemberSource(ISymbol member) |
271 | 272 | private static string GetMethodSource(IMethodSymbol method) |
272 | 273 | { |
273 | 274 | var returnType = method.ReturnType.ToDisplayString(); |
274 | | - var parameters = string.Join(", ", method.Parameters.Select(static parameter => $"{parameter.Type.ToDisplayString()} {parameter.Name}")); |
| 275 | + var typeParameters = method.TypeParameters.Length == 0 |
| 276 | + ? string.Empty |
| 277 | + : $"<{string.Join(", ", method.TypeParameters.Select(static typeParameter => typeParameter.Name))}>"; |
| 278 | + var parameters = string.Join(", ", method.Parameters.Select(GetParameterSource)); |
| 279 | + var constraints = GetTypeParameterConstraintsSource(method.TypeParameters); |
275 | 280 |
|
276 | | - return $" {returnType} {method.Name}({parameters});"; |
| 281 | + return $" {returnType} {method.Name}{typeParameters}({parameters}){constraints};"; |
| 282 | + } |
| 283 | + |
| 284 | + private static string GetParameterSource(IParameterSymbol parameter) |
| 285 | + { |
| 286 | + var modifiers = GetParameterModifiersSource(parameter); |
| 287 | + var defaultValue = GetParameterDefaultValueSource(parameter); |
| 288 | + |
| 289 | + return $"{modifiers}{parameter.Type.ToDisplayString()} {parameter.Name}{defaultValue}"; |
| 290 | + } |
| 291 | + |
| 292 | + private static string GetParameterModifiersSource(IParameterSymbol parameter) |
| 293 | + { |
| 294 | + var paramsModifier = parameter.IsParams ? "params " : string.Empty; |
| 295 | + var refModifier = parameter.RefKind switch |
| 296 | + { |
| 297 | + RefKind.Ref => "ref ", |
| 298 | + RefKind.Out => "out ", |
| 299 | + RefKind.In => "in ", |
| 300 | + _ => string.Empty, |
| 301 | + }; |
| 302 | + |
| 303 | + return paramsModifier + refModifier; |
| 304 | + } |
| 305 | + |
| 306 | + private static string GetParameterDefaultValueSource(IParameterSymbol parameter) |
| 307 | + { |
| 308 | + var syntax = parameter.DeclaringSyntaxReferences |
| 309 | + .Select(static reference => reference.GetSyntax()) |
| 310 | + .OfType<ParameterSyntax>() |
| 311 | + .FirstOrDefault(); |
| 312 | + |
| 313 | + if (syntax?.Default is not null) |
| 314 | + { |
| 315 | + return $" = {syntax.Default.Value}"; |
| 316 | + } |
| 317 | + |
| 318 | + if (!parameter.HasExplicitDefaultValue) |
| 319 | + { |
| 320 | + return string.Empty; |
| 321 | + } |
| 322 | + |
| 323 | + return parameter.ExplicitDefaultValue is null |
| 324 | + ? " = null" |
| 325 | + : $" = {FormatDefaultValue(parameter.ExplicitDefaultValue)}"; |
| 326 | + } |
| 327 | + |
| 328 | + private static string FormatDefaultValue(object value) |
| 329 | + { |
| 330 | + return value switch |
| 331 | + { |
| 332 | + bool boolValue => boolValue ? "true" : "false", |
| 333 | + char charValue => $"'{charValue}'", |
| 334 | + string stringValue => $"\"{stringValue.Replace("\\", "\\\\").Replace("\"", "\\\"")}\"", |
| 335 | + float floatValue => $"{floatValue.ToString("R", CultureInfo.InvariantCulture)}F", |
| 336 | + double doubleValue => $"{doubleValue.ToString("R", CultureInfo.InvariantCulture)}D", |
| 337 | + decimal decimalValue => $"{decimalValue.ToString(CultureInfo.InvariantCulture)}M", |
| 338 | + IFormattable formattable => formattable.ToString(null, CultureInfo.InvariantCulture), |
| 339 | + _ => value.ToString(), |
| 340 | + }; |
| 341 | + } |
| 342 | + |
| 343 | + private static string GetTypeParameterConstraintsSource(ImmutableArray<ITypeParameterSymbol> typeParameters) |
| 344 | + { |
| 345 | + var constraints = typeParameters |
| 346 | + .Select(GetTypeParameterConstraintSource) |
| 347 | + .Where(static constraint => !string.IsNullOrWhiteSpace(constraint)) |
| 348 | + .ToArray(); |
| 349 | + |
| 350 | + return constraints.Length == 0 |
| 351 | + ? string.Empty |
| 352 | + : " " + string.Join(" ", constraints); |
| 353 | + } |
| 354 | + |
| 355 | + private static string GetTypeParameterConstraintSource(ITypeParameterSymbol typeParameter) |
| 356 | + { |
| 357 | + var constraints = new List<string>(); |
| 358 | + |
| 359 | + if (typeParameter.HasUnmanagedTypeConstraint) |
| 360 | + { |
| 361 | + constraints.Add("unmanaged"); |
| 362 | + } |
| 363 | + else if (typeParameter.HasValueTypeConstraint) |
| 364 | + { |
| 365 | + constraints.Add("struct"); |
| 366 | + } |
| 367 | + else if (typeParameter.HasReferenceTypeConstraint) |
| 368 | + { |
| 369 | + constraints.Add("class"); |
| 370 | + } |
| 371 | + |
| 372 | + if (typeParameter.HasNotNullConstraint) |
| 373 | + { |
| 374 | + constraints.Add("notnull"); |
| 375 | + } |
| 376 | + |
| 377 | + constraints.AddRange(typeParameter.ConstraintTypes.Select(static type => type.ToDisplayString())); |
| 378 | + |
| 379 | + if (typeParameter.HasConstructorConstraint) |
| 380 | + { |
| 381 | + constraints.Add("new()"); |
| 382 | + } |
| 383 | + |
| 384 | + return constraints.Count == 0 |
| 385 | + ? string.Empty |
| 386 | + : $"where {typeParameter.Name} : {string.Join(", ", constraints)}"; |
277 | 387 | } |
278 | 388 |
|
279 | 389 | private static string GetPropertySource(IPropertySymbol property) |
|
0 commit comments