mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-01 01:25:27 +08:00 
			
		
		
		
	Making tuples pretty too
This commit is contained in:
		 Phil Scott
					Phil Scott
				
			
				
					committed by
					
						 Patrik Svensson
						Patrik Svensson
					
				
			
			
				
	
			
			
			 Patrik Svensson
						Patrik Svensson
					
				
			
						parent
						
							e8eb5b85b9
						
					
				
				
					commit
					74a2e10ff0
				
			| @@ -276,16 +276,85 @@ internal static class ExceptionFormatter | ||||
|         var prefix = GetPrefix(parameter); | ||||
|         var parameterType = parameter.ParameterType; | ||||
|  | ||||
|         if (parameterType.IsByRef && parameterType.GetElementType() is { } elementType) | ||||
|         string typeName; | ||||
|         if (parameterType.IsGenericType && TryGetTupleName(parameter, parameterType, out var s)) | ||||
|         { | ||||
|             parameterType = elementType; | ||||
|             typeName = s; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (parameterType.IsByRef && parameterType.GetElementType() is { } elementType) | ||||
|             { | ||||
|                 parameterType = elementType; | ||||
|             } | ||||
|  | ||||
|             typeName = TypeNameHelper.GetTypeDisplayName(parameterType); | ||||
|         } | ||||
|  | ||||
|         var typeName = TypeNameHelper.GetTypeDisplayName(parameterType, false, true); | ||||
|  | ||||
|         return string.IsNullOrWhiteSpace(prefix) ? typeName : $"{prefix} {typeName}"; | ||||
|     } | ||||
|  | ||||
|     private static bool TryGetTupleName(ParameterInfo parameter, Type parameterType, [NotNullWhen(true)] out string? tupleName) | ||||
|     { | ||||
|         var customAttribs = parameter.GetCustomAttributes(inherit: false); | ||||
|  | ||||
|         var tupleNameAttribute = customAttribs | ||||
|             .OfType<Attribute>() | ||||
|             .FirstOrDefault(a => | ||||
|             { | ||||
|                 var attributeType = a.GetType(); | ||||
|                 return attributeType.Namespace == "System.Runtime.CompilerServices" && | ||||
|                        attributeType.Name == "TupleElementNamesAttribute"; | ||||
|             }); | ||||
|  | ||||
|         if (tupleNameAttribute != null) | ||||
|         { | ||||
|             var propertyInfo = tupleNameAttribute.GetType() | ||||
|                 .GetProperty("TransformNames", BindingFlags.Instance | BindingFlags.Public)!; | ||||
|             var tupleNames = propertyInfo.GetValue(tupleNameAttribute) as IList<string>; | ||||
|             if (tupleNames?.Count > 0) | ||||
|             { | ||||
|                 var args = parameterType.GetGenericArguments(); | ||||
|                 var sb = new StringBuilder(); | ||||
|  | ||||
|                 sb.Append('('); | ||||
|                 for (var i = 0; i < args.Length; i++) | ||||
|                 { | ||||
|                     if (i > 0) | ||||
|                     { | ||||
|                         sb.Append(", "); | ||||
|                     } | ||||
|  | ||||
|                     sb.Append(TypeNameHelper.GetTypeDisplayName(args[i])); | ||||
|  | ||||
|                     if (i >= tupleNames.Count) | ||||
|                     { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     var argName = tupleNames[i]; | ||||
|  | ||||
|                     sb.Append(' '); | ||||
|                     sb.Append(argName); | ||||
|                 } | ||||
|  | ||||
|                 sb.Append(')'); | ||||
|  | ||||
|                 tupleName = sb.ToString(); | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         else if (parameterType.Namespace == "System" && parameterType.Name.Contains("ValueTuple`")) | ||||
|         { | ||||
|             var args = parameterType.GetGenericArguments().Select(i => TypeNameHelper.GetTypeDisplayName(i)); | ||||
|             tupleName = $"({string.Join(", ", args)})"; | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         tupleName = null; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     private static string GetMethodName(ref MethodBase method, out bool isAsync) | ||||
|     { | ||||
|         var declaringType = method.DeclaringType; | ||||
|   | ||||
| @@ -40,35 +40,13 @@ internal static class TypeNameHelper | ||||
|     /// <param name="fullName"><c>true</c> to print a fully qualified name.</param> | ||||
|     /// <param name="includeGenericParameterNames"><c>true</c> to include generic parameter names.</param> | ||||
|     /// <returns>The pretty printed type name.</returns> | ||||
|     public static string GetTypeDisplayName(Type type, bool fullName = true, bool includeGenericParameterNames = false) | ||||
|     public static string GetTypeDisplayName(Type type, bool fullName = false, bool includeGenericParameterNames = true) | ||||
|     { | ||||
|         var builder = new StringBuilder(); | ||||
|         ProcessType(builder, type, new DisplayNameOptions(fullName, includeGenericParameterNames)); | ||||
|         return builder.ToString(); | ||||
|     } | ||||
|  | ||||
|     public static StringBuilder AppendTypeDisplayName(this StringBuilder builder, Type type, bool fullName = true, | ||||
|         bool includeGenericParameterNames = false) | ||||
|     { | ||||
|         ProcessType(builder, type, new DisplayNameOptions(fullName, includeGenericParameterNames)); | ||||
|         return builder; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Returns a name of given generic type without '`'. | ||||
|     /// </summary> | ||||
|     public static string GetTypeNameForGenericType(Type type) | ||||
|     { | ||||
|         if (!type.IsGenericType) | ||||
|         { | ||||
|             throw new ArgumentException("The given type should be generic", nameof(type)); | ||||
|         } | ||||
|  | ||||
|         var genericPartIndex = type.Name.IndexOf('`'); | ||||
|  | ||||
|         return (genericPartIndex >= 0) ? type.Name.Substring(0, genericPartIndex) : type.Name; | ||||
|     } | ||||
|  | ||||
|     private static void ProcessType(StringBuilder builder, Type type, DisplayNameOptions options) | ||||
|     { | ||||
|         if (type.IsGenericType) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user