// Copyright © Microsoft Corporation. // This source file is subject to the Microsoft Permissive License. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx. // All other rights reserved. using System; using System.Collections; using System.Collections.Generic; using System.Compiler; using Microsoft.Ddue.Tools.Reflection; namespace Microsoft.Ddue.Tools { public class MemberDictionary : ICollection < Member > { private Dictionary < string, List < Member > > index = new Dictionary < string, List < Member > >(); private TypeNode type; // construct the dictionary public MemberDictionary(TypeNode type, ApiFilter filter) { this.type = type; bool isSealed = type.IsSealed; // add all member of the type that the filter allows MemberList members = type.Members; for (int i = 0; i < members.Count; i++) { Member member = members[i]; // don't add nested types if (member is TypeNode) continue; // if our type is sealed, don't add protected members (is this check even necessary?) // if (isSealed && (member.IsFamily || member.IsFamilyAndAssembly)) continue; // don't add members that the filter rejects if (!filter.IsExposedMember(member)) continue; // okay, add the member AddMember(member); } // for enumerations, don't list inherited members if (type is EnumNode) return; // for interfaces, list members of inherited interfaces if (type is Interface) { InterfaceList contracts = type.Interfaces; for (int i = 0; i < contracts.Count; i++) { Interface contract = contracts[i]; // members of hidden interfaces don't count if (!filter.IsExposedType(contract)) continue; // otherwise, add inherited interface members MemberList contractMembers = contract.Members; for (int j = 0; j < contractMembers.Count; j++) { Member contractMember = contractMembers[j]; // check for exposure; this is necessary to remove accessor methods if (!filter.IsExposedMember(contractMember)) continue; AddMember(contractMember); } } return; } // don't list inherited memers for static classes if (type.IsAbstract && type.IsSealed) return; // now interate up through the type hierarchy for (TypeNode parentType = type.BaseType; parentType != null; parentType = parentType.BaseType) { // iterate through the members of each type MemberList parentMembers = parentType.Members; for (int i = 0; i < parentMembers.Count; i++) { Member parentMember = parentMembers[i]; // don't add constructors if ((parentMember.NodeType == NodeType.InstanceInitializer) || (parentMember.NodeType == NodeType.StaticInitializer)) continue; // don't add inherited static members if (parentMember.IsStatic) continue; // don't add nested types if (parentMember is TypeNode) continue; // if our type is sealed, don't add protected members // if (isSealed && (parentMember.IsFamily || parentMember.IsFamilyAndAssembly)) continue; // don't add members that the filter rejects if (!filter.IsExposedMember(parentMember)) continue; // don't add members we have overridden if (this.Contains(parentMember)) continue; // otherwise, add the member AddMember(parentMember); } } } public List < Member > AllMembers { get { List < Member > list = new List < Member >(); foreach (List < Member > entries in index.Values) { list.AddRange(entries); } return (list); } } public int Count { get { int count = 0; foreach (List < Member > entries in index.Values) { count += entries.Count; } return (count); } } public IList < string > MemberNames { get { return (new List < string >(index.Keys)); } } // access the data public TypeNode Type { get { return (type); } } bool ICollection < Member >.IsReadOnly { get { return (true); } } public List < Member > this[string name] { get { List < Member > members; index.TryGetValue(name, out members); return (members); } } public void Clear() { throw new InvalidOperationException(); } public bool Contains(Member member) { // get candidate members with the same name List < Member > candidates; bool found = index.TryGetValue(member.Name.Name, out candidates); // if no candidates were found, we don't have the member if (!found) return (false); // iterate over the candidates, looking for one of the same type with the same parameters ParameterList parameters = GetParameters(member); foreach (Member candidate in candidates) { // candidates must be of the same type if (candidate.NodeType != member.NodeType) continue; // get candidate parameters ParameterList candidateParameters = GetParameters(candidate); // number of parameters must match if (parameters.Count != candidateParameters.Count) continue; // each parameter type must match bool parameterMismatch = false; for (int i = 0; i < parameters.Count; i++) { if (parameters[i].Type != candidateParameters[i].Type) parameterMismatch = true; } // if the parameters match, we have the member if (!parameterMismatch) return (true); } // no candidates matched return (false); } // methods to complete ICollection public void CopyTo(Member[] array, int index) { throw new NotImplementedException(); } void ICollection < Member >.Add(Member member) { throw new InvalidOperationException(); } IEnumerator < Member > IEnumerable < Member >.GetEnumerator() { return (GetEnumerator()); } IEnumerator IEnumerable.GetEnumerator() { return (GetEnumerator()); } public bool Remove(Member member) { throw new InvalidOperationException(); } private static ParameterList GetParameters(Member member) { // if the member is a method, get it's parameter list Method method = member as Method; if (method != null) { return (method.Parameters); } // if the member is a property, get it's parameter list Property property = member as Property; if (property != null) { return (property.Parameters); } // member is neither a method nor a property return (new ParameterList()); //return(null); } private void AddMember(Member member) { // get the member name string name = member.Name.Name; // look up the member list for that name List < Member > members; if (!index.TryGetValue(name, out members)) { // if there isn't one already, make one members = new List < Member >(); index.Add(name, members); } // add the member to the list members.Add(member); } // enumerator stuff private IEnumerator < Member > GetEnumerator() { return (AllMembers.GetEnumerator()); } } }