A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Reflection;
5
6namespace Unity.VisualScripting
7{
8 public static class CSharpNameUtility
9 {
10 private static readonly Dictionary<Type, string> primitives = new Dictionary<Type, string>
11 {
12 { typeof(byte), "byte" },
13 { typeof(sbyte), "sbyte" },
14 { typeof(short), "short" },
15 { typeof(ushort), "ushort" },
16 { typeof(int), "int" },
17 { typeof(uint), "uint" },
18 { typeof(long), "long" },
19 { typeof(ulong), "ulong" },
20 { typeof(float), "float" },
21 { typeof(double), "double" },
22 { typeof(decimal), "decimal" },
23 { typeof(string), "string" },
24 { typeof(char), "char" },
25 { typeof(bool), "bool" },
26 { typeof(void), "void" },
27 { typeof(object), "object" },
28 };
29
30 public static readonly Dictionary<string, string> operators = new Dictionary<string, string>
31 {
32 { "op_Addition", "+" },
33 { "op_Subtraction", "-" },
34 { "op_Multiply", "*" },
35 { "op_Division", "/" },
36 { "op_Modulus", "%" },
37 { "op_ExclusiveOr", "^" },
38 { "op_BitwiseAnd", "&" },
39 { "op_BitwiseOr", "|" },
40 { "op_LogicalAnd", "&&" },
41 { "op_LogicalOr", "||" },
42 { "op_Assign", "=" },
43 { "op_LeftShift", "<<" },
44 { "op_RightShift", ">>" },
45 { "op_Equality", "==" },
46 { "op_GreaterThan", ">" },
47 { "op_LessThan", "<" },
48 { "op_Inequality", "!=" },
49 { "op_GreaterThanOrEqual", ">=" },
50 { "op_LessThanOrEqual", "<=" },
51 { "op_MultiplicationAssignment", "*=" },
52 { "op_SubtractionAssignment", "-=" },
53 { "op_ExclusiveOrAssignment", "^=" },
54 { "op_LeftShiftAssignment", "<<=" },
55 { "op_ModulusAssignment", "%=" },
56 { "op_AdditionAssignment", "+=" },
57 { "op_BitwiseAndAssignment", "&=" },
58 { "op_BitwiseOrAssignment", "|=" },
59 { "op_Comma", "," },
60 { "op_DivisionAssignment", "/=" },
61 { "op_Decrement", "--" },
62 { "op_Increment", "++" },
63 { "op_UnaryNegation", "-" },
64 { "op_UnaryPlus", "+" },
65 { "op_OnesComplement", "~" },
66 };
67
68 private static readonly HashSet<char> illegalTypeFileNameCharacters = new HashSet<char>()
69 {
70 '<',
71 '>',
72 '?',
73 ' ',
74 ',',
75 ':',
76 };
77
78 public static string CSharpName(this MemberInfo member, ActionDirection direction)
79 {
80 if (member is MethodInfo && ((MethodInfo)member).IsOperator())
81 {
82 return operators[member.Name] + " operator";
83 }
84
85 if (member is ConstructorInfo)
86 {
87 return "new " + member.DeclaringType.CSharpName();
88 }
89
90 if ((member is FieldInfo || member is PropertyInfo) && direction != ActionDirection.Any)
91 {
92 return $"{member.Name} ({direction.ToString().ToLower()})";
93 }
94
95 return member.Name;
96 }
97
98 public static string CSharpName(this Type type, bool includeGenericParameters = true)
99 {
100 return type.CSharpName(TypeQualifier.Name, includeGenericParameters);
101 }
102
103 public static string CSharpFullName(this Type type, bool includeGenericParameters = true)
104 {
105 return type.CSharpName(TypeQualifier.Namespace, includeGenericParameters);
106 }
107
108 public static string CSharpUniqueName(this Type type, bool includeGenericParameters = true)
109 {
110 return type.CSharpName(TypeQualifier.GlobalNamespace, includeGenericParameters);
111 }
112
113 public static string CSharpFileName(this Type type, bool includeNamespace, bool includeGenericParameters = false)
114 {
115 var fileName = type.CSharpName(includeNamespace ? TypeQualifier.Namespace : TypeQualifier.Name, includeGenericParameters);
116
117 if (!includeGenericParameters && type.IsGenericType && fileName.Contains('<'))
118 {
119 fileName = fileName.Substring(0, fileName.IndexOf('<'));
120 }
121
122 fileName = fileName.ReplaceMultiple(illegalTypeFileNameCharacters, '_')
123 .Trim('_')
124 .RemoveConsecutiveCharacters('_');
125
126 return fileName;
127 }
128
129 private static string CSharpName(this Type type, TypeQualifier qualifier, bool includeGenericParameters = true)
130 {
131 if (primitives.ContainsKey(type))
132 {
133 return primitives[type];
134 }
135 else if (type.IsGenericParameter)
136 {
137 return includeGenericParameters ? type.Name : "";
138 }
139 else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
140 {
141 var nonNullable = Nullable.GetUnderlyingType(type);
142
143 var underlyingName = nonNullable.CSharpName(qualifier, includeGenericParameters);
144
145 return underlyingName + "?";
146 }
147 else
148 {
149 var name = type.Name;
150
151 if (type.IsGenericType && name.Contains('`'))
152 {
153 name = name.Substring(0, name.IndexOf('`'));
154 }
155
156 var genericArguments = (IEnumerable<Type>)type.GetGenericArguments();
157
158 if (type.IsNested)
159 {
160 name = type.DeclaringType.CSharpName(qualifier, includeGenericParameters) + "." + name;
161
162 if (type.DeclaringType.IsGenericType)
163 {
164 genericArguments.Skip(type.DeclaringType.GetGenericArguments().Length);
165 }
166 }
167
168 if (!type.IsNested)
169 {
170 if ((qualifier == TypeQualifier.Namespace || qualifier == TypeQualifier.GlobalNamespace) && type.Namespace != null)
171 {
172 name = type.Namespace + "." + name;
173 }
174
175 if (qualifier == TypeQualifier.GlobalNamespace)
176 {
177 name = "global::" + name;
178 }
179 }
180
181 if (genericArguments.Any())
182 {
183 name += "<";
184 name += string.Join(includeGenericParameters ? ", " : ",", genericArguments.Select(t => t.CSharpName(qualifier, includeGenericParameters)).ToArray());
185 name += ">";
186 }
187
188 return name;
189 }
190 }
191 }
192}