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.Runtime.InteropServices;
9 using Microsoft.CSharp.RuntimeBinder.Syntax;
10 
11 namespace Microsoft.CSharp.RuntimeBinder.Semantics
12 {
13     // ----------------------------------------------------------------------------
14     //
15     // MethodOrPropertySymbol
16     //
17     // MethodOrPropertySymbol - abstract class representing a method or a property. There
18     // are a bunch of algorithms in the compiler (e.g., override and overload
19     // resolution) that want to treat methods and properties the same. This
20     // abstract base class has the common parts.
21     //
22     // Changed to a ParentSymbol to allow generic methods to parent their type
23     // variables.
24     // ----------------------------------------------------------------------------
25 
26     internal abstract class MethodOrPropertySymbol : ParentSymbol
27     {
28         public uint modOptCount;              // number of CMOD_OPTs in signature and return type
29 
30         public new bool isStatic;               // Static member?
31         public bool isOverride;             // Overrides an inherited member. Only valid if isVirtual is set.
32                                             // false implies that a new vtable slot is required for this method.
33         public bool isOperator;             // a user defined operator (or default indexed property)
34         public bool isParamArray;           // new style varargs
35         public bool isHideByName;           // this property hides all below it regardless of signature
36         public List<Name> ParameterNames { get; private set; }
37         private bool[] _optionalParameterIndex;
38         private bool[] _defaultParameterIndex;
39         private ConstVal[] _defaultParameters;
40         private CType[] _defaultParameterConstValTypes;
41         private bool[] _marshalAsIndex;
42         private UnmanagedType[] _marshalAsBuffer;
43 
44         // This indicates the base member that this member overrides or implements.
45         // For an explicit interface member implementation, this is the interface member (and type)
46         // that the member implements. For an override member, this is the base member that is
47         // being overridden. This is not affected by implicit interface member implementation.
48         // If this symbol is a property and an explicit interface member implementation, the swtSlot
49         // may be an event. This is filled in during prepare.
50         public SymWithType swtSlot;
51         public CType RetType;            // Return type.
52 
53         private TypeArray _Params;
54         public TypeArray Params
55         {
56             get
57             {
58                 return _Params;
59             }
60             set
61             {
62                 Debug.Assert(_Params == null, "Should only be set once");
63                 _Params = value;
64                 int count = value.Count;
65                 if (count == 0)
66                 {
67                     _optionalParameterIndex = _defaultParameterIndex = _marshalAsIndex = Array.Empty<bool>();
68                     _defaultParameters = Array.Empty<ConstVal>();
69                     _defaultParameterConstValTypes = Array.Empty<CType>();
70                     _marshalAsBuffer = Array.Empty<UnmanagedType>();
71                 }
72                 else
73                 {
74                     _optionalParameterIndex = new bool[count];
75                     _defaultParameterIndex = new bool[count];
76                     _defaultParameters = new ConstVal[count];
77                     _defaultParameterConstValTypes = new CType[count];
78                     _marshalAsIndex = new bool[count];
79                     _marshalAsBuffer = new UnmanagedType[count];
80                 }
81             }
82         }
83 
MethodOrPropertySymbol()84         public MethodOrPropertySymbol()
85         {
86             ParameterNames = new List<Name>();
87         }
88 
89         /////////////////////////////////////////////////////////////////////////////////
90 
IsParameterOptional(int index)91         public bool IsParameterOptional(int index)
92         {
93             Debug.Assert(index < Params.Count);
94 
95             if (_optionalParameterIndex == null)
96             {
97                 return false;
98             }
99             return _optionalParameterIndex[index];
100         }
101 
SetOptionalParameter(int index)102         public void SetOptionalParameter(int index)
103         {
104             Debug.Assert(_optionalParameterIndex != null);
105             _optionalParameterIndex[index] = true;
106         }
107 
HasOptionalParameters()108         public bool HasOptionalParameters()
109         {
110             if (_optionalParameterIndex == null)
111             {
112                 return false;
113             }
114             foreach (bool b in _optionalParameterIndex)
115             {
116                 if (b)
117                 {
118                     return true;
119                 }
120             }
121             return false;
122         }
123 
HasDefaultParameterValue(int index)124         public bool HasDefaultParameterValue(int index)
125         {
126             Debug.Assert(index < Params.Count);
127             Debug.Assert(_defaultParameterIndex != null);
128             return _defaultParameterIndex[index];
129         }
130 
SetDefaultParameterValue(int index, CType type, ConstVal cv)131         public void SetDefaultParameterValue(int index, CType type, ConstVal cv)
132         {
133             Debug.Assert(_defaultParameterIndex != null);
134             _defaultParameterIndex[index] = true;
135             _defaultParameters[index] = cv;
136             _defaultParameterConstValTypes[index] = type;
137         }
138 
GetDefaultParameterValue(int index)139         public ConstVal GetDefaultParameterValue(int index)
140         {
141             Debug.Assert(HasDefaultParameterValue(index));
142             Debug.Assert(_defaultParameterIndex != null);
143             return _defaultParameters[index];
144         }
145 
GetDefaultParameterValueConstValType(int index)146         public CType GetDefaultParameterValueConstValType(int index)
147         {
148             Debug.Assert(HasDefaultParameterValue(index));
149             return _defaultParameterConstValTypes[index];
150         }
151 
IsMarshalAsParameter(int index)152         private bool IsMarshalAsParameter(int index)
153         {
154             return _marshalAsIndex[index];
155         }
156 
SetMarshalAsParameter(int index, UnmanagedType umt)157         public void SetMarshalAsParameter(int index, UnmanagedType umt)
158         {
159             _marshalAsIndex[index] = true;
160             _marshalAsBuffer[index] = umt;
161         }
162 
GetMarshalAsParameterValue(int index)163         private UnmanagedType GetMarshalAsParameterValue(int index)
164         {
165             Debug.Assert(IsMarshalAsParameter(index));
166             return _marshalAsBuffer[index];
167         }
168 
MarshalAsObject(int index)169         public bool MarshalAsObject(int index)
170         {
171             if (IsMarshalAsParameter(index))
172             {
173                 UnmanagedType marshalAsType = GetMarshalAsParameterValue(index);
174                 return marshalAsType == UnmanagedType.Interface || marshalAsType == UnmanagedType.IUnknown || marshalAsType == UnmanagedType.IDispatch;
175             }
176 
177             return false;
178         }
179 
getClass()180         public AggregateSymbol getClass() => parent as AggregateSymbol;
181 
IsExpImpl()182         public bool IsExpImpl()
183         {
184             return name == null;
185         }
186     }
187 }
188