// Copyright (c) Microsoft Corporation. All rights reserved. // using System; using System.Xml.XPath; using System.Compiler; namespace Microsoft.Ddue.Tools.Reflection { // exposes all apis for which documentation is written // this includes all visible members except for property and event accessors (e.g. get_ methods) and delegate members (e.g. Invoke). // enumeration members are included public class ExternalDocumentedFilter : ApiFilter { bool protectedSealedVisible = false; bool noPIA = false; public ExternalDocumentedFilter() : base() { } public ExternalDocumentedFilter(XPathNavigator configuration) : base(configuration) { protectedSealedVisible = (bool)configuration.Evaluate("boolean(protectedSealed[@expose='true'])"); noPIA = (bool)configuration.Evaluate("not(boolean(noPIA[@expose='false']))"); } public override bool IsExposedMember(Member member) { if (member == null) throw new ArgumentNullException("member"); TypeNode type = member.DeclaringType; // if the member isn't visible, we certainly won't expose it... if (!member.IsVisibleOutsideAssembly && !(protectedSealedVisible && type.IsSealed && (member.IsFamily || member.IsFamilyOrAssembly))) return (false); // ...but there are also some visible members we won't expose. // member of delegates are not exposed if (type.NodeType == NodeType.DelegateNode) return (false); // accessor methods for properties and events are not exposed if (member.IsSpecialName && (member.NodeType == NodeType.Method)) { string name = member.Name.Name; if (NameContains(name, "get_")) return (false); if (NameContains(name, "set_")) return (false); if (NameContains(name, "add_")) return (false); if (NameContains(name, "remove_")) return (false); if (NameContains(name, "raise_")) return (false); } // the value field of enumerations is not exposed if (member.IsSpecialName && (type.NodeType == NodeType.EnumNode) && (member.NodeType == NodeType.Field)) { string name = member.Name.Name; if (name == "value__") return (false); } // protected members of sealed types are not exposed // change of plan -- yes they are // if (type.IsSealed && (member.IsFamily || member.IsFamilyOrAssembly)) return(false); // One more test to deal with a wierd case: a private method is an explicit implementation for // a property accessor, but is not marked with the special name flag. To find these, test for // the accessibility of the methods they implement if (member.IsPrivate && member.NodeType == NodeType.Method) { Method method = (Method)member; MethodList implements = method.ImplementedInterfaceMethods; if ((implements.Count > 0) && (!IsExposedMember(implements[0]))) return (false); } // okay, passed all tests, the member is exposed as long as the filters allow it return (base.IsExposedMember(member)); } // we are satistied with the default namespace expose test, so don't override it public override bool IsExposedType(TypeNode type) { if (type == null) throw new ArgumentNullException("type"); if (!type.IsVisibleOutsideAssembly) return false; // filter out no-PIA COM types if (!noPIA) { if (IsEmbeddedInteropType(type)) return false; } // expose any visible types allowed by the base filter return (base.IsExposedType(type)); } // ApiFilter was extended to support interfaces that are filtered // out (embedded interop types) but still contribute to // the list of a type's implemented interfaces. See change // to MrefWriter.cs, method GetExposedInterfaces. public override bool IsDocumentedInterface(TypeNode type) { if (!noPIA && !IsEmbeddedInteropType(type)) return true; return base.IsDocumentedInterface(type); } private bool IsEmbeddedInteropType(TypeNode type) { bool compilerGeneratedAttribute = false; bool typeIdentifierAttribute = false; for (int i = 0; i < type.Attributes.Count; i++) { if (type.Attributes[i].Type.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute") compilerGeneratedAttribute = true; if (type.Attributes[i].Type.FullName == "System.Runtime.InteropServices.TypeIdentifierAttribute") typeIdentifierAttribute = true; } if (compilerGeneratedAttribute && typeIdentifierAttribute) return true; else return false; } private static bool NameContains(string name, string substring) { return (name.Contains(substring)); } } }