Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
EnumerableRewriter.cs
Go to the documentation of this file.
7
8namespace System.Linq;
9
11{
13
15
17
18 [RequiresUnreferencedCode("Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime.")]
20 {
21 }
22
23 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "This class's ctor is annotated as RequiresUnreferencedCode.")]
25 {
26 Expression expression = Visit(m.Object);
28 if (expression != m.Object || readOnlyCollection != m.Arguments)
29 {
30 MethodInfo method = m.Method;
31 Type[] typeArgs = (method.IsGenericMethod ? method.GetGenericArguments() : null);
32 if ((method.IsStatic || method.DeclaringType.IsAssignableFrom(expression.Type)) && ArgsMatch(method, readOnlyCollection, typeArgs))
33 {
35 }
36 if (method.DeclaringType == typeof(Queryable))
37 {
41 }
45 }
46 return m;
47 }
48
50 {
51 ParameterInfo[] parameters = mi.GetParameters();
52 if (parameters.Length != 0)
53 {
55 int i = 0;
56 for (int num = parameters.Length; i < num; i++)
57 {
59 ParameterInfo parameterInfo = parameters[i];
61 if (list == null && expression != argList[i])
62 {
64 for (int j = 0; j < i; j++)
65 {
66 list.Add(argList[j]);
67 }
68 }
69 list?.Add(expression);
70 }
71 if (list != null)
72 {
73 argList = list.AsReadOnly();
74 }
75 }
76 return argList;
77 }
78
80 {
82 while (true)
83 {
84 if (type.IsAssignableFrom(expression2.Type))
85 {
86 return expression2;
87 }
88 if (expression2.NodeType != ExpressionType.Quote)
89 {
90 break;
91 }
93 }
94 if (!type.IsAssignableFrom(expression2.Type) && type.IsArray && expression2.NodeType == ExpressionType.NewArrayInit)
95 {
97 if (type.IsAssignableFrom(c))
98 {
102 int i = 0;
103 for (int count = newArrayExpression.Expressions.Count; i < count; i++)
104 {
106 }
108 }
109 }
110 return expression;
111 }
112
114 {
115 return node;
116 }
117
118 private static Type GetPublicType(Type t)
119 {
121 {
122 return typeof(IGrouping<, >).MakeGenericType(t.GetGenericArguments());
123 }
124 if (!t.IsNestedPrivate)
125 {
126 return t;
127 }
129 {
130 return interfaceType2;
131 }
132 if (typeof(IEnumerable).IsAssignableFrom(t))
133 {
134 return typeof(IEnumerable);
135 }
136 return t;
137 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification = "The IGrouping<,> is kept since it's directly referenced hereand so it will also be preserved in all places where it's implemented.The GetInterfaces may return less after trimming but it will includethe IGrouping<,> if it was there before trimming, which is enough for thismethod to work.")]
138 static bool ImplementsIGrouping(Type type)
139 {
140 return type.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IGrouping<, >));
141 }
142 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "The IEnumerable<> is kept since it's directly referenced hereand so it will also be preserved in all places where it's implemented.The GetInterfaces may return less after trimming but it will includethe IEnumerable<> if it was there before trimming, which is enough for thismethod to work.")]
144 {
145 Type[] interfaces = type.GetInterfaces();
146 foreach (Type type2 in interfaces)
147 {
148 if (type2.IsGenericType && type2.GetGenericTypeDefinition() == typeof(IEnumerable<>))
149 {
151 return true;
152 }
153 }
154 interfaceType = null;
155 return false;
156 }
157 }
158
160 {
161 if (_equivalentTypeCache == null)
162 {
164 {
165 {
168 },
169 {
172 }
173 };
174 }
176 {
178 if (publicType.IsInterface && publicType.IsGenericType)
179 {
180 Type genericTypeDefinition = publicType.GetGenericTypeDefinition();
182 {
184 }
186 {
187 value = typeof(IOrderedEnumerable<>).MakeGenericType(publicType.GenericTypeArguments[0]);
188 }
190 {
192 }
194 {
195 value = typeof(IEnumerable<>).MakeGenericType(publicType.GenericTypeArguments[0]);
196 }
197 }
198 if (value == null)
199 {
201 }
203 }
204 return value;
205 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "The enumerable interface type (IOrderedQueryable<>, IOrderedEnumerable<>, IQueryable<> and IEnumerable<>) is kept since it's directly referenced hereand so it will also be preserved in all places where it's implemented.The GetInterfaces may return less after trimming but it will includethe enumerable interface type if it was there before trimming, which is enough for thismethod to work.")]
207 {
208 Type[] interfaces = sourceType.GetInterfaces();
209 var source = (from i in interfaces
210 where i.IsGenericType && i.GenericTypeArguments.Length == 1
211 select new
212 {
213 Info = i,
214 GenType = i.GetGenericTypeDefinition()
215 }).ToArray();
216 Type type2 = (from i in source
217 where i.GenType == typeof(IOrderedQueryable<>) || i.GenType == typeof(IOrderedEnumerable<>)
218 select i.Info.GenericTypeArguments[0]).Distinct().SingleOrDefault();
219 if (type2 != null)
220 {
221 return typeof(IOrderedEnumerable<>).MakeGenericType(type2);
222 }
223 type2 = (from i in source
224 where i.GenType == typeof(IQueryable<>) || i.GenType == typeof(IEnumerable<>)
225 select i.Info.GenericTypeArguments[0]).Distinct().Single();
226 return typeof(IEnumerable<>).MakeGenericType(type2);
227 }
228 }
229
231 {
233 {
234 if (enumerableQuery.Enumerable != null)
235 {
236 Type publicType = GetPublicType(enumerableQuery.Enumerable.GetType());
237 return Expression.Constant(enumerableQuery.Enumerable, publicType);
238 }
240 if (expression != c)
241 {
242 return Visit(expression);
243 }
244 }
245 return c;
246 }
247
248 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "Enumerable methods don't have trim annotations.")]
250 {
251 if (s_seqMethods == null)
252 {
254 }
255 MethodInfo methodInfo = s_seqMethods[name].FirstOrDefault((MethodInfo m) => ArgsMatch(m, args, typeArgs));
256 if (typeArgs != null)
257 {
258 return methodInfo.MakeGenericMethod(typeArgs);
259 }
260 return methodInfo;
261 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "This method is intentionally hiding the Enumerable type from the trimmer so it doesn't preserve all Enumerable's methods. This is safe because all Queryable methods have a DynamicDependency to the corresponding Enumerable method.")]
263 {
264 return type.GetMethods(BindingFlags.Static | BindingFlags.Public);
265 }
266 }
267
268 [RequiresUnreferencedCode("Enumerating in-memory collections as IQueryable can require unreferenced code because expressions referencing IQueryable extension methods can get rebound to IEnumerable extension methods. The IEnumerable extension methods could be trimmed causing the application to fail at runtime.")]
270 {
271 using (IEnumerator<MethodInfo> enumerator = (from m in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
272 where m.Name == name
273 select m).GetEnumerator())
274 {
275 if (!enumerator.MoveNext())
276 {
277 throw Error.NoMethodOnType(name, type);
278 }
279 do
280 {
281 MethodInfo current = enumerator.Current;
282 if (ArgsMatch(current, args, typeArgs))
283 {
284 return (typeArgs != null) ? current.MakeGenericMethod(typeArgs) : current;
285 }
286 }
287 while (enumerator.MoveNext());
288 }
290 }
291
293 {
294 ParameterInfo[] array = m.GetParameters();
295 if (array.Length != args.Count)
296 {
297 return false;
298 }
299 if (!m.IsGenericMethod && typeArgs != null && typeArgs.Length != 0)
300 {
301 return false;
302 }
303 if (!m.IsGenericMethodDefinition && m.IsGenericMethod && m.ContainsGenericParameters)
304 {
305 m = m.GetGenericMethodDefinition();
306 }
307 if (m.IsGenericMethodDefinition)
308 {
309 if (typeArgs == null || typeArgs.Length == 0)
310 {
311 return false;
312 }
313 if (m.GetGenericArguments().Length != typeArgs.Length)
314 {
315 return false;
316 }
318 }
319 int i = 0;
320 for (int count = args.Count; i < count; i++)
321 {
322 Type type = array[i].ParameterType;
323 if (type == null)
324 {
325 return false;
326 }
327 if (type.IsByRef)
328 {
330 }
332 if (!type.IsAssignableFrom(expression.Type))
333 {
334 if (expression.NodeType == ExpressionType.Quote)
335 {
337 }
338 if (!type.IsAssignableFrom(expression.Type) && !type.IsAssignableFrom(StripExpression(expression.Type)))
339 {
340 return false;
341 }
342 }
343 }
344 return true;
345 [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "MakeGenericMethod is only called to get the parameter types, which are only used to make a 'match' decision. The generic method is not invoked.")]
347 {
348 return method.MakeGenericMethod(genericTypes).GetParameters();
349 }
350 }
351
353 {
354 bool isArray = type.IsArray;
355 Type type2 = (isArray ? type.GetElementType() : type);
357 if (type3 != null)
358 {
359 type2 = type3.GetGenericArguments()[0];
360 }
361 if (isArray)
362 {
363 int arrayRank = type.GetArrayRank();
364 if (arrayRank != 1)
365 {
366 return type2.MakeArrayType(arrayRank);
367 }
368 return type2.MakeArrayType();
369 }
370 return type;
371 }
372
374 {
375 Type type = c.Type;
376 if (!typeof(IQueryable).IsAssignableFrom(type))
377 {
378 return base.VisitConditional(c);
379 }
383 Type type2 = expression.Type;
384 Type type3 = expression2.Type;
385 if (type2.IsAssignableFrom(type3))
386 {
388 }
389 if (type3.IsAssignableFrom(type2))
390 {
392 }
394 }
395
397 {
398 Type type = node.Type;
399 if (!typeof(IQueryable).IsAssignableFrom(type))
400 {
401 return base.VisitBlock(node);
402 }
404 ReadOnlyCollection<ParameterExpression> variables = VisitAndConvert(node.Variables, "EnumerableRewriter.VisitBlock");
405 if (type == node.Expressions.Last().Type)
406 {
408 }
410 }
411
413 {
414 Type type = node.Value.Type;
415 if (!typeof(IQueryable).IsAssignableFrom(type))
416 {
417 return base.VisitGoto(node);
418 }
419 LabelTarget target = VisitLabelTarget(node.Target);
421 return Expression.MakeGoto(node.Kind, target, expression, GetEquivalentType(typeof(EnumerableQuery).IsAssignableFrom(type) ? expression.Type : type));
422 }
423
425 {
427 if (_targetCache == null)
428 {
430 }
432 {
433 return value;
434 }
435 Type type = node.Type;
436 value = (typeof(IQueryable).IsAssignableFrom(type) ? Expression.Label(GetEquivalentType(type), node.Name) : base.VisitLabelTarget(node));
438 return value;
439 }
440}
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
bool ICollection< KeyValuePair< TKey, TValue > >. Contains(KeyValuePair< TKey, TValue > keyValuePair)
void Add(TKey key, TValue value)
static MethodInfo FindEnumerableMethodForQueryable(string name, ReadOnlyCollection< Expression > args, params Type[] typeArgs)
Dictionary< LabelTarget, LabelTarget > _targetCache
Dictionary< Type, Type > _equivalentTypeCache
static bool ArgsMatch(MethodInfo m, ReadOnlyCollection< Expression > args, Type[] typeArgs)
override Expression VisitConditional(ConditionalExpression c)
static Type StripExpression(Type type)
override Expression VisitBlock(BlockExpression node)
override Expression VisitLambda< T >(Expression< T > node)
static ILookup< string, MethodInfo > s_seqMethods
static MethodInfo FindMethod(Type type, string name, ReadOnlyCollection< Expression > args, Type[] typeArgs)
override Expression VisitConstant(ConstantExpression c)
Expression FixupQuotedExpression(Type type, Expression expression)
override Expression VisitMethodCall(MethodCallExpression m)
override Expression VisitGoto(GotoExpression node)
ReadOnlyCollection< Expression > FixupQuotedArgs(MethodInfo mi, ReadOnlyCollection< Expression > argList)
override LabelTarget VisitLabelTarget(LabelTarget node)
static Exception NoMethodOnType(string name, object type)
Definition Error.cs:25
static Exception NoMethodOnTypeMatchingArguments(string name, object type)
Definition Error.cs:30
virtual ? Expression Visit(Expression? node)
static ConstantExpression Constant(object? value)
static BlockExpression Block(Expression arg0, Expression arg1)
static MethodCallExpression Call(MethodInfo method)
static LabelExpression Label(LabelTarget target)
static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse)
static GotoExpression MakeGoto(GotoExpressionKind kind, LabelTarget target, Expression? value, Type type)
static NewArrayExpression NewArrayInit(Type type, params Expression[] initializers)
static Type FindGenericType(Type definition, Type type)
Definition TypeHelper.cs:8
virtual MethodInfo MakeGenericMethod(params Type[] typeArguments)
Definition MethodInfo.cs:41
Type? GetElementType()
virtual Type[] GetGenericArguments()
Definition Type.cs:500
bool IsNestedPrivate
Definition Type.cs:203
virtual bool IsGenericType
Definition Type.cs:111
Type[] GetInterfaces()