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.Diagnostics;
6 using System.Reflection;
7 using Microsoft.CSharp.RuntimeBinder.Syntax;
8 
9 namespace Microsoft.CSharp.RuntimeBinder.Semantics
10 {
11     ////////////////////////////////////////////////////////////////////////////////
12     //
13     // MethodSymbol - a symbol representing a method. Parent is a struct, interface
14     // or class (aggregate). No children.
15 
16     internal sealed class MethodSymbol : MethodOrPropertySymbol
17     {
18         private MethodKindEnum _methKind; // An extra bit to prevent sign-extension
19         private bool _inferenceMustFail; // Inference must fail if there are no type variables or if
20         private bool _checkedInfMustFail; // there is a type variable used in no parameter.
21 
22         private MethodSymbol _convNext; // For linked list of conversion operators.
23         private PropertySymbol _prop;     // For property accessors, this is the PropertySymbol.
24         private EventSymbol _evt;     // For event accessors, this is the EventSymbol.
25 
26         public bool isVirtual;              // Virtual member?
27         public MemberInfo AssociatedMemberInfo;
28 
29         public TypeArray typeVars;          // All the type variables for a generic method, as declarations.
30 
31         // If there is a type variable in the method which is used in no parameter,
32         // then inference must fail. Since this is expensive to check, we cache
33         // the result of the first call.
34 
InferenceMustFail()35         public bool InferenceMustFail()
36         {
37             if (_checkedInfMustFail)
38             {
39                 return _inferenceMustFail;
40             }
41             Debug.Assert(!_inferenceMustFail);
42             _checkedInfMustFail = true;
43             for (int ivar = 0; ivar < typeVars.Count; ivar++)
44             {
45                 TypeParameterType var = (TypeParameterType)typeVars[ivar];
46                 // See if type var is used in a parameter.
47                 for (int ipar = 0; ; ipar++)
48                 {
49                     if (ipar >= Params.Count)
50                     {
51                         // This type variable is not in any parameter.
52                         _inferenceMustFail = true;
53                         return true;
54                     }
55                     if (TypeManager.TypeContainsType(Params[ipar], var))
56                     {
57                         break;
58                     }
59                 }
60             }
61             // All type variables are used in a parameter.
62             return false;
63         }
64 
MethKind()65         public MethodKindEnum MethKind()
66         {
67             return _methKind;
68         }
69 
IsConstructor()70         public bool IsConstructor()
71         {
72             return _methKind == MethodKindEnum.Constructor;
73         }
74 
IsNullableConstructor()75         public bool IsNullableConstructor()
76         {
77             return getClass().isPredefAgg(PredefinedType.PT_G_OPTIONAL) &&
78                 Params.Count == 1 &&
79                 Params[0] is TypeParameterType &&
80                 IsConstructor();
81         }
82 
IsDestructor()83         public bool IsDestructor()              // Is a destructor
84         {
85             return _methKind == MethodKindEnum.Destructor;
86         }
87 
isPropertyAccessor()88         public bool isPropertyAccessor()  // true if this method is a property set or get method
89         {
90             return _methKind == MethodKindEnum.PropAccessor;
91         }
92 
isEventAccessor()93         public bool isEventAccessor()     // true if this method is an event add/remove method
94         {
95             return _methKind == MethodKindEnum.EventAccessor;
96         }
97 
isExplicit()98         private bool isExplicit()          // is user defined explicit conversion operator
99         {
100             return _methKind == MethodKindEnum.ExplicitConv;
101         }
102 
isImplicit()103         public bool isImplicit()          // is user defined implicit conversion operator
104         {
105             return _methKind == MethodKindEnum.ImplicitConv;
106         }
107 
isInvoke()108         public bool isInvoke()            // Invoke method on a delegate - isn't user callable
109         {
110             return _methKind == MethodKindEnum.Invoke;
111         }
112 
SetMethKind(MethodKindEnum mk)113         public void SetMethKind(MethodKindEnum mk)
114         {
115             _methKind = mk;
116         }
117 
ConvNext()118         public MethodSymbol ConvNext()
119         {
120             Debug.Assert(isImplicit() || isExplicit());
121             return _convNext;
122         }
123 
SetConvNext(MethodSymbol conv)124         public void SetConvNext(MethodSymbol conv)
125         {
126             Debug.Assert(isImplicit() || isExplicit());
127             Debug.Assert(conv == null || conv.isImplicit() || conv.isExplicit());
128             _convNext = conv;
129         }
130 
getProperty()131         public PropertySymbol getProperty()
132         {
133             Debug.Assert(isPropertyAccessor());
134             return _prop;
135         }
136 
SetProperty(PropertySymbol prop)137         public void SetProperty(PropertySymbol prop)
138         {
139             Debug.Assert(isPropertyAccessor());
140             _prop = prop;
141         }
142 
getEvent()143         public EventSymbol getEvent()
144         {
145             Debug.Assert(isEventAccessor());
146             return _evt;
147         }
148 
SetEvent(EventSymbol evt)149         public void SetEvent(EventSymbol evt)
150         {
151             Debug.Assert(isEventAccessor());
152             _evt = evt;
153         }
154 
isConversionOperator()155         public bool isConversionOperator()
156         {
157             return (isExplicit() || isImplicit());
158         }
159 
isUserCallable()160         public new bool isUserCallable()
161         {
162             return !isOperator && !isAnyAccessor();
163         }
164 
isAnyAccessor()165         private bool isAnyAccessor()
166         {
167             return isPropertyAccessor() || isEventAccessor();
168         }
169 
170         /*
171          * returns true if this property is a set accessor
172          */
isSetAccessor()173         public bool isSetAccessor()
174         {
175             if (!isPropertyAccessor())
176             {
177                 return false;
178             }
179 
180             PropertySymbol property = getProperty();
181 
182             if (property == null)
183             {
184                 Debug.Assert(false, "cannot find property for accessor");
185                 return false;
186             }
187 
188             return (this == property.SetterMethod);
189         }
190     }
191 }
192