Browse Source

Add MemberLookup.GetAccessibleMembers().

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
6b977c69a7
  1. 82
      ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs

82
ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs

@ -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
{

Loading…
Cancel
Save