diff options
Diffstat (limited to 'tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs')
-rw-r--r-- | tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs b/tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs new file mode 100644 index 0000000..4c40c54 --- /dev/null +++ b/tools/Sandcastle/Source/MRefBuilder/MemberDictionary.cs @@ -0,0 +1,273 @@ +// 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<Member> + + 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()); + } + + } + +} |