|
|
|
@ -17,7 +17,6 @@
@@ -17,7 +17,6 @@
|
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Collections; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.Linq; |
|
|
|
@ -141,6 +140,87 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -141,6 +140,87 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region GetAccessibleMembers
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Retrieves all members that are accessible and not hidden (by being overridden or shadowed).
|
|
|
|
|
/// Returns both members and nested type definitions. Does not include extension methods.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public IEnumerable<IEntity> GetAccessibleMembers(ResolveResult targetResolveResult) |
|
|
|
|
{ |
|
|
|
|
if (targetResolveResult == null) |
|
|
|
|
throw new ArgumentNullException("targetResolveResult"); |
|
|
|
|
|
|
|
|
|
bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; |
|
|
|
|
bool allowProtectedAccess = (targetResolveResult is ThisResolveResult || IsProtectedAccessAllowed(targetResolveResult.Type)); |
|
|
|
|
|
|
|
|
|
// maps the member name to the list of lookup groups
|
|
|
|
|
var lookupGroupDict = new Dictionary<string, List<LookupGroup>>(); |
|
|
|
|
|
|
|
|
|
// This loop will handle base types before derived types.
|
|
|
|
|
// The loop performs three jobs:
|
|
|
|
|
// 1) It marks entries in lookup groups from base classes as removed when those members
|
|
|
|
|
// are hidden by a derived class.
|
|
|
|
|
// 2) It adds a new lookup group with the members from a declaring type.
|
|
|
|
|
// 3) It replaces virtual members with the overridden version, placing the override in the
|
|
|
|
|
// lookup group belonging to the base class.
|
|
|
|
|
foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes()) { |
|
|
|
|
|
|
|
|
|
List<IEntity> entities = new List<IEntity>(); |
|
|
|
|
entities.AddRange(type.GetMembers(options: GetMemberOptions.IgnoreInheritedMembers)); |
|
|
|
|
if (!targetIsTypeParameter) |
|
|
|
|
entities.AddRange(type.GetNestedTypes(options: GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions).Select(t => t.GetDefinition())); |
|
|
|
|
|
|
|
|
|
foreach (var entityGroup in entities.GroupBy(e => e.Name)) { |
|
|
|
|
|
|
|
|
|
List<LookupGroup> lookupGroups = new List<LookupGroup>(); |
|
|
|
|
if (!lookupGroupDict.TryGetValue(entityGroup.Key, out lookupGroups)) |
|
|
|
|
lookupGroupDict.Add(entityGroup.Key, lookupGroups = new List<LookupGroup>()); |
|
|
|
|
|
|
|
|
|
List<IType> newNestedTypes = null; |
|
|
|
|
List<IParameterizedMember> newMethods = null; |
|
|
|
|
IMember newNonMethod = null; |
|
|
|
|
|
|
|
|
|
IEnumerable<IType> typeBaseTypes = null; |
|
|
|
|
|
|
|
|
|
if (!targetIsTypeParameter) { |
|
|
|
|
AddNestedTypes(type, entityGroup.OfType<IType>(), 0, lookupGroups, ref typeBaseTypes, ref newNestedTypes); |
|
|
|
|
} |
|
|
|
|
AddMembers(type, entityGroup.OfType<IMember>(), allowProtectedAccess, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod); |
|
|
|
|
|
|
|
|
|
if (newNestedTypes != null || newMethods != null || newNonMethod != null) |
|
|
|
|
lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
foreach (List<LookupGroup> lookupGroups in lookupGroupDict.Values) { |
|
|
|
|
// Remove interface members hidden by class members.
|
|
|
|
|
if (targetIsTypeParameter) { |
|
|
|
|
// This can happen only with type parameters.
|
|
|
|
|
RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Now report the results:
|
|
|
|
|
foreach (LookupGroup lookupGroup in lookupGroups) { |
|
|
|
|
if (!lookupGroup.MethodsAreHidden) { |
|
|
|
|
foreach (IMethod method in lookupGroup.Methods) { |
|
|
|
|
yield return method; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!lookupGroup.NonMethodIsHidden) { |
|
|
|
|
yield return lookupGroup.NonMethod; |
|
|
|
|
} |
|
|
|
|
if (lookupGroup.NestedTypes != null) { |
|
|
|
|
foreach (IType type in lookupGroup.NestedTypes) { |
|
|
|
|
ITypeDefinition typeDef = type.GetDefinition(); |
|
|
|
|
if (typeDef != null) |
|
|
|
|
yield return typeDef; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region class LookupGroup
|
|
|
|
|
sealed class LookupGroup |
|
|
|
|
{ |
|
|
|
|