Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.13/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/TypeSystem/Implementation/SpecializedMethod.cs @ 18242

Last change on this file since 18242 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 9.9 KB
Line 
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
19using System;
20using System.Collections.Generic;
21using System.Diagnostics;
22using System.Linq;
23using System.Text;
24using System.Threading;
25using ICSharpCode.NRefactory.Utils;
26
27namespace 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 ToReference()
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.ToReference(),
173          ToTypeReference(base.Substitution.ClassTypeArguments),
174          ToTypeReference(base.Substitution.MethodTypeArguments));
175      } else {
176        return base.ToReference();
177      }
178    }
179   
180    public override IMemberReference ToMemberReference()
181    {
182      return ToReference();
183    }
184   
185    public override bool Equals(object obj)
186    {
187      SpecializedMethod other = obj as SpecializedMethod;
188      if (other == null)
189        return false;
190      return this.baseMember.Equals(other.baseMember) && this.substitutionWithoutSpecializedTypeParameters.Equals(other.substitutionWithoutSpecializedTypeParameters);
191    }
192   
193    public override int GetHashCode()
194    {
195      unchecked {
196        return 1000000013 * baseMember.GetHashCode() + 1000000009 * substitutionWithoutSpecializedTypeParameters.GetHashCode();
197      }
198    }
199
200    public override IMember Specialize(TypeParameterSubstitution newSubstitution)
201    {
202      return methodDefinition.Specialize(TypeParameterSubstitution.Compose(newSubstitution, substitutionWithoutSpecializedTypeParameters));
203    }
204   
205    IMethod IMethod.Specialize(TypeParameterSubstitution newSubstitution)
206    {
207      return methodDefinition.Specialize(TypeParameterSubstitution.Compose(newSubstitution, substitutionWithoutSpecializedTypeParameters));
208    }
209   
210    public override string ToString()
211    {
212      StringBuilder b = new StringBuilder("[");
213      b.Append(GetType().Name);
214      b.Append(' ');
215      b.Append(this.DeclaringType.ReflectionName);
216      b.Append('.');
217      b.Append(this.Name);
218      if (this.TypeArguments.Count > 0) {
219        b.Append('[');
220        for (int i = 0; i < this.TypeArguments.Count; i++) {
221          if (i > 0) b.Append(", ");
222          b.Append(this.TypeArguments[i].ReflectionName);
223        }
224        b.Append(']');
225      } else if (this.TypeParameters.Count > 0) {
226        b.Append("``");
227        b.Append(this.TypeParameters.Count);
228      }
229      b.Append('(');
230      for (int i = 0; i < this.Parameters.Count; i++) {
231        if (i > 0) b.Append(", ");
232        b.Append(this.Parameters[i].ToString());
233      }
234      b.Append("):");
235      b.Append(this.ReturnType.ReflectionName);
236      b.Append(']');
237      return b.ToString();
238    }
239   
240    sealed class SpecializedTypeParameter : AbstractTypeParameter
241    {
242      readonly ITypeParameter baseTp;
243     
244      // The substition is set at the end of SpecializedMethod constructor
245      internal TypeVisitor substitution;
246     
247      public SpecializedTypeParameter(ITypeParameter baseTp, IMethod specializedOwner)
248        : base(specializedOwner, baseTp.Index, baseTp.Name, baseTp.Variance, baseTp.Attributes, baseTp.Region)
249      {
250        // We don't have to consider already-specialized baseTps because
251        // we read the baseTp directly from the unpacked memberDefinition.
252        this.baseTp = baseTp;
253      }
254     
255      public override int GetHashCode()
256      {
257        return baseTp.GetHashCode() ^ this.Owner.GetHashCode();
258      }
259     
260      public override bool Equals(IType other)
261      {
262        // Compare the owner, not the substitution, because the substitution may contain this specialized type parameter recursively
263        SpecializedTypeParameter o = other as SpecializedTypeParameter;
264        return o != null && baseTp.Equals(o.baseTp) && this.Owner.Equals(o.Owner);
265      }
266     
267      public override bool HasValueTypeConstraint {
268        get { return baseTp.HasValueTypeConstraint; }
269      }
270     
271      public override bool HasReferenceTypeConstraint {
272        get { return baseTp.HasReferenceTypeConstraint; }
273      }
274     
275      public override bool HasDefaultConstructorConstraint {
276        get { return baseTp.HasDefaultConstructorConstraint; }
277      }
278     
279      public override IEnumerable<IType> DirectBaseTypes {
280        get {
281          return baseTp.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution));
282        }
283      }
284    }
285  }
286}
Note: See TracBrowser for help on using the repository browser.