~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
 
2
// 
 
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
 
4
// software and associated documentation files (the "Software"), to deal in the Software
 
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
 
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
 
7
// to whom the Software is furnished to do so, subject to the following conditions:
 
8
// 
 
9
// The above copyright notice and this permission notice shall be included in all copies or
 
10
// substantial portions of the Software.
 
11
// 
 
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
17
// DEALINGS IN THE SOFTWARE.
 
18
 
 
19
using System;
 
20
using System.Collections.Generic;
 
21
using System.Diagnostics;
 
22
using System.Linq;
 
23
using System.Text;
 
24
using System.Threading;
 
25
using ICSharpCode.NRefactory.Utils;
 
26
 
 
27
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
 
28
{
 
29
        /// <summary>
 
30
        /// Represents a specialized IMethod (e.g. after type substitution).
 
31
        /// </summary>
 
32
        public class SpecializedMethod : SpecializedParameterizedMember, IMethod
 
33
        {
 
34
                readonly IMethod methodDefinition;
 
35
                readonly ITypeParameter[] specializedTypeParameters;
 
36
                readonly bool isParameterized;
 
37
                readonly TypeParameterSubstitution substitutionWithoutSpecializedTypeParameters;
 
38
                
 
39
                public SpecializedMethod(IMethod methodDefinition, TypeParameterSubstitution substitution)
 
40
                        : base(methodDefinition)
 
41
                {
 
42
                        if (substitution == null)
 
43
                                throw new ArgumentNullException("substitution");
 
44
                        this.methodDefinition = methodDefinition;
 
45
                        this.isParameterized = substitution.MethodTypeArguments != null;
 
46
                        if (methodDefinition.TypeParameters.Count > 0) {
 
47
                                // The method is generic, so we need to specialize the type parameters
 
48
                                // (for specializing the constraints, and also to set the correct Owner)
 
49
                                specializedTypeParameters = new ITypeParameter[methodDefinition.TypeParameters.Count];
 
50
                                for (int i = 0; i < specializedTypeParameters.Length; i++) {
 
51
                                        specializedTypeParameters[i] = new SpecializedTypeParameter(methodDefinition.TypeParameters[i], this);
 
52
                                }
 
53
                                if (!isParameterized) {
 
54
                                        // Add substitution that replaces the base method's type parameters with our specialized version
 
55
                                        // but do this only if the type parameters on the baseMember have not already been substituted
 
56
                                        substitutionWithoutSpecializedTypeParameters = this.Substitution;
 
57
                                        AddSubstitution(new TypeParameterSubstitution(null, specializedTypeParameters));
 
58
                                }
 
59
                        }
 
60
                        // Add the main substitution after the method type parameter specialization.
 
61
                        AddSubstitution(substitution);
 
62
                        if (substitutionWithoutSpecializedTypeParameters != null) {
 
63
                                // If we already have a substitution without specialized type parameters, update that:
 
64
                                substitutionWithoutSpecializedTypeParameters = TypeParameterSubstitution.Compose(substitution, substitutionWithoutSpecializedTypeParameters);
 
65
                        } else {
 
66
                                // Otherwise just use the whole substitution, as that doesn't contain specialized type parameters
 
67
                                // in this case.
 
68
                                substitutionWithoutSpecializedTypeParameters = this.Substitution;
 
69
                        }
 
70
                        if (specializedTypeParameters != null) {
 
71
                                // Set the substitution on the type parameters to the final composed substitution
 
72
                                foreach (var tp in specializedTypeParameters.OfType<SpecializedTypeParameter>()) {
 
73
                                        if (tp.Owner == this)
 
74
                                                tp.substitution = base.Substitution;
 
75
                                }
 
76
                        }
 
77
                }
 
78
                
 
79
                public IList<IType> TypeArguments {
 
80
                        get { return this.Substitution.MethodTypeArguments ?? EmptyList<IType>.Instance; }
 
81
                }
 
82
                
 
83
                public bool IsParameterized {
 
84
                        get { return isParameterized; }
 
85
                }
 
86
                
 
87
                public IList<IUnresolvedMethod> Parts {
 
88
                        get { return methodDefinition.Parts; }
 
89
                }
 
90
                
 
91
                public IList<IAttribute> ReturnTypeAttributes {
 
92
                        get { return methodDefinition.ReturnTypeAttributes; }
 
93
                }
 
94
                
 
95
                public IList<ITypeParameter> TypeParameters {
 
96
                        get {
 
97
                                return specializedTypeParameters ?? methodDefinition.TypeParameters;
 
98
                        }
 
99
                }
 
100
                
 
101
                public bool IsExtensionMethod {
 
102
                        get { return methodDefinition.IsExtensionMethod; }
 
103
                }
 
104
                
 
105
                public bool IsConstructor {
 
106
                        get { return methodDefinition.IsConstructor; }
 
107
                }
 
108
                
 
109
                public bool IsDestructor {
 
110
                        get { return methodDefinition.IsDestructor; }
 
111
                }
 
112
                
 
113
                public bool IsOperator {
 
114
                        get { return methodDefinition.IsOperator; }
 
115
                }
 
116
                
 
117
                public bool IsPartial {
 
118
                        get { return methodDefinition.IsPartial; }
 
119
                }
 
120
                
 
121
                public bool IsAsync {
 
122
                        get { return methodDefinition.IsAsync; }
 
123
                }
 
124
                
 
125
                public bool HasBody {
 
126
                        get { return methodDefinition.HasBody; }
 
127
                }
 
128
                
 
129
                public bool IsAccessor {
 
130
                        get { return methodDefinition.IsAccessor; }
 
131
                }
 
132
 
 
133
                public IMethod ReducedFrom {
 
134
                        get { return null; }
 
135
                }
 
136
 
 
137
                IMember accessorOwner;
 
138
                
 
139
                public IMember AccessorOwner {
 
140
                        get {
 
141
                                var result = LazyInit.VolatileRead(ref accessorOwner);
 
142
                                if (result != null) {
 
143
                                        return result;
 
144
                                } else {
 
145
                                        var ownerDefinition = methodDefinition.AccessorOwner;
 
146
                                        if (ownerDefinition == null)
 
147
                                                return null;
 
148
                                        result = ownerDefinition.Specialize(this.Substitution);
 
149
                                        return LazyInit.GetOrSet(ref accessorOwner, result);
 
150
                                }
 
151
                        }
 
152
                        internal set {
 
153
                                accessorOwner = value;
 
154
                        }
 
155
                }
 
156
 
 
157
                public override IMemberReference ToMemberReference()
 
158
                {
 
159
                        // Pass the MethodTypeArguments to the SpecializingMemberReference only if
 
160
                        // the generic method itself is parameterized, not if the generic method is only
 
161
                        // specialized with class type arguments.
 
162
                        
 
163
                        // This is necessary due to this part of the ToMemberReference() contract:
 
164
                        //   If this member is specialized using open generic types, the resulting member reference will need to be looked up in an appropriate generic context.
 
165
                        //   Otherwise, the main resolve context of a compilation is sufficient.
 
166
                        // ->
 
167
                        // This means that if the method itself isn't specialized,
 
168
                        // we must not include TypeParameterReferences for the specialized type parameters
 
169
                        // in the resulting member reference.
 
170
                        if (isParameterized) {
 
171
                                return new SpecializingMemberReference(
 
172
                                        baseMember.ToMemberReference(),
 
173
                                        ToTypeReference(base.Substitution.ClassTypeArguments),
 
174
                                        ToTypeReference(base.Substitution.MethodTypeArguments));
 
175
                        } else {
 
176
                                return base.ToMemberReference();
 
177
                        }
 
178
                }
 
179
                
 
180
                public override bool Equals(object obj)
 
181
                {
 
182
                        SpecializedMethod other = obj as SpecializedMethod;
 
183
                        if (other == null)
 
184
                                return false;
 
185
                        return this.baseMember.Equals(other.baseMember) && this.substitutionWithoutSpecializedTypeParameters.Equals(other.substitutionWithoutSpecializedTypeParameters);
 
186
                }
 
187
                
 
188
                public override int GetHashCode()
 
189
                {
 
190
                        unchecked {
 
191
                                return 1000000013 * baseMember.GetHashCode() + 1000000009 * substitutionWithoutSpecializedTypeParameters.GetHashCode();
 
192
                        }
 
193
                }
 
194
 
 
195
                public override IMember Specialize(TypeParameterSubstitution newSubstitution)
 
196
                {
 
197
                        return methodDefinition.Specialize(TypeParameterSubstitution.Compose(newSubstitution, substitutionWithoutSpecializedTypeParameters));
 
198
                }
 
199
                
 
200
                IMethod IMethod.Specialize(TypeParameterSubstitution newSubstitution)
 
201
                {
 
202
                        return methodDefinition.Specialize(TypeParameterSubstitution.Compose(newSubstitution, substitutionWithoutSpecializedTypeParameters));
 
203
                }
 
204
                
 
205
                public override string ToString()
 
206
                {
 
207
                        StringBuilder b = new StringBuilder("[");
 
208
                        b.Append(GetType().Name);
 
209
                        b.Append(' ');
 
210
                        b.Append(this.DeclaringType.ReflectionName);
 
211
                        b.Append('.');
 
212
                        b.Append(this.Name);
 
213
                        if (this.TypeArguments.Count > 0) {
 
214
                                b.Append('[');
 
215
                                for (int i = 0; i < this.TypeArguments.Count; i++) {
 
216
                                        if (i > 0) b.Append(", ");
 
217
                                        b.Append(this.TypeArguments[i].ReflectionName);
 
218
                                }
 
219
                                b.Append(']');
 
220
                        } else if (this.TypeParameters.Count > 0) {
 
221
                                b.Append("``");
 
222
                                b.Append(this.TypeParameters.Count);
 
223
                        }
 
224
                        b.Append('(');
 
225
                        for (int i = 0; i < this.Parameters.Count; i++) {
 
226
                                if (i > 0) b.Append(", ");
 
227
                                b.Append(this.Parameters[i].ToString());
 
228
                        }
 
229
                        b.Append("):");
 
230
                        b.Append(this.ReturnType.ReflectionName);
 
231
                        b.Append(']');
 
232
                        return b.ToString();
 
233
                }
 
234
                
 
235
                sealed class SpecializedTypeParameter : AbstractTypeParameter
 
236
                {
 
237
                        readonly ITypeParameter baseTp;
 
238
                        
 
239
                        // The substition is set at the end of SpecializedMethod constructor
 
240
                        internal TypeVisitor substitution;
 
241
                        
 
242
                        public SpecializedTypeParameter(ITypeParameter baseTp, IMethod specializedOwner)
 
243
                                : base(specializedOwner, baseTp.Index, baseTp.Name, baseTp.Variance, baseTp.Attributes, baseTp.Region)
 
244
                        {
 
245
                                // We don't have to consider already-specialized baseTps because
 
246
                                // we read the baseTp directly from the unpacked memberDefinition.
 
247
                                this.baseTp = baseTp;
 
248
                        }
 
249
                        
 
250
                        public override int GetHashCode()
 
251
                        {
 
252
                                return baseTp.GetHashCode() ^ this.Owner.GetHashCode();
 
253
                        }
 
254
                        
 
255
                        public override bool Equals(IType other)
 
256
                        {
 
257
                                // Compare the owner, not the substitution, because the substitution may contain this specialized type parameter recursively
 
258
                                SpecializedTypeParameter o = other as SpecializedTypeParameter;
 
259
                                return o != null && baseTp.Equals(o.baseTp) && this.Owner.Equals(o.Owner);
 
260
                        }
 
261
                        
 
262
                        public override bool HasValueTypeConstraint {
 
263
                                get { return baseTp.HasValueTypeConstraint; }
 
264
                        }
 
265
                        
 
266
                        public override bool HasReferenceTypeConstraint {
 
267
                                get { return baseTp.HasReferenceTypeConstraint; }
 
268
                        }
 
269
                        
 
270
                        public override bool HasDefaultConstructorConstraint {
 
271
                                get { return baseTp.HasDefaultConstructorConstraint; }
 
272
                        }
 
273
                        
 
274
                        public override IEnumerable<IType> DirectBaseTypes {
 
275
                                get {
 
276
                                        return baseTp.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution));
 
277
                                }
 
278
                        }
 
279
                }
 
280
        }
 
281
}