Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/TypeSystem/Implementation/GetMembersHelper.cs @ 11700

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

#2077: created branch and added first version

File size: 12.3 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.Linq;
22using ICSharpCode.NRefactory.Utils;
23
24namespace ICSharpCode.NRefactory.TypeSystem.Implementation
25{
26  /// <summary>
27  /// Provides helper methods for implementing GetMembers() on IType-implementations.
28  /// Note: GetMembersHelper will recursively call back into IType.GetMembers(), but only with
29  /// both GetMemberOptions.IgnoreInheritedMembers and GetMemberOptions.ReturnMemberDefinitions set,
30  /// and only the 'simple' overloads (not taking type arguments).
31  ///
32  /// Ensure that your IType implementation does not use the GetMembersHelper if both flags are set,
33  /// otherwise you'll get a StackOverflowException!
34  /// </summary>
35  static class GetMembersHelper
36  {
37    #region GetNestedTypes
38    public static IEnumerable<IType> GetNestedTypes(IType type, Predicate<ITypeDefinition> filter, GetMemberOptions options)
39    {
40      return GetNestedTypes(type, null, filter, options);
41    }
42   
43    public static IEnumerable<IType> GetNestedTypes(IType type, IList<IType> nestedTypeArguments, Predicate<ITypeDefinition> filter, GetMemberOptions options)
44    {
45      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
46        return GetNestedTypesImpl(type, nestedTypeArguments, filter, options);
47      } else {
48        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetNestedTypesImpl(t, nestedTypeArguments, filter, options));
49      }
50    }
51   
52    static IEnumerable<IType> GetNestedTypesImpl(IType outerType, IList<IType> nestedTypeArguments, Predicate<ITypeDefinition> filter, GetMemberOptions options)
53    {
54      ITypeDefinition outerTypeDef = outerType.GetDefinition();
55      if (outerTypeDef == null)
56        yield break;
57     
58      int outerTypeParameterCount = outerTypeDef.TypeParameterCount;
59      ParameterizedType pt = outerType as ParameterizedType;
60      foreach (ITypeDefinition nestedType in outerTypeDef.NestedTypes) {
61        int totalTypeParameterCount = nestedType.TypeParameterCount;
62        if (nestedTypeArguments != null) {
63          if (totalTypeParameterCount - outerTypeParameterCount != nestedTypeArguments.Count)
64            continue;
65        }
66        if (!(filter == null || filter(nestedType)))
67          continue;
68       
69        if (totalTypeParameterCount == 0 || (options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) {
70          yield return nestedType;
71        } else {
72          // We need to parameterize the nested type
73          IType[] newTypeArguments = new IType[totalTypeParameterCount];
74          for (int i = 0; i < outerTypeParameterCount; i++) {
75            newTypeArguments[i] = pt != null ? pt.GetTypeArgument(i) : outerTypeDef.TypeParameters[i];
76          }
77          for (int i = outerTypeParameterCount; i < totalTypeParameterCount; i++) {
78            if (nestedTypeArguments != null)
79              newTypeArguments[i] = nestedTypeArguments[i - outerTypeParameterCount];
80            else
81              newTypeArguments[i] = SpecialType.UnboundTypeArgument;
82          }
83          yield return new ParameterizedType(nestedType, newTypeArguments);
84        }
85      }
86    }
87    #endregion
88   
89    #region GetMethods
90    public static IEnumerable<IMethod> GetMethods(IType type, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
91    {
92      return GetMethods(type, null, filter, options);
93    }
94   
95    public static IEnumerable<IMethod> GetMethods(IType type, IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
96    {
97      if (typeArguments != null && typeArguments.Count > 0) {
98        filter = FilterTypeParameterCount(typeArguments.Count).And(filter);
99      }
100     
101      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
102        return GetMethodsImpl(type, typeArguments, filter, options);
103      } else {
104        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetMethodsImpl(t, typeArguments, filter, options));
105      }
106    }
107   
108    static Predicate<IUnresolvedMethod> FilterTypeParameterCount(int expectedTypeParameterCount)
109    {
110      return m => m.TypeParameters.Count == expectedTypeParameterCount;
111    }
112   
113    const GetMemberOptions declaredMembers = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;
114   
115    static IEnumerable<IMethod> GetMethodsImpl(IType baseType, IList<IType> methodTypeArguments, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
116    {
117      IEnumerable<IMethod> declaredMethods = baseType.GetMethods(filter, options | declaredMembers);
118     
119      ParameterizedType pt = baseType as ParameterizedType;
120      if ((options & GetMemberOptions.ReturnMemberDefinitions) == 0
121          && (pt != null || (methodTypeArguments != null && methodTypeArguments.Count > 0)))
122      {
123        TypeParameterSubstitution substitution = null;
124        foreach (IMethod m in declaredMethods) {
125          if (methodTypeArguments != null && methodTypeArguments.Count > 0) {
126            if (m.TypeParameters.Count != methodTypeArguments.Count)
127              continue;
128          }
129          if (substitution == null) {
130            if (pt != null)
131              substitution = pt.GetSubstitution(methodTypeArguments);
132            else
133              substitution = new TypeParameterSubstitution(null, methodTypeArguments);
134          }
135          yield return new SpecializedMethod(m, substitution);
136        }
137      } else {
138        foreach (IMethod m in declaredMethods) {
139          yield return m;
140        }
141      }
142    }
143    #endregion
144   
145    #region GetAccessors
146    public static IEnumerable<IMethod> GetAccessors(IType type, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
147    {
148      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
149        return GetAccessorsImpl(type, filter, options);
150      } else {
151        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetAccessorsImpl(t, filter, options));
152      }
153    }
154   
155    static IEnumerable<IMethod> GetAccessorsImpl(IType baseType, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
156    {
157      return GetConstructorsOrAccessorsImpl(baseType, baseType.GetAccessors(filter, options | declaredMembers), filter, options);
158    }
159    #endregion
160   
161    #region GetConstructors
162    public static IEnumerable<IMethod> GetConstructors(IType type, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
163    {
164      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
165        return GetConstructorsImpl(type, filter, options);
166      } else {
167        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetConstructorsImpl(t, filter, options));
168      }
169    }
170   
171    static IEnumerable<IMethod> GetConstructorsImpl(IType baseType, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
172    {
173      return GetConstructorsOrAccessorsImpl(baseType, baseType.GetConstructors(filter, options | declaredMembers), filter, options);
174    }
175   
176    static IEnumerable<IMethod> GetConstructorsOrAccessorsImpl(IType baseType, IEnumerable<IMethod> declaredMembers, Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
177    {
178      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) {
179        return declaredMembers;
180      }
181     
182      ParameterizedType pt = baseType as ParameterizedType;
183      if (pt != null) {
184        var substitution = pt.GetSubstitution();
185        return declaredMembers.Select(m => new SpecializedMethod(m, substitution) { DeclaringType = pt });
186      } else {
187        return declaredMembers;
188      }
189    }
190    #endregion
191   
192    #region GetProperties
193    public static IEnumerable<IProperty> GetProperties(IType type, Predicate<IUnresolvedProperty> filter, GetMemberOptions options)
194    {
195      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
196        return GetPropertiesImpl(type, filter, options);
197      } else {
198        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetPropertiesImpl(t, filter, options));
199      }
200    }
201   
202    static IEnumerable<IProperty> GetPropertiesImpl(IType baseType, Predicate<IUnresolvedProperty> filter, GetMemberOptions options)
203    {
204      IEnumerable<IProperty> declaredProperties = baseType.GetProperties(filter, options | declaredMembers);
205      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) {
206        return declaredProperties;
207      }
208     
209      ParameterizedType pt = baseType as ParameterizedType;
210      if (pt != null) {
211        var substitution = pt.GetSubstitution();
212        return declaredProperties.Select(m => new SpecializedProperty(m, substitution) { DeclaringType = pt });
213      } else {
214        return declaredProperties;
215      }
216    }
217    #endregion
218   
219    #region GetFields
220    public static IEnumerable<IField> GetFields(IType type, Predicate<IUnresolvedField> filter, GetMemberOptions options)
221    {
222      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
223        return GetFieldsImpl(type, filter, options);
224      } else {
225        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetFieldsImpl(t, filter, options));
226      }
227    }
228   
229    static IEnumerable<IField> GetFieldsImpl(IType baseType, Predicate<IUnresolvedField> filter, GetMemberOptions options)
230    {
231      IEnumerable<IField> declaredFields = baseType.GetFields(filter, options | declaredMembers);
232      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) {
233        return declaredFields;
234      }
235     
236      ParameterizedType pt = baseType as ParameterizedType;
237      if (pt != null) {
238        var substitution = pt.GetSubstitution();
239        return declaredFields.Select(m => new SpecializedField(m, substitution) { DeclaringType = pt });
240      } else {
241        return declaredFields;
242      }
243    }
244    #endregion
245   
246    #region GetEvents
247    public static IEnumerable<IEvent> GetEvents(IType type, Predicate<IUnresolvedEvent> filter, GetMemberOptions options)
248    {
249      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
250        return GetEventsImpl(type, filter, options);
251      } else {
252        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetEventsImpl(t, filter, options));
253      }
254    }
255   
256    static IEnumerable<IEvent> GetEventsImpl(IType baseType, Predicate<IUnresolvedEvent> filter, GetMemberOptions options)
257    {
258      IEnumerable<IEvent> declaredEvents = baseType.GetEvents(filter, options | declaredMembers);
259      if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) {
260        return declaredEvents;
261      }
262     
263      ParameterizedType pt = baseType as ParameterizedType;
264      if (pt != null) {
265        var substitution = pt.GetSubstitution();
266        return declaredEvents.Select(m => new SpecializedEvent(m, substitution) { DeclaringType = pt });
267      } else {
268        return declaredEvents;
269      }
270    }
271    #endregion
272   
273    #region GetMembers
274    public static IEnumerable<IMember> GetMembers(IType type, Predicate<IUnresolvedMember> filter, GetMemberOptions options)
275    {
276      if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
277        return GetMembersImpl(type, filter, options);
278      } else {
279        return type.GetNonInterfaceBaseTypes().SelectMany(t => GetMembersImpl(t, filter, options));
280      }
281    }
282   
283    static IEnumerable<IMember> GetMembersImpl(IType baseType, Predicate<IUnresolvedMember> filter, GetMemberOptions options)
284    {
285      foreach (var m in GetMethodsImpl(baseType, null, filter, options))
286        yield return m;
287      foreach (var m in GetPropertiesImpl(baseType, filter, options))
288        yield return m;
289      foreach (var m in GetFieldsImpl(baseType, filter, options))
290        yield return m;
291      foreach (var m in GetEventsImpl(baseType, filter, options))
292        yield return m;
293    }
294    #endregion
295  }
296}
Note: See TracBrowser for help on using the repository browser.