diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 05a7b75d92..edcf640158 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -230,6 +230,7 @@ + diff --git a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs index e2608b812f..4523a72023 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -26,35 +26,23 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public static IEnumerable GetAllBaseTypes(this IType type, ITypeResolveContext context) { - List output = new List(); - Stack activeTypeDefinitions = new Stack(); - CollectAllBaseTypes(type, context, activeTypeDefinitions, output); - return output; + BaseTypeCollector collector = new BaseTypeCollector(context); + collector.CollectBaseTypes(type); + return collector; } - static void CollectAllBaseTypes(IType type, ITypeResolveContext context, Stack activeTypeDefinitions, List output) + /// + /// Gets the non-interface base types. + /// + /// + /// When is an interface, this method will also return base interfaces. + /// + public static IEnumerable GetNonInterfaceBaseTypes(this IType type, ITypeResolveContext context) { - ITypeDefinition def = type.GetDefinition(); - if (def != null) { - // Maintain a stack of currently active type definitions, and avoid having one definition - // multiple times on that stack. - // This is necessary to ensure the output is finite in the presence of cyclic inheritance: - // class C : C> {} would not be caught by the 'no duplicate output' check, yet would - // produce infinite output. - if (activeTypeDefinitions.Contains(def)) - return; - activeTypeDefinitions.Push(def); - } - // Avoid outputting a type more than once - necessary for "diamond" multiple inheritance - // (e.g. C implements I1 and I2, and both interfaces derive from Object) - if (!output.Contains(type)) { - output.Add(type); - foreach (IType baseType in type.GetBaseTypes(context)) { - CollectAllBaseTypes(baseType, context, activeTypeDefinitions, output); - } - } - if (def != null) - activeTypeDefinitions.Pop(); + BaseTypeCollector collector = new BaseTypeCollector(context); + collector.SkipImplementedInterfaces = true; + collector.CollectBaseTypes(type); + return collector; } #endregion diff --git a/ICSharpCode.NRefactory/TypeSystem/IType.cs b/ICSharpCode.NRefactory/TypeSystem/IType.cs index 6e64bf1204..8c36a912da 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IType.cs @@ -61,44 +61,96 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the direct base types. /// + /// The context used for resolving type references + /// Returns the direct base types including interfaces IEnumerable GetBaseTypes(ITypeResolveContext context); /// /// Gets inner classes (including inherited inner classes). /// + /// The context used for resolving type references + /// The filter used to select which types to return. + /// The filter is tested on the unparameterized types. + /// + /// If this type is parameterized, the nested type will also be parameterized. + /// Any additional type parameters on the nested type will be parameterized with the + /// corresponding ITypeParameter. + /// IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null); /// - /// Gets all methods that can be called on this return type. + /// Gets all instance constructors for this type. /// - /// The list does not include constructors. - IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null); + /// The context used for resolving type references + /// The filter used to select which constructors to return. + /// The filter is tested on the original method definitions (before specialization). + /// + /// This list does not include constructors in base classes or static constructors. + /// For methods on parameterized types, type substitution will be performed on the method signature, + /// and the appriopriate will be returned. + /// + IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null); /// - /// Gets all instance constructors for this type. + /// Gets all methods that can be called on this type. /// - /// This list does not include constructors in base classes or static constructors. - IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null); + /// The context used for resolving type references + /// The filter used to select which methods to return. + /// The filter is tested on the original method definitions (before specialization). + /// + /// The list does not include constructors. + /// For methods on parameterized types, type substitution will be performed on the method signature, + /// and the appriopriate will be returned. + /// + IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null); /// - /// Gets all properties that can be called on this return type. + /// Gets all properties that can be called on this type. /// + /// The context used for resolving type references + /// The filter used to select which properties to return. + /// The filter is tested on the original property definitions (before specialization). + /// + /// For properties on parameterized types, type substitution will be performed on the property signature, + /// and the appriopriate will be returned. + /// IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null); /// - /// Gets all fields that can be called on this return type. + /// Gets all fields that can be accessed on this type. /// + /// The context used for resolving type references + /// The filter used to select which constructors to return. + /// The filter is tested on the original field definitions (before specialization). + /// + /// For fields on parameterized types, type substitution will be performed on the field's return type, + /// and the appriopriate will be returned. + /// IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null); /// - /// Gets all events that can be called on this return type. + /// Gets all events that can be accessed on this type. /// + /// The context used for resolving type references + /// The filter used to select which events to return. + /// The filter is tested on the original event definitions (before specialization). + /// + /// For fields on parameterized types, type substitution will be performed on the event's return type, + /// and the appriopriate will be returned. + /// IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null); /// - /// Gets all members that can be called on this return type. - /// This is the union of GetFields(),GetProperties(),GetMethods() and GetEvents(). This does not include constructors. + /// Gets all members that can be called on this type. /// + /// The context used for resolving type references + /// The filter used to select which members to return. + /// The filter is tested on the original member definitions (before specialization). + /// + /// The resulting list is the union of GetFields(), GetProperties(), GetMethods() and GetEvents(). + /// It does not include constructors. + /// For parameterized types, type substitution will be performed. + /// IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null); } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs new file mode 100644 index 0000000000..fde4af5842 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Helper class for the GetAllBaseTypes() implementation. + /// + sealed class BaseTypeCollector : List + { + readonly ITypeResolveContext context; + readonly Stack activeTypeDefinitions = new Stack(); + + /// + /// If this option is enabled, the list will not contain interfaces when retrieving the base types + /// of a class. + /// + internal bool SkipImplementedInterfaces; + + public BaseTypeCollector(ITypeResolveContext context) + { + this.context = context; + } + + public void CollectBaseTypes(IType type) + { + ITypeDefinition def = type.GetDefinition(); + if (def != null) { + // Maintain a stack of currently active type definitions, and avoid having one definition + // multiple times on that stack. + // This is necessary to ensure the output is finite in the presence of cyclic inheritance: + // class C : C> {} would not be caught by the 'no duplicate output' check, yet would + // produce infinite output. + if (activeTypeDefinitions.Contains(def)) + return; + activeTypeDefinitions.Push(def); + } + // Avoid outputting a type more than once - necessary for "diamond" multiple inheritance + // (e.g. C implements I1 and I2, and both interfaces derive from Object) + if (!this.Contains(type)) { + this.Add(type); + foreach (IType baseType in type.GetBaseTypes(context)) { + if (SkipImplementedInterfaces && def != null && def.ClassType != ClassType.Interface) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && baseTypeDef.ClassType == ClassType.Interface) { + // skip the interface + continue; + } + } + CollectBaseTypes(baseType); + } + } + if (def != null) + activeTypeDefinitions.Pop(); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs index f9ee9a45ea..b331ea1074 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; @@ -434,27 +433,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetMethods(context, filter); - - List methods = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - methods.AddRange(baseType.GetMethods(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(methods); - AddFilteredRange(methods, this.Methods.Where(m => !m.IsConstructor), filter); - } - } - return methods; + return ParameterizedType.GetMethods(this, context, filter); } public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) @@ -464,7 +443,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return compound.GetConstructors(context, filter); List methods = new List(); - AddFilteredRange(methods, this.Methods.Where(m => m.IsConstructor && !m.IsStatic), filter); + foreach (IMethod m in this.Methods) { + if (m.IsConstructor && !m.IsStatic) { + if (filter == null || filter(m)) + methods.Add(m); + } + } if (this.AddDefaultConstructorIfRequired) { if (this.ClassType == ClassType.Class && methods.Count == 0 @@ -480,129 +464,22 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetProperties(context, filter); - - List properties = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - properties.AddRange(baseType.GetProperties(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(properties); - AddFilteredRange(properties, this.Properties, filter); - } - } - return properties; + return ParameterizedType.GetProperties(this, context, filter); } public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetFields(context, filter); - - List fields = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - fields.AddRange(baseType.GetFields(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(fields); - AddFilteredRange(fields, this.Fields, filter); - } - } - return fields; + return ParameterizedType.GetFields(this, context, filter); } public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetEvents(context, filter); - - List events = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - events.AddRange(baseType.GetEvents(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(events); - AddFilteredRange(events, this.Events, filter); - } - } - return events; + return ParameterizedType.GetEvents(this, context, filter); } public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetMembers(context, filter); - - List members = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - members.AddRange(baseType.GetMembers(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(members); - AddFilteredRange(members, this.Methods.Where(m => !m.IsConstructor), filter); - AddFilteredRange(members, this.Properties, filter); - AddFilteredRange(members, this.Fields, filter); - AddFilteredRange(members, this.Events, filter); - } - } - return members; - } - - static void AddFilteredRange(List targetList, IEnumerable sourceList, Predicate filter) where T : class - { - if (filter == null) { - targetList.AddRange(sourceList); - } else { - foreach (T element in sourceList) { - if (filter(element)) - targetList.Add(element); - } - } - } - - /// - /// Removes duplicate members from the list. - /// This is necessary when the same member can be inherited twice due to multiple inheritance. - /// - static void RemoveDuplicates(List list) where T : class - { - if (list.Count > 1) { - HashSet hash = new HashSet(); - list.RemoveAll(m => !hash.Add(m)); - } + return ParameterizedType.GetMembers(this, context, filter); } // we use reference equality diff --git a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs index 688dc38932..560676dccf 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs @@ -7,6 +7,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem @@ -103,33 +104,37 @@ namespace ICSharpCode.NRefactory.TypeSystem return types; } - public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter) - { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetEvents(context, filter)); - } - public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter) { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetMethods(context, filter)); + return ParameterizedType.GetMethods(this, context, FilterNonStatic(filter)); } public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter) { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetProperties(context, filter)); + return ParameterizedType.GetProperties(this, context, FilterNonStatic(filter)); } public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter) { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetFields(context, filter)); + return ParameterizedType.GetFields(this, context, FilterNonStatic(filter)); + } + + public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter) + { + return ParameterizedType.GetEvents(this, context, FilterNonStatic(filter)); + } + + public override IEnumerable GetMembers(ITypeResolveContext context, Predicate filter) + { + return ParameterizedType.GetMembers(this, context, FilterNonStatic(filter)); } static Predicate FilterNonStatic(Predicate filter) where T : class, IMember { - return member => !member.IsStatic && (filter == null || filter(member)); + if (filter == null) + return member => !member.IsStatic; + else + return member => !member.IsStatic && filter(member); } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs index a75fb7c217..58ad685957 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -206,11 +206,11 @@ namespace ICSharpCode.NRefactory.TypeSystem return types; } - public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) { Substitution substitution = new Substitution(typeArguments); Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List methods = genericType.GetMethods(context, filter).ToList(); + List methods = genericType.GetConstructors(context, filter).ToList(); for (int i = 0; i < methods.Count; i++) { SpecializedMethod m = new SpecializedMethod(methods[i]); m.SetDeclaringType(this); @@ -220,102 +220,191 @@ namespace ICSharpCode.NRefactory.TypeSystem return methods; } - public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) { - Substitution substitution = new Substitution(typeArguments); - Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List methods = genericType.GetConstructors(context, filter).ToList(); - for (int i = 0; i < methods.Count; i++) { - SpecializedMethod m = new SpecializedMethod(methods[i]); - m.SetDeclaringType(this); - m.SubstituteTypes(substitutionFunc); - methods[i] = m; + return GetMethods(this, context, filter); + } + + internal static IEnumerable GetMethods(IType type, ITypeResolveContext context, Predicate filter) + { + Predicate newFilter; + if (filter == null) + newFilter = m => !m.IsConstructor; + else + newFilter = m => !m.IsConstructor && filter(m); + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMethodsInternal(t, context, newFilter)); + } + + static IEnumerable GetMethodsInternal(IType baseType, ITypeResolveContext context, Predicate filter) + { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef == null) + yield break; + baseTypeDef = baseTypeDef.GetCompoundClass(); + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + Substitution substitution = null; + Func substitutionFunc = null; + foreach (IMethod m in baseTypeDef.Methods) { + if (!(filter == null || filter(m))) + continue; + if (substitution == null) { + substitution = new Substitution(pt.typeArguments); + substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + } + SpecializedMethod sm = new SpecializedMethod(m); + sm.SetDeclaringType(pt); + sm.SubstituteTypes(substitutionFunc); + yield return sm; + } + } else { + foreach (IMethod m in baseTypeDef.Methods) { + if (filter == null || filter(m)) + yield return m; + } } - return methods; } public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) { - Substitution substitution = new Substitution(typeArguments); - Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List properties = genericType.GetProperties(context, filter).ToList(); - for (int i = 0; i < properties.Count; i++) { - SpecializedProperty p = new SpecializedProperty(properties[i]); - p.SetDeclaringType(this); - p.SubstituteTypes(substitutionFunc); - properties[i] = p; + return GetProperties(this, context, filter); + } + + internal static IEnumerable GetProperties(IType type, ITypeResolveContext context, Predicate filter) + { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetPropertiesInternal(t, context, filter)); + } + + static IEnumerable GetPropertiesInternal(IType baseType, ITypeResolveContext context, Predicate filter) + { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef == null) + yield break; + baseTypeDef = baseTypeDef.GetCompoundClass(); + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + Substitution substitution = null; + Func substitutionFunc = null; + foreach (IProperty p in baseTypeDef.Properties) { + if (!(filter == null || filter(p))) + continue; + if (substitution == null) { + substitution = new Substitution(pt.typeArguments); + substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + } + SpecializedProperty sp = new SpecializedProperty(p); + sp.SetDeclaringType(pt); + sp.SubstituteTypes(substitutionFunc); + yield return sp; + } + } else { + foreach (IProperty p in baseTypeDef.Properties) { + if (filter == null || filter(p)) + yield return p; + } } - return properties; } public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) { - Substitution substitution = new Substitution(typeArguments); - List fields = genericType.GetFields(context, filter).ToList(); - for (int i = 0; i < fields.Count; i++) { - SpecializedField f = new SpecializedField(fields[i]); - f.SetDeclaringType(this); - f.ReturnType = f.ReturnType.Resolve(context).AcceptVisitor(substitution); - fields[i] = f; + return GetFields(this, context, filter); + } + + internal static IEnumerable GetFields(IType type, ITypeResolveContext context, Predicate filter) + { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetFieldsInternal(t, context, filter)); + } + + static IEnumerable GetFieldsInternal(IType baseType, ITypeResolveContext context, Predicate filter) + { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef == null) + yield break; + baseTypeDef = baseTypeDef.GetCompoundClass(); + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + Substitution substitution = null; + Func substitutionFunc = null; + foreach (IField f in baseTypeDef.Fields) { + if (!(filter == null || filter(f))) + continue; + if (substitution == null) { + substitution = new Substitution(pt.typeArguments); + substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + } + SpecializedField sf = new SpecializedField(f); + sf.SetDeclaringType(pt); + sf.ReturnType = f.ReturnType.Resolve(context).AcceptVisitor(substitution); + yield return sf; + } + } else { + foreach (IField f in baseTypeDef.Fields) { + if (filter == null || filter(f)) + yield return f; + } } - return fields; } public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) { - Substitution substitution = new Substitution(typeArguments); - List events = genericType.GetEvents(context, filter).ToList(); - for (int i = 0; i < events.Count; i++) { - SpecializedEvent e = new SpecializedEvent(events[i]); - e.SetDeclaringType(this); - e.ReturnType = e.ReturnType.Resolve(context).AcceptVisitor(substitution); - events[i] = e; + return GetEvents(this, context, filter); + } + + internal static IEnumerable GetEvents(IType type, ITypeResolveContext context, Predicate filter) + { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetEventsInternal(t, context, filter)); + } + + static IEnumerable GetEventsInternal(IType baseType, ITypeResolveContext context, Predicate filter) + { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef == null) + yield break; + baseTypeDef = baseTypeDef.GetCompoundClass(); + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + Substitution substitution = null; + Func substitutionFunc = null; + foreach (IEvent e in baseTypeDef.Events) { + if (!(filter == null || filter(e))) + continue; + if (substitution == null) { + substitution = new Substitution(pt.typeArguments); + substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + } + SpecializedEvent se = new SpecializedEvent(e); + se.SetDeclaringType(pt); + se.ReturnType = e.ReturnType.Resolve(context).AcceptVisitor(substitution); + yield return se; + } + } else { + foreach (IEvent e in baseTypeDef.Events) { + if (filter == null || filter(e)) + yield return e; + } } - return events; } public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) { - Substitution substitution = new Substitution(typeArguments); - Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List members = genericType.GetMembers(context, filter).ToList(); - for (int i = 0; i < members.Count; i++) { - members[i] = Specialize(members[i], substitutionFunc); - } - return members; + return GetMembers(this, context, filter); } - IMember Specialize(IMember member, Func substitution) + internal static IEnumerable GetMembers(IType type, ITypeResolveContext context, Predicate filter) { - IMethod method = member as IMethod; - if (method != null) { - SpecializedMethod m = new SpecializedMethod(method); - m.SetDeclaringType(this); - m.SubstituteTypes(substitution); - return m; - } - IProperty property = member as IProperty; - if (property != null) { - SpecializedProperty p = new SpecializedProperty(property); - p.SetDeclaringType(this); - p.SubstituteTypes(substitution); - return p; - } - IField field = member as IField; - if (field != null) { - SpecializedField f = new SpecializedField(field); - f.SetDeclaringType(this); - f.ReturnType = substitution(f.ReturnType); - return f; - } - IEvent ev = member as IEvent; - if (ev != null) { - SpecializedEvent e = new SpecializedEvent(ev); - e.SetDeclaringType(this); - e.ReturnType = substitution(e.ReturnType); - return e; - } - throw new ArgumentException("Unknown member"); + Predicate methodFilter; + if (filter == null) + methodFilter = m => !m.IsConstructor; + else + methodFilter = m => !m.IsConstructor && filter(m); + return type.GetNonInterfaceBaseTypes(context).SelectMany( + delegate (IType t) { + IEnumerable members = GetMethodsInternal(t, context, methodFilter); + members = members.Concat(GetPropertiesInternal(t, context, filter)); + members = members.Concat(GetFieldsInternal(t, context, filter)); + members = members.Concat(GetEventsInternal(t, context, filter)); + return members; + }); } public override bool Equals(object obj)