1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.Diagnostics.CodeAnalysis;
9 using System.Linq;
10 using System.Reflection;
11 using System.Runtime.CompilerServices;
12 using System.Runtime.InteropServices;
13 using Microsoft.CSharp.RuntimeBinder.Semantics;
14 using Microsoft.CSharp.RuntimeBinder.Syntax;
15 
16 namespace Microsoft.CSharp.RuntimeBinder
17 {
18     internal sealed class SymbolTable
19     {
20         /////////////////////////////////////////////////////////////////////////////////
21         // Members
22         private readonly HashSet<Type> _typesWithConversionsLoaded = new HashSet<Type>();
23         private readonly HashSet<NameHashKey> _namesLoadedForEachType = new HashSet<NameHashKey>();
24 
25         // Members from the managed binder.
26         private readonly SYMTBL _symbolTable;
27         private readonly SymFactory _symFactory;
28         private readonly TypeManager _typeManager;
29         private readonly BSYMMGR _bsymmgr;
30         private readonly CSemanticChecker _semanticChecker;
31 
32         /////////////////////////////////////////////////////////////////////////////////
33 
34         private sealed class NameHashKey : IEquatable<NameHashKey>
35         {
36             internal readonly Type type;
37             internal readonly string name;
38 
NameHashKey(Type type, string name)39             public NameHashKey(Type type, string name)
40             {
41                 this.type = type;
42                 this.name = name;
43             }
44 
45             public bool Equals(NameHashKey other) => other != null && type.Equals(other.type) && name.Equals(other.name);
46 
47 #if  DEBUG
48             [ExcludeFromCodeCoverage] // Typed overload should always be the method called.
49 #endif
Equals(object obj)50             public override bool Equals(object obj)
51             {
52                 Debug.Fail("Sub-optimal overload called. Check if this can be avoided.");
53                 return Equals(obj as NameHashKey);
54             }
55 
GetHashCode()56             public override int GetHashCode()
57             {
58                 return type.GetHashCode() ^ name.GetHashCode();
59             }
60         }
61 
62         /////////////////////////////////////////////////////////////////////////////////
63 
SymbolTable( SYMTBL symTable, SymFactory symFactory, TypeManager typeManager, BSYMMGR bsymmgr, CSemanticChecker semanticChecker)64         internal SymbolTable(
65             SYMTBL symTable,
66             SymFactory symFactory,
67             TypeManager typeManager,
68             BSYMMGR bsymmgr,
69             CSemanticChecker semanticChecker)
70         {
71             _symbolTable = symTable;
72             _symFactory = symFactory;
73             _typeManager = typeManager;
74             _bsymmgr = bsymmgr;
75             _semanticChecker = semanticChecker;
76 
77             // Now populate object.
78             LoadSymbolsFromType(typeof(object));
79         }
80 
81         /////////////////////////////////////////////////////////////////////////////////
82 
PopulateSymbolTableWithName( string name, IEnumerable<Type> typeArguments, Type callingType)83         internal void PopulateSymbolTableWithName(
84             string name,
85             IEnumerable<Type> typeArguments,
86             Type callingType)
87         {
88             // The first argument is the object that we're calling off of.
89             if (callingType.IsGenericType)
90             {
91                 callingType = callingType.GetGenericTypeDefinition();
92             }
93 
94             if (name == SpecialNames.Indexer)
95             {
96                 // If we don't find an indexer name for this type, use SpecialNames.Indexer as a key on the
97                 // empty results we'll get, so that those empty results gets cached.
98                 name = callingType.GetIndexerName() ?? SpecialNames.Indexer;
99             }
100 
101             NameHashKey key = new NameHashKey(callingType, name);
102 
103             // If we've already populated this name/type pair, then just leave.
104             if (_namesLoadedForEachType.Contains(key))
105             {
106                 return;
107             }
108 
109             // Add the names.
110             AddNamesOnType(key);
111 
112             // Take each type argument and load its conversions into the symbol table.
113             if (typeArguments != null)
114             {
115                 foreach (Type o in typeArguments)
116                 {
117                     AddConversionsForType(o);
118                 }
119             }
120         }
121 
122         /////////////////////////////////////////////////////////////////////////////////
123 
LookupMember( string name, Expr callingObject, ParentSymbol context, int arity, MemberLookup mem, bool allowSpecialNames, bool requireInvocable)124         internal SymWithType LookupMember(
125             string name,
126             Expr callingObject,
127             ParentSymbol context,
128             int arity,
129             MemberLookup mem,
130             bool allowSpecialNames,
131             bool requireInvocable)
132         {
133             CType type = callingObject.Type;
134 
135             if (type is ArrayType)
136             {
137                 type = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_ARRAY);
138             }
139             if (type is NullableType nub)
140             {
141                 type = nub.GetAts();
142             }
143 
144             if (!mem.Lookup(
145                 _semanticChecker,
146                 type,
147                 callingObject,
148                 context,
149                 GetName(name),
150                 arity,
151                 (allowSpecialNames ? 0 : MemLookFlags.UserCallable) |
152                     (name == SpecialNames.Indexer ? MemLookFlags.Indexer : 0) |
153                     (name == SpecialNames.Constructor ? MemLookFlags.Ctor : 0) |
154                     (requireInvocable ? MemLookFlags.MustBeInvocable : 0)))
155             {
156                 return null;
157             }
158             return mem.SwtFirst();
159         }
160 
AddParameterConversions(MethodBase method)161         private void AddParameterConversions(MethodBase method)
162         {
163             foreach (ParameterInfo param in method.GetParameters())
164             {
165                 AddConversionsForType(param.ParameterType);
166             }
167         }
168 
169         #region InheritanceHierarchy
AddNamesOnType(NameHashKey key)170         private void AddNamesOnType(NameHashKey key)
171         {
172             Debug.Assert(!_namesLoadedForEachType.Contains(key));
173 
174             // We need to declare all of its inheritance hierarchy.
175             List<Type> inheritance = CreateInheritanceHierarchyList(key.type);
176 
177             // Now add every method as it appears in the inheritance hierarchy.
178             AddNamesInInheritanceHierarchy(key.name, inheritance);
179         }
180 
181         /////////////////////////////////////////////////////////////////////////////////
182 
AddNamesInInheritanceHierarchy(string name, List<Type> inheritance)183         private void AddNamesInInheritanceHierarchy(string name, List<Type> inheritance)
184         {
185             for (int i = inheritance.Count - 1; i >= 0; --i)
186             {
187                 Type type = inheritance[i];
188                 if (type.IsGenericType)
189                 {
190                     type = type.GetGenericTypeDefinition();
191                 }
192 
193                 if (!_namesLoadedForEachType.Add(new NameHashKey(type, name)))
194                 {
195                     continue;
196                 }
197 
198                 // Now loop over all methods and add them.
199                 IEnumerator<MemberInfo> memberEn = type
200                     .GetMembers(
201                         BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
202                     .Where(member => member.DeclaringType == type && member.Name == name).GetEnumerator();
203                 if (memberEn.MoveNext())
204                 {
205                     List<EventInfo> events = null;
206                     CType cType = GetCTypeFromType(type);
207                     if (!(cType is AggregateType aggType))
208                         continue;
209                     AggregateSymbol aggregate = aggType.getAggregate();
210                     FieldSymbol addedField = null;
211 
212                     // We need to add fields before the actual events, so do the first iteration
213                     // excluding events.
214                     do
215                     {
216                         MemberInfo member = memberEn.Current;
217                         if (member is MethodInfo method)
218                         {
219                             MethodKindEnum kind;
220                             switch (member.Name)
221                             {
222                                 case SpecialNames.Invoke:
223                                     kind = MethodKindEnum.Invoke;
224                                     break;
225 
226                                 case SpecialNames.ImplicitConversion:
227                                     kind = MethodKindEnum.ImplicitConv;
228                                     break;
229 
230                                 case SpecialNames.ExplicitConversion:
231                                     kind = MethodKindEnum.ExplicitConv;
232                                     break;
233 
234                                 default:
235                                     kind = MethodKindEnum.Actual;
236                                     break;
237                             }
238 
239                             AddMethodToSymbolTable(method, aggregate, kind);
240                             AddParameterConversions(method);
241                         }
242                         else if (member is ConstructorInfo ctor)
243                         {
244                             AddMethodToSymbolTable(ctor, aggregate, MethodKindEnum.Constructor);
245                             AddParameterConversions(ctor);
246                         }
247                         else if (member is PropertyInfo prop)
248                         {
249                             AddPropertyToSymbolTable(prop, aggregate);
250                         }
251                         else if (member is FieldInfo field)
252                         {
253                             // Store this field so that if we also find an event, we can
254                             // mark it as the backing field of the event.
255                             Debug.Assert(addedField == null);
256                             addedField = AddFieldToSymbolTable(field, aggregate);
257                         }
258                         else if (member is EventInfo e)
259                         {
260                             // Store events until after all fields
261                             (events = events ?? new List<EventInfo>()).Add(e);
262                         }
263                     } while (memberEn.MoveNext());
264 
265                     if (events != null)
266                     {
267                         foreach (EventInfo e in events)
268                         {
269                             AddEventToSymbolTable(e, aggregate, addedField);
270                         }
271                     }
272                 }
273             }
274         }
275 
276         /////////////////////////////////////////////////////////////////////////////////
277 
CreateInheritanceHierarchyList(Type type)278         private List<Type> CreateInheritanceHierarchyList(Type type)
279         {
280             List<Type> list;
281             if (type.IsInterface)
282             {
283                 Type[] ifaces = type.GetInterfaces();
284 
285                 // Since IsWindowsRuntimeType() is rare, this is probably the final size
286                 list = new List<Type>(ifaces.Length + 2)
287                 {
288                     type
289                 };
290                 foreach (Type iface in type.GetInterfaces())
291                 {
292                     LoadSymbolsFromType(iface);
293                     list.Add(iface);
294                 }
295 
296                 Type obj = typeof(object);
297                 LoadSymbolsFromType(obj);
298                 list.Add(obj);
299             }
300             else
301             {
302                 list = new List<Type> { type };
303                 for (Type parent = type.BaseType; parent != null; parent = parent.BaseType)
304                 {
305                     // Load it in the symbol table.
306                     LoadSymbolsFromType(parent);
307 
308                     // Insert into our list of Types.
309                     list.Add(parent);
310                 }
311             }
312 
313             // If we have a WinRT type then we should load the members of it's collection interfaces
314             // as well as those members are on this type as far as the user is concerned.
315             CType ctype = GetCTypeFromType(type);
316             if (ctype.IsWindowsRuntimeType())
317             {
318                 TypeArray collectioniFaces = ((AggregateType)ctype).GetWinRTCollectionIfacesAll(_semanticChecker.SymbolLoader);
319 
320                 for (int i = 0; i < collectioniFaces.Count; i++)
321                 {
322                     CType collectionType = collectioniFaces[i];
323                     Debug.Assert(collectionType.isInterfaceType());
324 
325                     // Insert into our list of Types.
326                     list.Add(collectionType.AssociatedSystemType);
327                 }
328             }
329             return list;
330         }
331         #endregion
332 
333         #region GetName
334         /////////////////////////////////////////////////////////////////////////////////
335 
GetName(string p)336         private Name GetName(string p)
337         {
338             return NameManager.Add(p ?? "");
339         }
340 
341         /////////////////////////////////////////////////////////////////////////////////
342 
GetName(Type type)343         private Name GetName(Type type)
344         {
345             string name = type.Name;
346             if (type.IsGenericType)
347             {
348                 int idx = name.IndexOf('`');
349                 if (idx >= 0)
350                 {
351                     return NameManager.Add(name, idx);
352                 }
353             }
354 
355             return NameManager.Add(name);
356         }
357 
358         #endregion
359 
360         #region TypeParameters
361         /////////////////////////////////////////////////////////////////////////////////
362 
GetMethodTypeParameters(MethodInfo method, MethodSymbol parent)363         private TypeArray GetMethodTypeParameters(MethodInfo method, MethodSymbol parent)
364         {
365             if (method.IsGenericMethod)
366             {
367                 Type[] genericArguments = method.GetGenericArguments();
368                 CType[] ctypes = new CType[genericArguments.Length];
369                 for (int i = 0; i < genericArguments.Length; i++)
370                 {
371                     Type t = genericArguments[i];
372                     ctypes[i] = LoadMethodTypeParameter(parent, t);
373                 }
374 
375                 // After we load the type parameters, we need to resolve their bounds.
376                 for (int i = 0; i < genericArguments.Length; i++)
377                 {
378                     Type t = genericArguments[i];
379                     ((TypeParameterType)ctypes[i]).GetTypeParameterSymbol().SetBounds(
380                         _bsymmgr.AllocParams(
381                         GetCTypeArrayFromTypes(t.GetGenericParameterConstraints())));
382                 }
383                 return _bsymmgr.AllocParams(ctypes.Length, ctypes);
384             }
385             return BSYMMGR.EmptyTypeArray();
386         }
387 
388         /////////////////////////////////////////////////////////////////////////////////
389 
GetAggregateTypeParameters(Type type, AggregateSymbol agg)390         private TypeArray GetAggregateTypeParameters(Type type, AggregateSymbol agg)
391         {
392             if (type.IsGenericType)
393             {
394                 Type genericDefinition = type.GetGenericTypeDefinition();
395                 Type[] genericArguments = genericDefinition.GetGenericArguments();
396                 List<CType> ctypes = new List<CType>();
397                 int outerParameters = agg.isNested() ? agg.GetOuterAgg().GetTypeVarsAll().Count : 0;
398 
399                 for (int i = 0; i < genericArguments.Length; i++)
400                 {
401                     // Suppose we have the following:
402                     //
403                     // class A<A1, A2, ..., An>
404                     // {
405                     //     class B<B1, B2, ..., Bm>
406                     //     {
407                     //     }
408                     // }
409                     //
410                     // B will have m+n generic arguments - { A1, A2, ..., An, B1, B2, ..., Bn }.
411                     // As we enumerate these, we need to skip type parameters whose GenericParameterPosition
412                     // is less than n, since the first n type parameters are { A1, A2, ..., An }.
413 
414                     Type t = genericArguments[i];
415 
416                     if (t.GenericParameterPosition < outerParameters)
417                     {
418                         continue;
419                     }
420 
421                     CType ctype;
422                     if (t.IsGenericParameter && t.DeclaringType == genericDefinition)
423                     {
424                         ctype = LoadClassTypeParameter(agg, t);
425                     }
426                     else
427                     {
428                         ctype = GetCTypeFromType(t);
429                     }
430 
431                     // We check to make sure we own the type parameter - this is because we're
432                     // currently calculating TypeArgsThis, NOT TypeArgsAll.
433                     if (((TypeParameterType)ctype).GetOwningSymbol() == agg)
434                     {
435                         ctypes.Add(ctype);
436                     }
437                 }
438                 return _bsymmgr.AllocParams(ctypes.Count, ctypes.ToArray());
439             }
440             return BSYMMGR.EmptyTypeArray();
441         }
442 
443         /////////////////////////////////////////////////////////////////////////////////
444 
LoadClassTypeParameter(AggregateSymbol parent, Type t)445         private TypeParameterType LoadClassTypeParameter(AggregateSymbol parent, Type t)
446         {
447             for (AggregateSymbol p = parent; p != null; p = p.parent as AggregateSymbol)
448             {
449                 for (TypeParameterSymbol typeParam = _bsymmgr.LookupAggMember(
450                         GetName(t), p, symbmask_t.MASK_TypeParameterSymbol) as TypeParameterSymbol;
451                     typeParam != null;
452                     typeParam = BSYMMGR.LookupNextSym(typeParam, p, symbmask_t.MASK_TypeParameterSymbol) as TypeParameterSymbol)
453                 {
454                     if (AreTypeParametersEquivalent(typeParam.GetTypeParameterType().AssociatedSystemType, t))
455                     {
456                         return typeParam.GetTypeParameterType();
457                     }
458                 }
459             }
460             return AddTypeParameterToSymbolTable(parent, null, t, true);
461         }
462 
463         /////////////////////////////////////////////////////////////////////////////////
464 
AreTypeParametersEquivalent(Type t1, Type t2)465         private bool AreTypeParametersEquivalent(Type t1, Type t2)
466         {
467             Debug.Assert(t1.IsGenericParameter && t2.IsGenericParameter);
468 
469             if (t1 == t2)
470             {
471                 return true;
472             }
473 
474             Type t1Original = GetOriginalTypeParameterType(t1);
475             Type t2Original = GetOriginalTypeParameterType(t2);
476 
477             return t1Original == t2Original;
478         }
479 
480         /////////////////////////////////////////////////////////////////////////////////
481 
482         // GetOriginalTypeParameterType
483         // This was added so that LoadClassTypeParameter would not fail to find outer
484         // type parameters when given a System.Type from an outer class and a matching
485         // type parameter from in an inner class. In Reflection type parameters are
486         // always declared by their inner most declaring class. For example, given:
487         //
488         //   class A<T> {
489         //     class B<U> { }
490         //   }
491         //
492         // in Reflection there are two Ts, A<T>'s T, and B<U>'s T. In our world there is
493         // only A<T>'s T.
494         //
495         // So this method here drills down and finds the type parameter type corresponding
496         // to the position of the given type parameter, from the outer most containing
497         // type. So in the above example, given B<U>'s T from reflection, this will return
498         // A<T>'s T, so that you can make a reference comparison of type parameters coming
499         // from different nesting levels.
500         //
501         // There is an exception, we don't handle the case where you have type parameters
502         // coming from different partially constructed methods. E.g.
503         //
504         //   class A<T,S> {
505         //     public void M<U> { }
506         //   }
507         //
508         //   A<T,int>.M<U>
509         //   A<T,string>.M<U>
510         //
511         // In the above two methods, the two U's are different in Reflection. Here we just
512         // return the type parameter type given if it is in a method, we do not try to
513         // generalize these occurrences for reference equality.
514         //
GetOriginalTypeParameterType(Type t)515         private Type GetOriginalTypeParameterType(Type t)
516         {
517             Debug.Assert(t.IsGenericParameter);
518 
519             int pos = t.GenericParameterPosition;
520 
521             Type parentType = t.DeclaringType;
522             if (parentType != null && parentType.IsGenericType)
523             {
524                 parentType = parentType.GetGenericTypeDefinition();
525             }
526 
527             if (t.DeclaringMethod != null)
528             {
529                 if (parentType.GetGenericArguments() == null || pos >= parentType.GetGenericArguments().Length)
530                 {
531                     return t;
532                 }
533             }
534 
535             while (parentType.GetGenericArguments().Length > pos)
536             {
537                 Type nextParent = parentType.DeclaringType;
538                 if (nextParent != null && nextParent.IsGenericType)
539                 {
540                     nextParent = nextParent.GetGenericTypeDefinition();
541                 }
542 
543                 if (nextParent?.GetGenericArguments()?.Length > pos)
544                 {
545                     parentType = nextParent;
546                 }
547                 else
548                 {
549                     break;
550                 }
551             }
552 
553             return parentType.GetGenericArguments()[pos];
554         }
555 
556         /////////////////////////////////////////////////////////////////////////////////
557 
LoadMethodTypeParameter(MethodSymbol parent, Type t)558         private TypeParameterType LoadMethodTypeParameter(MethodSymbol parent, Type t)
559         {
560             for (Symbol sym = parent.firstChild; sym != null; sym = sym.nextChild)
561             {
562                 if (!(sym is TypeParameterSymbol parSym))
563                 {
564                     continue;
565                 }
566 
567                 TypeParameterType type = parSym.GetTypeParameterType();
568                 if (AreTypeParametersEquivalent(type.AssociatedSystemType, t))
569                 {
570                     return type;
571                 }
572             }
573 
574             return AddTypeParameterToSymbolTable(null, parent, t, false);
575         }
576 
577         /////////////////////////////////////////////////////////////////////////////////
578 
AddTypeParameterToSymbolTable( AggregateSymbol agg, MethodSymbol meth, Type t, bool bIsAggregate)579         private TypeParameterType AddTypeParameterToSymbolTable(
580                 AggregateSymbol agg,
581                 MethodSymbol meth,
582                 Type t,
583                 bool bIsAggregate)
584         {
585             Debug.Assert((agg != null && bIsAggregate) || (meth != null && !bIsAggregate));
586 
587             TypeParameterSymbol typeParam;
588             if (bIsAggregate)
589             {
590                 typeParam = _symFactory.CreateClassTypeParameter(
591                     GetName(t),
592                     agg,
593                     t.GenericParameterPosition,
594                     t.GenericParameterPosition);
595             }
596             else
597             {
598                 typeParam = _symFactory.CreateMethodTypeParameter(
599                     GetName(t),
600                     meth,
601                     t.GenericParameterPosition,
602                     t.GenericParameterPosition);
603             }
604 
605             if ((t.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0)
606             {
607                 typeParam.Covariant = true;
608             }
609             if ((t.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0)
610             {
611                 typeParam.Contravariant = true;
612             }
613 
614             SpecCons cons = SpecCons.None;
615 
616             if ((t.GenericParameterAttributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0)
617             {
618                 cons |= SpecCons.New;
619             }
620             if ((t.GenericParameterAttributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0)
621             {
622                 cons |= SpecCons.Ref;
623             }
624             if ((t.GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
625             {
626                 cons |= SpecCons.Val;
627             }
628 
629             typeParam.SetConstraints(cons);
630             typeParam.SetAccess(ACCESS.ACC_PUBLIC);
631             TypeParameterType typeParamType = _typeManager.GetTypeParameter(typeParam);
632 
633             return typeParamType;
634         }
635 
636         #endregion
637 
638         #region LoadTypeChain
639         /////////////////////////////////////////////////////////////////////////////////
640 
LoadSymbolsFromType(Type type)641         private CType LoadSymbolsFromType(Type type)
642         {
643             List<object> declarationChain = BuildDeclarationChain(type);
644 
645             NamespaceOrAggregateSymbol current = NamespaceSymbol.Root;
646 
647             // Go through the declaration chain and add namespaces and types for
648             // each element in the chain.
649             for (int i = 0; i < declarationChain.Count; i++)
650             {
651                 object o = declarationChain[i];
652                 if (o is Type t)
653                 {
654                     if (t.IsNullableType())
655                     {
656                         return _typeManager.GetNullable(GetCTypeFromType(t.GetGenericArguments()[0]));
657                     }
658 
659                     AggregateSymbol next = FindSymForType(
660                         _symbolTable.LookupSym(GetName(t), current, symbmask_t.MASK_AggregateSymbol), t);
661 
662                     // If we haven't found this type yet, then add it to our symbol table.
663                     if (next == null)
664                     {
665                         // Note that if we have anything other than an AggregateSymbol,
666                         // we must be at the end of the line - that is, nothing else can
667                         // have children.
668                         CType ctype = ProcessSpecialTypeInChain(current, t);
669                         if (ctype != null)
670                         {
671                             Debug.Assert(!(ctype is AggregateType));
672                             return ctype;
673                         }
674 
675                         // This is a regular class.
676                         next = AddAggregateToSymbolTable(current, t);
677                     }
678 
679                     if (t == type)
680                     {
681                         return GetConstructedType(type, next);
682                     }
683 
684                     current = next;
685                 }
686                 else if (o is MethodInfo m)
687                 {
688                     // We cant be at the end.
689                     Debug.Assert(i + 1 < declarationChain.Count);
690                     return ProcessMethodTypeParameter(m, declarationChain[++i] as Type, current as AggregateSymbol);
691                 }
692                 else
693                 {
694                     Debug.Assert(o is string);
695                     current = AddNamespaceToSymbolTable(current, o as string);
696                 }
697             }
698 
699             Debug.Fail("Should be unreachable");
700             return null;
701         }
702 
703         /////////////////////////////////////////////////////////////////////////////////
704 
ProcessMethodTypeParameter(MethodInfo methinfo, Type t, AggregateSymbol parent)705         private TypeParameterType ProcessMethodTypeParameter(MethodInfo methinfo, Type t, AggregateSymbol parent)
706         {
707             MethodSymbol meth = FindMatchingMethod(methinfo, parent);
708             if (meth == null)
709             {
710                 meth = AddMethodToSymbolTable(methinfo, parent, MethodKindEnum.Actual);
711 
712                 // Because we return null from AddMethodToSymbolTable when we have a MethodKindEnum.Actual
713                 // and the method that we're trying to add is a special name, we need to assert that
714                 // we indeed have added a method. This is because no special name should have a method
715                 // type parameter on it.
716                 Debug.Assert(meth != null);
717             }
718             return LoadMethodTypeParameter(meth, t);
719         }
720 
721         /////////////////////////////////////////////////////////////////////////////////
722 
GetConstructedType(Type type, AggregateSymbol agg)723         private CType GetConstructedType(Type type, AggregateSymbol agg)
724         {
725             // We've found the one we want, so return it.
726             if (type.IsGenericType)
727             {
728                 // If we're a generic type, then we need to add the type arguments.
729                 List<CType> types = new List<CType>();
730 
731                 foreach (Type argument in type.GetGenericArguments())
732                 {
733                     types.Add(GetCTypeFromType(argument));
734                 }
735 
736                 TypeArray typeArray = _bsymmgr.AllocParams(types.ToArray());
737                 AggregateType aggType = _typeManager.GetAggregate(agg, typeArray);
738                 return aggType;
739             }
740             CType ctype = agg.getThisType();
741             return ctype;
742         }
743 
744         /////////////////////////////////////////////////////////////////////////////////
745 
ProcessSpecialTypeInChain(NamespaceOrAggregateSymbol parent, Type t)746         private CType ProcessSpecialTypeInChain(NamespaceOrAggregateSymbol parent, Type t)
747         {
748             if (t.IsGenericParameter)
749             {
750                 AggregateSymbol agg = parent as AggregateSymbol;
751                 Debug.Assert(agg != null);
752                 return LoadClassTypeParameter(agg, t);
753             }
754 
755             if (t.IsArray)
756             {
757                 // Now we return an array of nesting level corresponding to the rank.
758                 return _typeManager.GetArray(
759                     GetCTypeFromType(t.GetElementType()),
760                     t.GetArrayRank(),
761 #if netcoreapp
762                     t.IsSZArray
763 #else
764                     t.GetElementType().MakeArrayType() == t
765 #endif
766                     );
767             }
768 
769             if (t.IsPointer)
770             {
771                 // Now we return the pointer type that we want.
772                 return _typeManager.GetPointer(GetCTypeFromType(t.GetElementType()));
773             }
774 
775             return null;
776         }
777 
778         /////////////////////////////////////////////////////////////////////////////////
779 
BuildDeclarationChain(Type callingType)780         private static List<object> BuildDeclarationChain(Type callingType)
781         {
782             // We need to build the parent chain of the calling type. Since we only
783             // have the type itself, first we need to build the chain up from the
784             // type down to the root namespace, then we need to ensure that
785             // the chain exists in our symbol table by searching from the root namespace
786             // back down to the calling type. Also note that if we have a method type
787             // parameter, then we'll also add the MethodBase to the chain.
788             //
789             // Note that we'll populate this list in a hybrid way - we'll add the
790             // types for the type part of the chain, and we'll just add the string names
791             // of the namespaces.
792 
793             // Strip off the ref-ness.
794             if (callingType.IsByRef)
795             {
796                 callingType = callingType.GetElementType();
797             }
798 
799             List<object> callChain = new List<object>();
800             for (Type t = callingType; t != null; t = t.DeclaringType)
801             {
802                 callChain.Add(t);
803 
804                 if (t.IsGenericParameter && t.DeclaringMethod != null)
805                 {
806                     MethodBase methodBase = t.DeclaringMethod;
807                     bool bAdded = false;
808 #if UNSUPPORTEDAPI
809                     foreach (MethodInfo methinfo in Enumerable.Where(t.DeclaringType.GetRuntimeMethods(), m => m.MetadataToken == methodBase.MetadataToken))
810 #else
811                     foreach (MethodInfo methinfo in Enumerable.Where(t.DeclaringType.GetRuntimeMethods(), m => m.HasSameMetadataDefinitionAs(methodBase)))
812 #endif
813                     {
814                         if (!methinfo.IsGenericMethod)
815                         {
816                             continue;
817                         }
818 
819                         Debug.Assert(!bAdded);
820                         callChain.Add(methinfo);
821                         bAdded = true;
822                     }
823                     Debug.Assert(bAdded);
824                 }
825             }
826 
827             callChain.Reverse();
828 
829             // Now take out the namespaces and add them to the end of the chain.
830             if (callingType.Namespace != null)
831             {
832                 callChain.InsertRange(0, callingType.Namespace.Split('.'));
833             }
834             return callChain;
835         }
836 
837         // We have an aggregate symbol of the correct parent and full name, but it may have the wrong arity, or, due to
838         // dynamic loading or creation, two different types can exist that have the same name.
839 
840         // In the static compiler, this would have been an error and name lookup would be ambiguous, but here we never have
841         // to lookup names of types for real (only names of members).
842 
843         // For either case, move onto the next symbol in the chain, and check again for appropriate type.
FindSymForType(Symbol sym, Type t)844         private AggregateSymbol FindSymForType(Symbol sym, Type t)
845         {
846             while (sym != null)
847             {
848                 // We use "IsEquivalentTo" so that unified local types match.
849                 if (sym is AggregateSymbol agg)
850                 if (agg.AssociatedSystemType.IsEquivalentTo(t.IsGenericType ? t.GetGenericTypeDefinition() : t))
851                 {
852                     return agg;
853                 }
854 
855                 sym = sym.nextSameName;
856             }
857 
858             return null;
859         }
860 
AddNamespaceToSymbolTable(NamespaceOrAggregateSymbol parent, string sz)861         private NamespaceSymbol AddNamespaceToSymbolTable(NamespaceOrAggregateSymbol parent, string sz)
862         {
863             Name name = GetName(sz);
864             return _symbolTable.LookupSym(name, parent, symbmask_t.MASK_NamespaceSymbol) as NamespaceSymbol
865                 ?? _symFactory.CreateNamespace(name, parent as NamespaceSymbol);
866         }
867         #endregion
868 
869         #region CTypeFromType
870         /////////////////////////////////////////////////////////////////////////////////
871 
GetCTypeArrayFromTypes(Type[] types)872         internal CType[] GetCTypeArrayFromTypes(Type[] types)
873         {
874             Debug.Assert(types != null);
875 
876             int length = types.Length;
877             if (length == 0)
878             {
879                 return Array.Empty<CType>();
880             }
881 
882             CType[] ctypes = new CType[length];
883             for (int i = 0; i < types.Length; i++)
884             {
885                 Type t = types[i];
886                 Debug.Assert(t != null);
887                 ctypes[i] = GetCTypeFromType(t);
888             }
889 
890             return ctypes;
891         }
892 
893         /////////////////////////////////////////////////////////////////////////////////
894 
895         internal CType GetCTypeFromType(Type type) => type.IsByRef
896             ? _typeManager.GetParameterModifier(LoadSymbolsFromType(type.GetElementType()), false)
897             : LoadSymbolsFromType(type);
898 
899         #endregion
900 
901         #region Aggregates
902         /////////////////////////////////////////////////////////////////////////////////
903 
AddAggregateToSymbolTable( NamespaceOrAggregateSymbol parent, Type type)904         private AggregateSymbol AddAggregateToSymbolTable(
905             NamespaceOrAggregateSymbol parent,
906             Type type)
907         {
908             AggregateSymbol agg = _symFactory.CreateAggregate(GetName(type), parent, _typeManager);
909             agg.AssociatedSystemType = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
910             agg.AssociatedAssembly = type.Assembly;
911 
912             // We have to set the TypeVars, access, and the AggKind before we can set the aggState
913             // because of the assertion checking the compiler does.
914             AggKindEnum kind;
915             if (type.IsInterface)
916             {
917                 kind = AggKindEnum.Interface;
918             }
919             else if (type.IsEnum)
920             {
921                 kind = AggKindEnum.Enum;
922                 agg.SetUnderlyingType((AggregateType)GetCTypeFromType(Enum.GetUnderlyingType(type)));
923             }
924             else if (type.IsValueType)
925             {
926                 kind = AggKindEnum.Struct;
927             }
928             else
929             {
930                 // If it derives from Delegate or MulticastDelegate, then its
931                 // a delegate type. However, MuticastDelegate itself is not a
932                 // delegate type.
933                 if (type.BaseType != null &&
934                     (type.BaseType.FullName == "System.MulticastDelegate" ||
935                     type.BaseType.FullName == "System.Delegate") &&
936                     type.FullName != "System.MulticastDelegate")
937                 {
938                     kind = AggKindEnum.Delegate;
939                 }
940                 else
941                 {
942                     kind = AggKindEnum.Class;
943                 }
944             }
945             agg.SetAggKind(kind);
946             agg.SetTypeVars(BSYMMGR.EmptyTypeArray());
947 
948             ACCESS access;
949             if (type.IsPublic)
950             {
951                 access = ACCESS.ACC_PUBLIC;
952             }
953             else if (type.IsNested)
954             {
955                 // If its nested, we may have other accessibility options.
956                 if (type.IsNestedAssembly)
957                 {
958                     access = ACCESS.ACC_INTERNAL;
959                 }
960                 else if (type.IsNestedFamORAssem)
961                 {
962                     access = ACCESS.ACC_INTERNALPROTECTED;
963                 }
964                 else if (type.IsNestedPrivate)
965                 {
966                     access = ACCESS.ACC_PRIVATE;
967                 }
968                 else if (type.IsNestedFamily)
969                 {
970                     access = ACCESS.ACC_PROTECTED;
971                 }
972                 else if (type.IsNestedFamANDAssem)
973                 {
974                     access = ACCESS.ACC_INTERNAL_AND_PROTECTED;
975                 }
976                 else
977                 {
978                     Debug.Assert(type.IsPublic || type.IsNestedPublic);
979                     access = ACCESS.ACC_PUBLIC;
980                 }
981             }
982             else
983             {
984                 // We're not public and we're not nested - we must be internal.
985                 access = ACCESS.ACC_INTERNAL;
986             }
987             agg.SetAccess(access);
988 
989             if (!type.IsGenericParameter)
990             {
991                 agg.SetTypeVars(GetAggregateTypeParameters(type, agg));
992             }
993 
994             if (type.IsGenericType)
995             {
996                 Type genericDefinition = type.GetGenericTypeDefinition();
997                 Type[] genericArguments = genericDefinition.GetGenericArguments();
998 
999                 // After we load the type parameters, we need to resolve their bounds.
1000                 for (int i = 0; i < agg.GetTypeVars().Count; i++)
1001                 {
1002                     Type t = genericArguments[i];
1003                     if (agg.GetTypeVars()[i] is TypeParameterType typeVar)
1004                     {
1005                         typeVar.GetTypeParameterSymbol().SetBounds(
1006                             _bsymmgr.AllocParams(
1007                             GetCTypeArrayFromTypes(t.GetGenericParameterConstraints())));
1008                     }
1009                 }
1010             }
1011 
1012             agg.SetAbstract(type.IsAbstract);
1013 
1014             {
1015                 string typeName = type.FullName;
1016                 if (type.IsGenericType)
1017                 {
1018                     typeName = type.GetGenericTypeDefinition().FullName;
1019                 }
1020                 if (typeName != null)
1021                 {
1022                     PredefinedType predefinedType = PredefinedTypeFacts.TryGetPredefTypeIndex(typeName);
1023                     if (predefinedType != PredefinedType.PT_UNDEFINEDINDEX)
1024                     {
1025                         PredefinedTypes.InitializePredefinedType(agg, predefinedType);
1026                     }
1027                 }
1028             }
1029 
1030             agg.SetSealed(type.IsSealed);
1031             if (type.BaseType != null)
1032             {
1033                 // type.BaseType can be null for Object or for interface types.
1034                 Type t = type.BaseType;
1035                 if (t.IsGenericType)
1036                 {
1037                     t = t.GetGenericTypeDefinition();
1038                 }
1039                 agg.SetBaseClass((AggregateType)GetCTypeFromType(t));
1040             }
1041             agg.SetTypeManager(_typeManager);
1042             agg.SetFirstUDConversion(null);
1043             SetInterfacesOnAggregate(agg, type);
1044             agg.SetHasPubNoArgCtor(type.GetConstructor(Type.EmptyTypes) != null);
1045 
1046             // If we have a delegate, get its invoke and constructor methods as well.
1047             if (agg.IsDelegate())
1048             {
1049                 PopulateSymbolTableWithName(SpecialNames.Constructor, null, type);
1050                 PopulateSymbolTableWithName(SpecialNames.Invoke, null, type);
1051             }
1052 
1053             return agg;
1054         }
1055 
1056         /////////////////////////////////////////////////////////////////////////////////
1057 
SetInterfacesOnAggregate(AggregateSymbol aggregate, Type type)1058         private void SetInterfacesOnAggregate(AggregateSymbol aggregate, Type type)
1059         {
1060             if (type.IsGenericType)
1061             {
1062                 type = type.GetGenericTypeDefinition();
1063             }
1064             Type[] interfaces = type.GetInterfaces();
1065 
1066             // We won't be able to find the difference between Ifaces and
1067             // IfacesAll anymore - at runtime, the class implements all of its
1068             // Ifaces and IfacesAll, so theres no way to differentiate.
1069             //
1070             // This actually doesn't matter though - for conversions and methodcalls,
1071             // we don't really care where they've come from as long as we know the overall
1072             // set of IfacesAll.
1073 
1074             aggregate.SetIfaces(_bsymmgr.AllocParams(interfaces.Length, GetCTypeArrayFromTypes(interfaces)));
1075             aggregate.SetIfacesAll(aggregate.GetIfaces());
1076         }
1077         #endregion
1078 
1079         #region Field
1080         /////////////////////////////////////////////////////////////////////////////////
1081 
AddFieldToSymbolTable(FieldInfo fieldInfo, AggregateSymbol aggregate)1082         private FieldSymbol AddFieldToSymbolTable(FieldInfo fieldInfo, AggregateSymbol aggregate)
1083         {
1084             FieldSymbol field = _symbolTable.LookupSym(
1085                 GetName(fieldInfo.Name),
1086                 aggregate,
1087                 symbmask_t.MASK_FieldSymbol) as FieldSymbol;
1088             if (field != null)
1089             {
1090                 return field;
1091             }
1092 
1093             field = _symFactory.CreateMemberVar(GetName(fieldInfo.Name), aggregate);
1094             field.AssociatedFieldInfo = fieldInfo;
1095 
1096             field.isStatic = fieldInfo.IsStatic;
1097             ACCESS access;
1098             if (fieldInfo.IsPublic)
1099             {
1100                 access = ACCESS.ACC_PUBLIC;
1101             }
1102             else if (fieldInfo.IsPrivate)
1103             {
1104                 access = ACCESS.ACC_PRIVATE;
1105             }
1106             else if (fieldInfo.IsFamily)
1107             {
1108                 access = ACCESS.ACC_PROTECTED;
1109             }
1110             else if (fieldInfo.IsAssembly)
1111             {
1112                 access = ACCESS.ACC_INTERNAL;
1113             }
1114             else if (fieldInfo.IsFamilyOrAssembly)
1115             {
1116                 access = ACCESS.ACC_INTERNALPROTECTED;
1117             }
1118             else
1119             {
1120                 Debug.Assert(fieldInfo.IsFamilyAndAssembly);
1121                 access = ACCESS.ACC_INTERNAL_AND_PROTECTED;
1122             }
1123             field.SetAccess(access);
1124             field.isReadOnly = fieldInfo.IsInitOnly;
1125             field.isEvent = false;
1126             field.isAssigned = true;
1127             field.SetType(GetCTypeFromType(fieldInfo.FieldType));
1128 
1129             return field;
1130         }
1131         #endregion
1132 
1133         #region Events
1134 
1135         /////////////////////////////////////////////////////////////////////////////////
1136 
1137         private static readonly Type s_Sentinel = typeof(SymbolTable);
1138         private static Type s_EventRegistrationTokenType = s_Sentinel;
1139         private static Type s_WindowsRuntimeMarshal = s_Sentinel;
1140         private static Type s_EventRegistrationTokenTable = s_Sentinel;
1141 
1142         internal static Type EventRegistrationTokenType
1143         {
1144             get
1145             {
1146                 return GetTypeByName(ref s_EventRegistrationTokenType, "System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken, System.Runtime.InteropServices.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
1147             }
1148         }
1149 
1150         internal static Type WindowsRuntimeMarshalType
1151         {
1152             get
1153             {
1154                 return GetTypeByName(ref s_WindowsRuntimeMarshal, "System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal, System.Runtime.InteropServices.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
1155             }
1156         }
1157 
1158         private static Type EventRegistrationTokenTableType
1159         {
1160             get
1161             {
1162                 return GetTypeByName(ref s_EventRegistrationTokenTable, "System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable`1, System.Runtime.InteropServices.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
1163             }
1164         }
1165 
GetTypeByName(ref Type cachedResult, string name)1166         private static Type GetTypeByName(ref Type cachedResult, string name)
1167         {
1168             if ((object)cachedResult == s_Sentinel)
1169             {
1170                 System.Threading.Interlocked.CompareExchange(ref cachedResult, Type.GetType(name, throwOnError: false), s_Sentinel);
1171             }
1172 
1173             return cachedResult;
1174         }
1175 
AddEventToSymbolTable(EventInfo eventInfo, AggregateSymbol aggregate, FieldSymbol addedField)1176         private void AddEventToSymbolTable(EventInfo eventInfo, AggregateSymbol aggregate, FieldSymbol addedField)
1177         {
1178             EventSymbol ev = _symbolTable.LookupSym(
1179                 GetName(eventInfo.Name),
1180                 aggregate,
1181                 symbmask_t.MASK_EventSymbol) as EventSymbol;
1182             if (ev != null)
1183             {
1184                 Debug.Assert(ev.AssociatedEventInfo == eventInfo);
1185                 return;
1186             }
1187 
1188             ev = _symFactory.CreateEvent(GetName(eventInfo.Name), aggregate);
1189             ev.AssociatedEventInfo = eventInfo;
1190 
1191             // EventSymbol
1192             ACCESS access = ACCESS.ACC_PRIVATE;
1193             if (eventInfo.AddMethod != null)
1194             {
1195                 ev.methAdd = AddMethodToSymbolTable(eventInfo.AddMethod, aggregate, MethodKindEnum.EventAccessor);
1196                 ev.methAdd.SetEvent(ev);
1197                 ev.isOverride = ev.methAdd.IsOverride();
1198 
1199                 access = ev.methAdd.GetAccess();
1200             }
1201             if (eventInfo.RemoveMethod != null)
1202             {
1203                 ev.methRemove = AddMethodToSymbolTable(eventInfo.RemoveMethod, aggregate, MethodKindEnum.EventAccessor);
1204                 ev.methRemove.SetEvent(ev);
1205                 ev.isOverride = ev.methRemove.IsOverride();
1206 
1207                 access = ev.methRemove.GetAccess();
1208             }
1209             Debug.Assert(ev.methAdd != null || ev.methRemove != null);
1210             ev.isStatic = false;
1211             ev.type = GetCTypeFromType(eventInfo.EventHandlerType);
1212 
1213             // Symbol
1214             ev.SetAccess(access);
1215 
1216             Type eventRegistrationTokenType = EventRegistrationTokenType;
1217             if ((object)eventRegistrationTokenType != null && (object)WindowsRuntimeMarshalType != null &&
1218                 ev.methAdd.RetType.AssociatedSystemType == eventRegistrationTokenType &&
1219                 ev.methRemove.Params[0].AssociatedSystemType == eventRegistrationTokenType)
1220             {
1221                 ev.IsWindowsRuntimeEvent = true;
1222             }
1223 
1224             // If we imported a field on the same aggregate, with the same name, and it also
1225             // has the same type, then that field is the backing field for this event, and
1226             // we mark it as such. This is used for the CSharpIsEventBinder.
1227             // In the case of a WindowsRuntime event, the field will be of type
1228             // EventRegistrationTokenTable<delegateType>.
1229             CType addedFieldType = addedField?.GetType();
1230             if (addedFieldType != null)
1231             {
1232                 if (addedFieldType == ev.type)
1233                 {
1234                     addedField.isEvent = true;
1235                 }
1236                 else
1237                 {
1238                     Type associated = addedFieldType.AssociatedSystemType;
1239                     if (associated.IsConstructedGenericType
1240                         && associated.GetGenericTypeDefinition() == EventRegistrationTokenTableType
1241                         && associated.GenericTypeArguments[0] == ev.type.AssociatedSystemType)
1242                     {
1243                         addedField.isEvent = true;
1244                     }
1245                 }
1246             }
1247         }
1248         #endregion
1249 
1250         #region Properties
1251         /////////////////////////////////////////////////////////////////////////////////
1252 
AddPredefinedPropertyToSymbolTable(AggregateSymbol type, Name property)1253         internal void AddPredefinedPropertyToSymbolTable(AggregateSymbol type, Name property)
1254         {
1255             AggregateType aggtype = type.getThisType();
1256             Type t = aggtype.AssociatedSystemType;
1257 
1258             var props = Enumerable.Where(t.GetRuntimeProperties(), x => x.Name == property.Text);
1259 
1260             foreach (PropertyInfo pi in props)
1261             {
1262                 AddPropertyToSymbolTable(pi, type);
1263             }
1264         }
1265 
1266         /////////////////////////////////////////////////////////////////////////////////
1267 
AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol aggregate)1268         private void AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol aggregate)
1269         {
1270             Name name;
1271             bool isIndexer = property.GetIndexParameters().Length != 0
1272                              && property.DeclaringType?.GetCustomAttribute<DefaultMemberAttribute>()
1273                              ?.MemberName == property.Name;
1274 
1275             if (isIndexer)
1276             {
1277                 name = GetName(SpecialNames.Indexer);
1278             }
1279             else
1280             {
1281                 name = GetName(property.Name);
1282             }
1283             PropertySymbol prop = _symbolTable.LookupSym(
1284                 name,
1285                 aggregate,
1286                 symbmask_t.MASK_PropertySymbol) as PropertySymbol;
1287 
1288             // If we already had one, see if it matches.
1289             if (prop != null)
1290             {
1291                 PropertySymbol prevProp = null;
1292 
1293                 // We'll have multiple properties with the same name if we have indexers.
1294                 // In that case, we need to look at every indexer to see if we find one with
1295                 // the matching associated sym that we want.
1296                 while (prop != null)
1297                 {
1298                     if (prop.AssociatedPropertyInfo.IsEquivalentTo(property))
1299                     {
1300                         return;
1301                     }
1302 
1303                     prevProp = prop;
1304                     prop = SymbolLoader.LookupNextSym(prop, prop.parent, symbmask_t.MASK_PropertySymbol) as PropertySymbol;
1305                 }
1306 
1307                 prop = prevProp;
1308                 if (isIndexer)
1309                 {
1310                     // We have an indexer for a different property info, so
1311                     // create a new symbol for it.
1312                     prop = null;
1313                 }
1314             }
1315 
1316             // If we already had a property but its associated info doesn't match,
1317             // then we repurpose the property that we've found. This can happen
1318             // in the case of generic instantiations.
1319             //
1320             // Note that this is a bit of a hack - the best way to fix this is
1321             // by not depending on the instantiated properties at all, but rather depending
1322             // on their non-instantiated generic form, which can be gotten from the
1323             // parent's generic type definition's member. From there, we'll also need to
1324             // keep track of the instantiation as we move along, so that when we need the
1325             // associated property, we can instantiate it correctly.
1326             //
1327             // This seems far too heavyweight - since we know we will never bind to more
1328             // than one property per payload, lets just blast it each time.
1329             if (prop == null)
1330             {
1331                 if (isIndexer)
1332                 {
1333                     prop = _semanticChecker.SymbolLoader.GetGlobalSymbolFactory().CreateIndexer(name, aggregate, GetName(property.Name));
1334                     prop.Params = CreateParameterArray(null, property.GetIndexParameters());
1335                 }
1336                 else
1337                 {
1338                     prop = _symFactory.CreateProperty(GetName(property.Name), aggregate);
1339                     prop.Params = BSYMMGR.EmptyTypeArray();
1340                 }
1341             }
1342             prop.AssociatedPropertyInfo = property;
1343 
1344             prop.isStatic = property.GetGetMethod(true) != null ? property.GetGetMethod(true).IsStatic : property.GetSetMethod(true).IsStatic;
1345             prop.isParamArray = DoesMethodHaveParameterArray(property.GetIndexParameters());
1346             prop.swtSlot = null;
1347             prop.RetType = GetCTypeFromType(property.PropertyType);
1348             prop.isOperator = isIndexer;
1349 
1350             // Determine if its an override. We should always have an accessor, unless
1351             // the metadata was bogus.
1352             if (property.GetMethod != null || property.SetMethod != null)
1353             {
1354                 MethodInfo accessor = property.GetMethod ?? property.SetMethod; // Must have at least one.
1355                 prop.isOverride = accessor.IsVirtual && accessor.IsHideBySig && accessor.GetRuntimeBaseDefinition() != accessor;
1356                 prop.isHideByName = !accessor.IsHideBySig;
1357             }
1358 
1359             SetParameterDataForMethProp(prop, property.GetIndexParameters());
1360 
1361             // Get and set.
1362             MethodInfo methGet = property.GetMethod;
1363             MethodInfo methSet = property.SetMethod;
1364             ACCESS access = ACCESS.ACC_PRIVATE;
1365             if (methGet != null)
1366             {
1367                 prop.GetterMethod = AddMethodToSymbolTable(methGet, aggregate, MethodKindEnum.PropAccessor);
1368 
1369                 // If we have an indexed property, leave the method as a method we can call,
1370                 // and mark the property as bogus.
1371                 if (isIndexer || prop.GetterMethod.Params.Count == 0)
1372                 {
1373                     prop.GetterMethod.SetProperty(prop);
1374                 }
1375                 else
1376                 {
1377                     prop.Bogus = true;
1378                     prop.GetterMethod.SetMethKind(MethodKindEnum.Actual);
1379                 }
1380 
1381                 if (prop.GetterMethod.GetAccess() > access)
1382                 {
1383                     access = prop.GetterMethod.GetAccess();
1384                 }
1385             }
1386             if (methSet != null)
1387             {
1388                 prop.SetterMethod = AddMethodToSymbolTable(methSet, aggregate, MethodKindEnum.PropAccessor);
1389 
1390                 // If we have an indexed property, leave the method as a method we can call,
1391                 // and mark the property as bogus.
1392                 if (isIndexer || prop.SetterMethod.Params.Count == 1)
1393                 {
1394                     prop.SetterMethod.SetProperty(prop);
1395                 }
1396                 else
1397                 {
1398                     prop.Bogus = true;
1399                     prop.SetterMethod.SetMethKind(MethodKindEnum.Actual);
1400                 }
1401 
1402                 if (prop.SetterMethod.GetAccess() > access)
1403                 {
1404                     access = prop.SetterMethod.GetAccess();
1405                 }
1406             }
1407 
1408             // The access of the property is the least restrictive access of its getter/setter.
1409             prop.SetAccess(access);
1410         }
1411 
1412         #endregion
1413 
1414         #region Methods
1415         /////////////////////////////////////////////////////////////////////////////////
1416 
AddPredefinedMethodToSymbolTable(AggregateSymbol type, Name methodName)1417         internal void AddPredefinedMethodToSymbolTable(AggregateSymbol type, Name methodName)
1418         {
1419             Type t = type.getThisType().AssociatedSystemType;
1420 
1421             // If we got here, it means we couldn't find it in our initial lookup. Means we haven't loaded it from reflection yet.
1422             // Lets go and do that now.
1423             // Check if we have constructors or not.
1424             if (methodName == NameManager.GetPredefinedName(PredefinedName.PN_CTOR))
1425             {
1426                 foreach (ConstructorInfo c in t.GetConstructors())
1427                 {
1428                     AddMethodToSymbolTable(
1429                         c,
1430                         type,
1431                         MethodKindEnum.Constructor);
1432                 }
1433             }
1434             else
1435             {
1436                 var methods = Enumerable.Where(t.GetRuntimeMethods(), m => m.Name == methodName.Text && m.DeclaringType == t);
1437 
1438                 foreach (MethodInfo m in methods)
1439                 {
1440                     AddMethodToSymbolTable(
1441                         m,
1442                         type,
1443                         m.Name == SpecialNames.Invoke ? MethodKindEnum.Invoke : MethodKindEnum.Actual);
1444                 }
1445             }
1446         }
1447 
1448         /////////////////////////////////////////////////////////////////////////////////
1449 
AddMethodToSymbolTable(MethodBase member, AggregateSymbol callingAggregate, MethodKindEnum kind)1450         private MethodSymbol AddMethodToSymbolTable(MethodBase member, AggregateSymbol callingAggregate, MethodKindEnum kind)
1451         {
1452             MethodInfo method = member as MethodInfo;
1453 
1454             Debug.Assert(method != null || member is ConstructorInfo);
1455 #if UNSUPPORTEDAPI
1456             Debug.Assert(member.DeclaringType == member.ReflectedType);
1457 #endif
1458             // If we are trying to add an actual method via MethodKindEnum.Actual, and
1459             // the memberinfo is a special name, and its not static, then return null.
1460             // We'll re-add the thing later with some other method kind.
1461             //
1462             // This will happen for things like indexers and properties. The ones that have
1463             // special names that we DO want to allow adding are things like operators, which
1464             // are static and will not be added again later.
1465 
1466             if (kind == MethodKindEnum.Actual && // MethKindEnum.Actual
1467                 (method == null || // Not a ConstructorInfo
1468                     (!method.IsStatic && method.IsSpecialName))) // Not static and is a special name
1469             {
1470                 return null;
1471             }
1472 
1473             MethodSymbol methodSymbol = FindMatchingMethod(member, callingAggregate);
1474             if (methodSymbol != null)
1475             {
1476                 return methodSymbol;
1477             }
1478 
1479             ParameterInfo[] parameters = member.GetParameters();
1480             // First create the method.
1481             methodSymbol = _symFactory.CreateMethod(GetName(member.Name), callingAggregate);
1482             methodSymbol.AssociatedMemberInfo = member;
1483             methodSymbol.SetMethKind(kind);
1484             if (kind == MethodKindEnum.ExplicitConv || kind == MethodKindEnum.ImplicitConv)
1485             {
1486                 callingAggregate.SetHasConversion();
1487                 methodSymbol.SetConvNext(callingAggregate.GetFirstUDConversion());
1488                 callingAggregate.SetFirstUDConversion(methodSymbol);
1489             }
1490 
1491             ACCESS access;
1492             if (member.IsPublic)
1493             {
1494                 access = ACCESS.ACC_PUBLIC;
1495             }
1496             else if (member.IsPrivate)
1497             {
1498                 access = ACCESS.ACC_PRIVATE;
1499             }
1500             else if (member.IsFamily)
1501             {
1502                 access = ACCESS.ACC_PROTECTED;
1503             }
1504             else if (member.IsFamilyOrAssembly)
1505             {
1506                 access = ACCESS.ACC_INTERNALPROTECTED;
1507             }
1508             else if (member.IsAssembly)
1509             {
1510                 access = ACCESS.ACC_INTERNAL;
1511             }
1512             else
1513             {
1514                 Debug.Assert(member.IsFamilyAndAssembly);
1515                 access = ACCESS.ACC_INTERNAL_AND_PROTECTED;
1516             }
1517 
1518             methodSymbol.SetAccess(access);
1519             methodSymbol.isVirtual = member.IsVirtual;
1520             methodSymbol.isStatic = member.IsStatic;
1521 
1522             if (method != null)
1523             {
1524                 methodSymbol.typeVars = GetMethodTypeParameters(method, methodSymbol);
1525                 methodSymbol.isOverride = method.IsVirtual && method.IsHideBySig && method.GetRuntimeBaseDefinition() != method;
1526                 methodSymbol.isOperator = IsOperator(method);
1527                 methodSymbol.swtSlot = GetSlotForOverride(method);
1528                 methodSymbol.RetType = GetCTypeFromType(method.ReturnType);
1529             }
1530             else
1531             {
1532                 methodSymbol.typeVars = BSYMMGR.EmptyTypeArray();
1533                 methodSymbol.isOverride = false;
1534                 methodSymbol.isOperator = false;
1535                 methodSymbol.swtSlot = null;
1536                 methodSymbol.RetType = _typeManager.GetVoid();
1537             }
1538 
1539             methodSymbol.modOptCount = GetCountOfModOpts(parameters);
1540 
1541             methodSymbol.isParamArray = DoesMethodHaveParameterArray(parameters);
1542             methodSymbol.isHideByName = false;
1543 
1544             methodSymbol.Params = CreateParameterArray(methodSymbol.AssociatedMemberInfo, parameters);
1545 
1546             SetParameterDataForMethProp(methodSymbol, parameters);
1547 
1548             return methodSymbol;
1549         }
1550 
1551         /////////////////////////////////////////////////////////////////////////////////
1552 
SetParameterDataForMethProp(MethodOrPropertySymbol methProp, ParameterInfo[] parameters)1553         private void SetParameterDataForMethProp(MethodOrPropertySymbol methProp, ParameterInfo[] parameters)
1554         {
1555             if (parameters.Length > 0)
1556             {
1557                 // See if we have a param array.
1558                 if (parameters[parameters.Length - 1].GetCustomAttribute(typeof(ParamArrayAttribute), false) != null)
1559                 {
1560                     methProp.isParamArray = true;
1561                 }
1562 
1563                 // Mark the names of the parameters, and their default values.
1564                 for (int i = 0; i < parameters.Length; i++)
1565                 {
1566                     SetParameterAttributes(methProp, parameters, i);
1567 
1568                     // Insert the name.
1569                     methProp.ParameterNames.Add(GetName(parameters[i].Name));
1570                 }
1571             }
1572         }
1573 
1574         /////////////////////////////////////////////////////////////////////////////////
1575 
SetParameterAttributes(MethodOrPropertySymbol methProp, ParameterInfo[] parameters, int i)1576         private void SetParameterAttributes(MethodOrPropertySymbol methProp, ParameterInfo[] parameters, int i)
1577         {
1578             ParameterInfo parameter = parameters[i];
1579             if ((parameter.Attributes & ParameterAttributes.Optional) != 0 && !parameter.ParameterType.IsByRef)
1580             {
1581                 methProp.SetOptionalParameter(i);
1582                 PopulateSymbolTableWithName("Value", new Type[] { typeof(Missing) }, typeof(Missing)); // We might need this later
1583             }
1584 
1585             // Get MarshalAsAttribute
1586             if ((parameter.Attributes & ParameterAttributes.HasFieldMarshal) != 0)
1587             {
1588                 MarshalAsAttribute attr = parameter.GetCustomAttribute<MarshalAsAttribute>(false);
1589                 if (attr != null)
1590                 {
1591                     methProp.SetMarshalAsParameter(i, attr.Value);
1592                 }
1593             }
1594 
1595             DateTimeConstantAttribute dateAttr = parameter.GetCustomAttribute<DateTimeConstantAttribute>(false);
1596             // Get the various kinds of default values
1597             if (dateAttr != null)
1598             {
1599                 // Get DateTimeConstant
1600                 ConstVal cv = ConstVal.Get(((DateTime)dateAttr.Value).Ticks);
1601                 CType cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_DATETIME);
1602                 methProp.SetDefaultParameterValue(i, cvType, cv);
1603             }
1604             else
1605             {
1606                 DecimalConstantAttribute decAttr = parameter.GetCustomAttribute<DecimalConstantAttribute>();
1607                 if (decAttr != null)
1608                 {
1609                     // Get DecimalConstant
1610                     ConstVal cv = ConstVal.Get(decAttr.Value);
1611                     CType cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_DECIMAL);
1612                     methProp.SetDefaultParameterValue(i, cvType, cv);
1613                 }
1614                 else if ((parameter.Attributes & ParameterAttributes.HasDefault) != 0 && !parameter.ParameterType.IsByRef)
1615                 {
1616                     // Only set a default value if we have one, and the type that we're
1617                     // looking at isn't a by ref type or a type parameter.
1618 
1619                     ConstVal cv = default(ConstVal);
1620                     CType cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_OBJECT);
1621 
1622                     // We need to use RawDefaultValue, because DefaultValue is too clever.
1623 #if UNSUPPORTEDAPI
1624                     if (parameter.RawDefaultValue != null)
1625                     {
1626                         object defValue = parameter.RawDefaultValue;
1627 #else
1628                     if (parameter.DefaultValue != null)
1629                     {
1630                         object defValue = parameter.DefaultValue;
1631 #endif
1632                         Debug.Assert(Type.GetTypeCode(defValue.GetType()) != TypeCode.Decimal); // Handled above
1633                         switch (Type.GetTypeCode(defValue.GetType()))
1634                         {
1635 
1636                             case TypeCode.Byte:
1637                                 cv = ConstVal.Get((byte)defValue);
1638                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_BYTE);
1639                                 break;
1640 
1641                             case TypeCode.Int16:
1642                                 cv = ConstVal.Get((short)defValue);
1643                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_SHORT);
1644                                 break;
1645 
1646                             case TypeCode.Int32:
1647                                 cv = ConstVal.Get((int)defValue);
1648                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_INT);
1649                                 break;
1650 
1651                             case TypeCode.Int64:
1652                                 cv = ConstVal.Get((long)defValue);
1653                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_LONG);
1654                                 break;
1655 
1656                             case TypeCode.Single:
1657                                 cv = ConstVal.Get((float)defValue);
1658                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_FLOAT);
1659                                 break;
1660 
1661                             case TypeCode.Double:
1662                                 cv = ConstVal.Get((double)defValue);
1663                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_DOUBLE);
1664                                 break;
1665 
1666                             case TypeCode.Char:
1667                                 cv = ConstVal.Get((char)defValue);
1668                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_CHAR);
1669                                 break;
1670 
1671                             case TypeCode.Boolean:
1672                                 cv = ConstVal.Get((bool)defValue);
1673                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_BOOL);
1674                                 break;
1675 
1676                             case TypeCode.SByte:
1677                                 cv = ConstVal.Get((sbyte)defValue);
1678                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_SBYTE);
1679                                 break;
1680 
1681                             case TypeCode.UInt16:
1682                                 cv = ConstVal.Get((ushort)defValue);
1683                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_USHORT);
1684                                 break;
1685 
1686                             case TypeCode.UInt32:
1687                                 cv = ConstVal.Get((uint)defValue);
1688                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_UINT);
1689                                 break;
1690 
1691                             case TypeCode.UInt64:
1692                                 cv = ConstVal.Get((ulong)defValue);
1693                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_ULONG);
1694                                 break;
1695 
1696                             case TypeCode.String:
1697                                 cv = ConstVal.Get((string)defValue);
1698                                 cvType = _semanticChecker.SymbolLoader.GetPredefindType(PredefinedType.PT_STRING);
1699                                 break;
1700                         }
1701 
1702                         // if we hit no case in the switch, we get object/null
1703                         // because that's how we initialized the constval.
1704                     }
1705 
1706                     methProp.SetDefaultParameterValue(i, cvType, cv);
1707                 }
1708             }
1709         }
1710 
1711         /////////////////////////////////////////////////////////////////////////////////
1712 
1713         private MethodSymbol FindMatchingMethod(MemberInfo method, AggregateSymbol callingAggregate)
1714         {
1715             MethodSymbol meth = _bsymmgr.LookupAggMember(GetName(method.Name), callingAggregate, symbmask_t.MASK_MethodSymbol) as MethodSymbol;
1716             while (meth != null)
1717             {
1718                 if (meth.AssociatedMemberInfo.IsEquivalentTo(method))
1719                 {
1720                     return meth;
1721                 }
1722                 meth = BSYMMGR.LookupNextSym(meth, callingAggregate, symbmask_t.MASK_MethodSymbol) as MethodSymbol;
1723             }
1724             return null;
1725         }
1726 
1727         /////////////////////////////////////////////////////////////////////////////////
1728 
1729         private uint GetCountOfModOpts(ParameterInfo[] parameters)
1730         {
1731             uint count = 0;
1732 #if UNSUPPORTEDAPI
1733             foreach (ParameterInfo p in parameters)
1734             {
1735                 if (p.GetOptionalCustomModifiers() != null)
1736                 {
1737                     count += (uint)p.GetOptionalCustomModifiers().Length;
1738                 }
1739             }
1740 #endif
1741             return count;
1742         }
1743 
1744         /////////////////////////////////////////////////////////////////////////////////
1745 
1746         private TypeArray CreateParameterArray(MemberInfo associatedInfo, ParameterInfo[] parameters)
1747         {
1748             List<CType> types = new List<CType>();
1749 
1750             foreach (ParameterInfo p in parameters)
1751             {
1752                 types.Add(GetTypeOfParameter(p, associatedInfo));
1753             }
1754 
1755             if (associatedInfo is MethodBase mb && (mb.CallingConvention & CallingConventions.VarArgs) != 0)
1756             {
1757                 types.Add(_typeManager.GetArgListType());
1758             }
1759 
1760             return _bsymmgr.AllocParams(types.Count, types.ToArray());
1761         }
1762 
1763         /////////////////////////////////////////////////////////////////////////////////
1764 
1765         private CType GetTypeOfParameter(ParameterInfo p, MemberInfo m)
1766         {
1767             Type t = p.ParameterType;
1768             CType ctype;
1769             if (t.IsGenericParameter && t.DeclaringMethod != null && t.DeclaringMethod == m)
1770             {
1771                 // If its a method type parameter from ourselves, just find it.
1772                 ctype = LoadMethodTypeParameter(FindMethodFromMemberInfo(m), t);
1773             }
1774             else
1775             {
1776                 ctype = GetCTypeFromType(t);
1777             }
1778 
1779             // Check if we have an out parameter.
1780             if (ctype is ParameterModifierType mod && p.IsOut && !p.IsIn)
1781             {
1782                 CType parameterType = mod.GetParameterType();
1783                 ctype = _typeManager.GetParameterModifier(parameterType, true);
1784             }
1785 
1786             return ctype;
1787         }
1788 
1789         /////////////////////////////////////////////////////////////////////////////////
1790 
1791         private bool DoesMethodHaveParameterArray(ParameterInfo[] parameters)
1792         {
1793             if (parameters.Length == 0)
1794             {
1795                 return false;
1796             }
1797 
1798             ParameterInfo p = parameters[parameters.Length - 1];
1799             var attributes = p.GetCustomAttributes(false);
1800 
1801             foreach (object o in attributes)
1802             {
1803                 if (o is ParamArrayAttribute)
1804                 {
1805                     return true;
1806                 }
1807             }
1808             return false;
1809         }
1810 
1811         /////////////////////////////////////////////////////////////////////////////////
1812 
1813         private SymWithType GetSlotForOverride(MethodInfo method)
1814         {
1815             if (method.IsVirtual && method.IsHideBySig)
1816             {
1817                 MethodInfo baseMethodInfo = method.GetRuntimeBaseDefinition();
1818                 if (baseMethodInfo == method)
1819                 {
1820                     // We just found ourselves, so we don't care here.
1821                     return null;
1822                 }
1823 
1824                 // We have the base class method that we're overriding. We can assume
1825                 // that all the parent aggregate symbols were added, and that we added
1826                 // the methods in order. As such, our parent methods should be in the
1827                 // symbol table at this point.
1828 
1829                 AggregateSymbol aggregate = GetCTypeFromType(baseMethodInfo.DeclaringType).getAggregate();
1830                 MethodSymbol baseMethod = FindMethodFromMemberInfo(baseMethodInfo);
1831                 Debug.Assert(baseMethod != null);
1832                 return new SymWithType(baseMethod, aggregate.getThisType());
1833             }
1834 
1835             return null;
1836         }
1837 
1838         /////////////////////////////////////////////////////////////////////////////////
1839 
1840         private MethodSymbol FindMethodFromMemberInfo(MemberInfo baseMemberInfo)
1841         {
1842             CType t = GetCTypeFromType(baseMemberInfo.DeclaringType);
1843             Debug.Assert(t is AggregateType);
1844             AggregateSymbol aggregate = t.getAggregate();
1845             Debug.Assert(aggregate != null);
1846 
1847             MethodSymbol meth = _semanticChecker.SymbolLoader.LookupAggMember(
1848                 GetName(baseMemberInfo.Name),
1849                 aggregate,
1850                 symbmask_t.MASK_MethodSymbol) as MethodSymbol;
1851             for (;
1852                     meth != null && !meth.AssociatedMemberInfo.IsEquivalentTo(baseMemberInfo);
1853                     meth = SymbolLoader.LookupNextSym(meth, aggregate, symbmask_t.MASK_MethodSymbol) as MethodSymbol)
1854                 ;
1855 
1856             return meth;
1857         }
1858 
1859         /////////////////////////////////////////////////////////////////////////////////
1860 
1861         internal bool AggregateContainsMethod(AggregateSymbol agg, string szName, symbmask_t mask)
1862         {
1863             return _semanticChecker.SymbolLoader.LookupAggMember(GetName(szName), agg, mask) != null;
1864         }
1865         #endregion
1866 
1867         #region Conversions
1868         /////////////////////////////////////////////////////////////////////////////////
1869 
1870         internal void AddConversionsForType(Type type)
1871         {
1872             if (type.IsInterface)
1873             {
1874                 AddConversionsForOneType(type);
1875             }
1876             for (Type t = type; t.BaseType != null; t = t.BaseType)
1877             {
1878                 AddConversionsForOneType(t);
1879             }
1880         }
1881 
1882         /////////////////////////////////////////////////////////////////////////////////
1883 
1884         private void AddConversionsForOneType(Type type)
1885         {
1886             if (type.IsGenericType)
1887             {
1888                 type = type.GetGenericTypeDefinition();
1889             }
1890 
1891             if (!_typesWithConversionsLoaded.Add(type))
1892             {
1893                 return;
1894             }
1895 
1896             // Always make the aggregate for the type, regardless of whether or not
1897             // there are any conversions.
1898             CType t = GetCTypeFromType(type);
1899 
1900             if (!(t is AggregateType))
1901             {
1902                 CType endT;
1903                 while ((endT = t.GetBaseOrParameterOrElementType()) != null)
1904                 {
1905                     t = endT;
1906                 }
1907             }
1908 
1909             if (t is TypeParameterType paramType)
1910             {
1911                 // Add conversions for the bounds.
1912                 foreach (CType bound in paramType.GetBounds().Items)
1913                 {
1914                     AddConversionsForType(bound.AssociatedSystemType);
1915                 }
1916                 return;
1917             }
1918 
1919             Debug.Assert(t is AggregateType);
1920             AggregateSymbol aggregate = ((AggregateType)t).getAggregate();
1921 
1922             // Now find all the conversions and make them.
1923             foreach (MethodInfo conversion in type.GetRuntimeMethods())
1924             {
1925                 if (conversion.IsPublic && conversion.IsStatic && conversion.DeclaringType == type
1926                     && conversion.IsSpecialName && !conversion.IsGenericMethod)
1927                 {
1928                     MethodKindEnum methodKind;
1929                     switch (conversion.Name)
1930                     {
1931                         case SpecialNames.ImplicitConversion:
1932                             methodKind = MethodKindEnum.ImplicitConv;
1933                             break;
1934                         case SpecialNames.ExplicitConversion:
1935                             methodKind = MethodKindEnum.ExplicitConv;
1936                             break;
1937                         default:
1938                             continue;
1939                     }
1940 
1941                     AddMethodToSymbolTable(conversion, aggregate, methodKind);
1942                 }
1943             }
1944         }
1945         #endregion
1946 
1947         #region Operators
1948         /////////////////////////////////////////////////////////////////////////////////
1949 
1950         private static bool IsOperator(MethodInfo method)
1951         {
1952             if (method.IsSpecialName && method.IsStatic)
1953             {
1954                 switch (method.Name)
1955                 {
1956                     case SpecialNames.ImplicitConversion:
1957                     case SpecialNames.ExplicitConversion:
1958                     case SpecialNames.CLR_Add:
1959                     case SpecialNames.CLR_Subtract:
1960                     case SpecialNames.CLR_Multiply:
1961                     case SpecialNames.CLR_Division:
1962                     case SpecialNames.CLR_Modulus:
1963                     case SpecialNames.CLR_LShift:
1964                     case SpecialNames.CLR_RShift:
1965                     case SpecialNames.CLR_LT:
1966                     case SpecialNames.CLR_GT:
1967                     case SpecialNames.CLR_LTE:
1968                     case SpecialNames.CLR_GTE:
1969                     case SpecialNames.CLR_Equality:
1970                     case SpecialNames.CLR_Inequality:
1971                     case SpecialNames.CLR_BitwiseAnd:
1972                     case SpecialNames.CLR_ExclusiveOr:
1973                     case SpecialNames.CLR_BitwiseOr:
1974                     case SpecialNames.CLR_LogicalNot:
1975                     case SpecialNames.CLR_UnaryNegation:
1976                     case SpecialNames.CLR_UnaryPlus:
1977                     case SpecialNames.CLR_OnesComplement:
1978                     case SpecialNames.CLR_True:
1979                     case SpecialNames.CLR_False:
1980                     case SpecialNames.CLR_PreIncrement:
1981                     case SpecialNames.CLR_PreDecrement:
1982                         return true;
1983                 }
1984             }
1985 
1986             return false;
1987         }
1988 
1989         #endregion
1990     }
1991 }
1992