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