summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/Reflection
diff options
context:
space:
mode:
Diffstat (limited to 'tools/Sandcastle/Source/Reflection')
-rw-r--r--tools/Sandcastle/Source/Reflection/AllDocumentedFilter.cs90
-rw-r--r--tools/Sandcastle/Source/Reflection/AllTopicFilter.cs23
-rw-r--r--tools/Sandcastle/Source/Reflection/ApiFilter.cs208
-rw-r--r--tools/Sandcastle/Source/Reflection/ApiNamer.cs30
-rw-r--r--tools/Sandcastle/Source/Reflection/ApiVisitor.cs339
-rw-r--r--tools/Sandcastle/Source/Reflection/AssemblyReferenceEventArgs.cs36
-rw-r--r--tools/Sandcastle/Source/Reflection/AssemblyResolver.cs89
-rw-r--r--tools/Sandcastle/Source/Reflection/ExternalDocumentedFilter.cs82
-rw-r--r--tools/Sandcastle/Source/Reflection/ExternalFilter.cs31
-rw-r--r--tools/Sandcastle/Source/Reflection/ExternalTopicFilter.cs23
-rw-r--r--tools/Sandcastle/Source/Reflection/GlobalSuppressions.cs55
-rw-r--r--tools/Sandcastle/Source/Reflection/MemberFilter.cs50
-rw-r--r--tools/Sandcastle/Source/Reflection/NamespaceFilter.cs143
-rw-r--r--tools/Sandcastle/Source/Reflection/NoFilter.cs28
-rw-r--r--tools/Sandcastle/Source/Reflection/Notes.txt215
-rw-r--r--tools/Sandcastle/Source/Reflection/OrcasNamer.cs376
-rw-r--r--tools/Sandcastle/Source/Reflection/Properties/AssemblyInfo.cs40
-rw-r--r--tools/Sandcastle/Source/Reflection/Reflection.cs298
-rw-r--r--tools/Sandcastle/Source/Reflection/Reflection.csproj107
-rw-r--r--tools/Sandcastle/Source/Reflection/RootFilter.cs126
-rw-r--r--tools/Sandcastle/Source/Reflection/TestResolver.cs22
-rw-r--r--tools/Sandcastle/Source/Reflection/TypeFilter.cs120
-rw-r--r--tools/Sandcastle/Source/Reflection/WhidbeyNamer.cs275
23 files changed, 2806 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/Reflection/AllDocumentedFilter.cs b/tools/Sandcastle/Source/Reflection/AllDocumentedFilter.cs
new file mode 100644
index 0000000..a171b52
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/AllDocumentedFilter.cs
@@ -0,0 +1,90 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+//using System;
+using System.Compiler;
+using System.Xml.XPath;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ // exposes all apis, including internal apis, for which documentation is written
+
+ // this includes all members except for property and event accessors (e.g. get_ methods) and delegate members (e.g. Invoke).
+
+ // enumeration members are included
+
+ public class AllDocumentedFilter : ApiFilter {
+
+ public AllDocumentedFilter() : base() { }
+
+ public AllDocumentedFilter(XPathNavigator configuration) : base(configuration) { }
+
+
+
+ public override bool IsExposedMember(Member member) {
+
+ // member of delegates are not exposed
+ TypeNode type = member.DeclaringType;
+ 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);
+ }
+
+ // members marked as compiler-generated are not exposed
+ if (ListContainsAttribute(member.Attributes, "System.Runtime.CompilerServices.CompilerGeneratedAttribute")) {
+ return (false);
+ }
+
+ // okay, passed all tests, so member is exposed
+ return (base.IsExposedMember(member));
+
+ }
+
+ // all namespace and all types are exposed
+
+ /** <summary>Check the given type and all parent types for compiler attributes.
+ * If none are found look for any filters to determine if it is exposed.</summary> */
+ public override bool IsExposedType(TypeNode type) {
+
+ // don't include compiler-generated types
+ // check this and all parents for compiler attributes
+ TypeNode curType = type; //cursor
+ while (curType != null)
+ {
+ if (ListContainsAttribute(curType.Attributes, "System.Runtime.CompilerServices.CompilerGeneratedAttribute"))
+ return false;
+
+ curType = curType.DeclaringType; //check the next parent
+ }
+
+ //continue on with checking if the type is exposed
+ return base.IsExposedType(type);
+ }
+
+ private static bool ListContainsAttribute(AttributeList attributes, string name) {
+ for (int i = 0; i < attributes.Count; i++) {
+ if (attributes[i].Type.FullName == name) return (true);
+ }
+ return (false);
+ }
+
+ private static bool NameContains(string name, string substring) {
+ return (name.Contains(substring));
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/AllTopicFilter.cs b/tools/Sandcastle/Source/Reflection/AllTopicFilter.cs
new file mode 100644
index 0000000..b92bba6
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/AllTopicFilter.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ // exposes all apis for which a topic exists
+ // this includes all documented members (see DocumentFilter) except for enumeration members
+
+ public class AllTopicFilter : AllDocumentedFilter {
+
+ public override bool IsExposedMember(Member member) {
+ // don't expose members of enumerations
+ if (member.DeclaringType.NodeType == NodeType.EnumNode) return (false);
+ // otherwise, agree with DocumentedFilter
+ return (base.IsExposedMember(member));
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/ApiFilter.cs b/tools/Sandcastle/Source/Reflection/ApiFilter.cs
new file mode 100644
index 0000000..201878f
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/ApiFilter.cs
@@ -0,0 +1,208 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class ApiFilter {
+
+#region Member Variables
+
+ private RootFilter apiFilter = new RootFilter(true);
+
+ private RootFilter attributeFilter = new RootFilter(true);
+
+ private Dictionary < string, bool > namespaceCache = new Dictionary < string, bool >();
+
+#endregion
+
+#region Constructors
+
+ // stored filters
+
+ public ApiFilter() {
+ // apiFilters.Add(new UserFilter("System.Reflection", "", "", true));
+ // apiFilters.Add(new UserFilter("System", "Object", "", true));
+ // apiFilters.Add(new UserFilter("", "", "", false));
+
+ // attributeFilters.Add(new UserFilter("System.Runtime.InteropServices", "ComVisibleAttribute", "", false));
+ }
+
+ public ApiFilter(XPathNavigator configuration) {
+
+ if (configuration == null) throw new ArgumentNullException("configuration");
+
+ // API filter nodes
+ XPathNavigator apiFilterNode = configuration.SelectSingleNode("apiFilter");
+ if (apiFilterNode != null) {
+ XmlReader configurationReader = apiFilterNode.ReadSubtree();
+ configurationReader.MoveToContent();
+ apiFilter = new RootFilter(configurationReader);
+ configurationReader.Close();
+ }
+
+ // Attribute filter nodes
+ XPathNavigator attributeFilterNode = configuration.SelectSingleNode("attributeFilter");
+ if (attributeFilterNode != null) {
+ XmlReader configurationReader = attributeFilterNode.ReadSubtree();
+ configurationReader.MoveToContent();
+ attributeFilter = new RootFilter(configurationReader);
+ configurationReader.Close();
+ }
+
+ }
+
+#endregion
+
+#region Public API
+
+ public virtual bool HasExposedMembers(TypeNode type)
+ {
+ if (type == null) throw new ArgumentNullException("type");
+ return (apiFilter.HasExposedMembers(type));
+ }
+
+ // exposure logic for artibrary APIs
+ // call the appropriate particular exposure logic
+
+ public virtual bool IsExposedApi(Member api) {
+
+ Namespace space = api as Namespace;
+ if (space != null) return (IsExposedNamespace(space));
+
+ TypeNode type = api as TypeNode;
+ if (type != null) return (IsExposedType(type));
+
+ return (IsExposedMember(api));
+ }
+
+ public virtual bool IsExposedAttribute(AttributeNode attribute) {
+ if (attribute == null) throw new ArgumentNullException("attribute");
+
+ // check whether attribte type is exposed
+ TypeNode attributeType = attribute.Type;
+ if (!IsExposedType(attributeType)) return (false);
+
+ // check whether expressions used to instantiate attribute are exposed
+ ExpressionList expressions = attribute.Expressions;
+ for (int i = 0; i < expressions.Count; i++) {
+ if (!IsExposedExpression(expressions[i])) return (false);
+ }
+
+ // apply user filters to attribute
+ return (attributeFilter.IsExposedType(attributeType));
+ }
+
+ public virtual bool IsExposedMember(Member member) {
+ if (member == null) throw new ArgumentNullException("member");
+ return (apiFilter.IsExposedMember(member));
+ }
+
+ // namespce logic
+ // a namespace is exposed if any type in it is exposed
+
+ public virtual bool IsExposedNamespace(Namespace space) {
+ if (space == null) throw new ArgumentNullException("space");
+ string name = space.Name.Name;
+
+ // look in cache to see if namespace exposure is already determined
+ bool exposed;
+ if (!namespaceCache.TryGetValue(name, out exposed)) {
+ // it is not; determine exposure now
+
+ // the namespace is exposed if any types in it are exposed
+ exposed = NamespaceContainesExposedTypes(space) ?? false;
+
+ // the namespace is also exposed if it contains exposed members, even if all types are hidden
+ if (!exposed)
+ {
+ exposed = NamespaceContainsExposedMembers(space);
+ }
+
+ // cache the result
+ namespaceCache.Add(name, exposed);
+
+ }
+ return (exposed);
+ }
+
+ // type and member logic
+ // by default, types and members are exposed if a user filter says it, or if no user filter forbids it
+
+ public virtual bool IsExposedType(TypeNode type) {
+ if (type == null) throw new ArgumentNullException("type");
+ return (apiFilter.IsExposedType(type));
+ }
+
+#endregion
+
+#region Implementation
+
+ private bool IsExposedExpression(Expression expression) {
+ if (expression.NodeType == NodeType.Literal) {
+ Literal literal = (Literal)expression;
+ TypeNode type = literal.Type;
+ if (!IsExposedType(type)) return (false);
+ if (type.FullName == "System.Type") {
+ // if the value is itself a type, we need to test whether that type is visible
+ TypeNode value = literal.Value as TypeNode;
+ if ((value != null) && !IsExposedType(value)) return (false);
+ }
+ return (true);
+ } else if (expression.NodeType == NodeType.NamedArgument) {
+ NamedArgument assignment = (NamedArgument)expression;
+ return (IsExposedExpression(assignment.Value));
+ } else {
+ throw new InvalidOperationException("Encountered unrecognized expression");
+ }
+ }
+
+ private bool? NamespaceContainesExposedTypes(Namespace space)
+ {
+ TypeNodeList types = space.Types;
+
+ for (int i = 0; i < types.Count; i++)
+ {
+ TypeNode type = types[i];
+ if (IsExposedType(type)) return (true);
+ }
+
+ if (apiFilter.NamespaceFilterCount < 1)
+ {
+ return null; //this apiFilter does not contain any namespaces
+ }
+
+ return (false);
+ }
+
+
+ /** <summary>Check for any exposed members in any of the types.
+ * Returns true if the type has an exposed memeber filter and
+ * it is matched. This is used to determine if the namespace
+ * should be visited if the namespace and all types are set to
+ * false for exposed, we still want to visit them if any members
+ * are set to true.
+ * </summary> */
+ private bool NamespaceContainsExposedMembers(Namespace space)
+ {
+ TypeNodeList types = space.Types;
+ for (int i = 0; i < types.Count; i++)
+ {
+ TypeNode type = types[i];
+
+ if (HasExposedMembers(type)) return true;
+ }
+ return (false);
+ }
+
+#endregion
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/ApiNamer.cs b/tools/Sandcastle/Source/Reflection/ApiNamer.cs
new file mode 100644
index 0000000..ade218f
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/ApiNamer.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public abstract class ApiNamer {
+
+ public virtual string GetApiName(Member api) {
+
+ Namespace space = api as Namespace;
+ if (space != null) return (GetNamespaceName(space));
+
+ TypeNode type = api as TypeNode;
+ if (type != null) return (GetTypeName(type));
+
+ return (GetMemberName(api));
+
+ }
+
+ public abstract string GetMemberName(Member member);
+
+ public abstract string GetNamespaceName(Namespace space);
+
+ public abstract string GetTypeName(TypeNode type);
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/ApiVisitor.cs b/tools/Sandcastle/Source/Reflection/ApiVisitor.cs
new file mode 100644
index 0000000..7b5d9af
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/ApiVisitor.cs
@@ -0,0 +1,339 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+
+using System.Compiler;
+
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class ApiVisitor : IDisposable {
+
+ private static Comparison < Member > memberComparison = new Comparison < Member >(CompareMembers);
+
+ // Sorting logic
+
+ private static Comparison < Namespace > namespaceComparison = new Comparison < Namespace >(CompareMembers);
+
+ private static Comparison < TypeNode > typeComparison = new Comparison < TypeNode >(CompareMembers);
+
+ private List < AssemblyNode > accessoryAssemblies = new List < AssemblyNode >();
+
+ // Disposal logic
+
+ private List < AssemblyNode > assemblies = new List < AssemblyNode >();
+
+ // object model store
+
+ private Dictionary < string, Namespace > catalog = new Dictionary < string, Namespace >();
+
+ private ApiFilter filter;
+
+ // Keep track of any metadata load errors
+
+ private Dictionary < string, Exception > loadErrors = new Dictionary < string, Exception >();
+
+ // Revised assembly storage
+
+ private AssemblyResolver resolver = new AssemblyResolver();
+
+ protected ApiVisitor(ApiFilter filter) {
+ this.filter = filter;
+ }
+
+ protected ApiVisitor() : this(new NoFilter()) { }
+
+ public AssemblyNode[] AccessoryAssemblies {
+ get {
+ return (accessoryAssemblies.ToArray());
+ }
+ }
+
+ public ApiFilter ApiFilter {
+ get {
+ return (filter);
+ }
+ set {
+ filter = value;
+ }
+ }
+
+ public AssemblyNode[] Assemblies {
+ get {
+ return (assemblies.ToArray());
+ }
+ }
+
+ public Dictionary < string, Exception > LoadErrors {
+ get {
+ return (loadErrors);
+ }
+ }
+
+ public AssemblyResolver Resolver {
+ get {
+ return (resolver);
+ }
+ set {
+ resolver = value;
+ }
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ foreach (AssemblyNode assembly in assemblies) {
+ // Console.WriteLine(loadedModule.Name);
+ assembly.Dispose();
+ }
+ foreach (AssemblyNode accessoryAssembly in accessoryAssemblies) {
+ accessoryAssembly.Dispose();
+ }
+ }
+ }
+
+ public void LoadAccessoryAssemblies(string filePattern) {
+
+ // get the full path to the relevent directory
+ string directoryPath = Path.GetDirectoryName(filePattern);
+ if ((directoryPath == null) || (directoryPath.Length == 0)) directoryPath = Environment.CurrentDirectory;
+ directoryPath = Path.GetFullPath(directoryPath);
+
+ // get the file name, which may contain wildcards
+ string filePath = Path.GetFileName(filePattern);
+
+ // look up the files and load them
+ string[] files = Directory.GetFiles(directoryPath, filePath);
+ foreach (string file in files) {
+ LoadAccessoryAssembly(file);
+ }
+ }
+
+ // Accessory modules
+
+ //private IDictionary cache = new Hashtable();
+
+ public void LoadAccessoryAssembly(string filePath) {
+ AssemblyNode assembly = AssemblyNode.GetAssembly(filePath, null, false, false, false, false); // this causes non-classes to register as classes
+ if (assembly != null) {
+ if (assembly.Name == "mscorlib") ResetMscorlib(assembly);
+
+ resolver.Add(assembly);
+ //assembly.AssemblyReferenceResolutionAfterProbingFailed += unresolvedModuleHandler;
+ accessoryAssemblies.Add(assembly);
+ }
+ }
+
+ public void LoadAssemblies(string filePattern) {
+
+ // get the full path to the relevent directory
+ string directoryPath = Path.GetDirectoryName(filePattern);
+ if ((directoryPath == null) || (directoryPath.Length == 0)) directoryPath = Environment.CurrentDirectory;
+ directoryPath = Path.GetFullPath(directoryPath);
+
+ // get the file name, which may contain wildcards
+ string filePath = Path.GetFileName(filePattern);
+
+ // look up the files and load them
+ string[] files = Directory.GetFiles(directoryPath, filePath);
+ foreach (string file in files) {
+ LoadAssembly(file);
+ }
+
+ }
+
+ // Parsing logic
+
+ public void LoadAssembly(string filePath) {
+ //Console.WriteLine("loading {0}", filePath);
+ //AssemblyNode assembly = AssemblyNode.GetAssembly(filePath); // this causes mscorlib to be missing members
+ //AssemblyNode assembly = AssemblyNode.GetAssembly(filePath, cache); // this causes compact framework non-classes to register as classes
+ //AssemblyNode assembly = AssemblyNode.GetAssembly(filePath, cache, false, false, true, false); // this causes missing mscorlib members
+ //AssemblyNode assembly = AssemblyNode.GetAssembly(filePath, cache, false, false, false, false); // this causes non-classes to register as classes
+ //AssemblyNode assembly = AssemblyNode.GetAssembly(filePath, null, false, false, true, false); // this causes missing mscorlib members
+ AssemblyNode assembly = AssemblyNode.GetAssembly(filePath, null, false, false, false, false); // this causes non-classes to register as classes
+
+ if (assembly != null) {
+ if (assembly.Name == "mscorlib") ResetMscorlib(assembly);
+
+ // Console.WriteLine("assembly = {0}", assembly.Name);
+ resolver.Add(assembly);
+ //assembly.AssemblyReferenceResolutionAfterProbingFailed += unresolvedModuleHandler;
+ assemblies.Add(assembly);
+ //Console.WriteLine("{0} has {1} types", assembly.Name, assembly.ExportedTypes.Count);
+ //StoreTypes(assembly.Types);
+ }
+
+ }
+
+ // Visit Object Model
+
+ public void VisitApis() {
+
+ // store types
+ // we have to do this after all assemblies are registered because the resolution may not work unless
+ // all the assemblies we need are in the resolver cache
+ //Console.WriteLine("storing types");
+ foreach (AssemblyNode assembly in assemblies) {
+ //Console.WriteLine("assembly {0}", assembly.Name);
+ //Console.WriteLine("has {0} types", assembly.Types.Count);
+ StoreTypes(assembly.Types);
+ //Console.WriteLine("done with assembly");
+ }
+ //Console.WriteLine("done storing types");
+
+ //Console.WriteLine("visiting namespaces");
+ NamespaceList spaces = new NamespaceList();
+ foreach (Namespace space in catalog.Values) {
+ if (filter.IsExposedNamespace(space)) spaces.Add(space);
+ }
+ VisitNamespaces(spaces);
+ }
+
+ protected virtual void VisitEntity(Member entity) {
+ // inherit and insert logic here
+ }
+
+ protected virtual void VisitMember(Member member) {
+ VisitEntity(member);
+ }
+
+ protected virtual void VisitMembers(MemberList members) {
+ // sort members by name
+ Member[] sorted_members = new Member[members.Count];
+ for (int i = 0; i < members.Count; i++) sorted_members[i] = members[i];
+ Array.Sort < Member >(sorted_members, memberComparison);
+ // visit them
+ foreach (Member member in sorted_members) {
+ // don't visit nested types, as they are already visited
+ if (member is TypeNode) continue;
+ if (filter.IsExposedMember(member))
+ {
+ VisitMember(member);
+ }
+ }
+ }
+
+ protected virtual void VisitNamespace(Namespace space) {
+ //Console.WriteLine("Visit Entity {0}",space.FullName);
+ VisitEntity(space);
+ TypeNodeList types = space.Types;
+ VisitTypes(types);
+ }
+
+ protected virtual void VisitNamespaces(NamespaceList spaces) {
+ // sort namespaces by name
+ Namespace[] sorted_spaces = new Namespace[spaces.Count];
+ for (int i = 0; i < spaces.Count; i++) sorted_spaces[i] = spaces[i];
+ Array.Sort < Namespace >(sorted_spaces, namespaceComparison);
+ // visit them
+ foreach (Namespace space in sorted_spaces) {
+ if (filter.IsExposedNamespace(space)) VisitNamespace(space);
+ }
+ }
+
+ protected virtual void VisitType(TypeNode type) {
+ //Console.WriteLine(type.FullName);
+ VisitEntity(type);
+ MemberList members = type.Members;
+ //Console.WriteLine("{0}: {1}", type.FullName, members.Length);
+ VisitMembers(members);
+ }
+
+ protected virtual void VisitTypes(TypeNodeList types) {
+ // sort types by name
+ TypeNode[] sorted_types = new TypeNode[types.Count];
+ for (int i = 0; i < types.Count; i++) sorted_types[i] = types[i];
+ Array.Sort < TypeNode >(sorted_types, typeComparison);
+ // visit them
+ foreach (TypeNode type in sorted_types) {
+ //Console.WriteLine("visiting {0}", type.Name);
+ //visit this type if it is exposed, or has members that are set as exposed
+ if (filter.IsExposedType(type) || filter.HasExposedMembers(type))
+ VisitType(type); //visit type and members
+ }
+ }
+
+ private static int CompareMembers(Member a, Member b) {
+ return (String.Compare(a.FullName, b.FullName));
+ }
+
+ private static int CompareNamespaces(Namespace a, Namespace b) {
+ return (String.Compare(a.Name.Name, b.Name.Name));
+ }
+
+ private static int CompareTypes(TypeNode a, TypeNode b) {
+ return (String.Compare(a.Name.Name, b.Name.Name));
+ }
+
+ private static string GetNamespaceName(TypeNode type) {
+ TypeNode parent = type.DeclaringType;
+ if (parent != null) {
+ return (GetNamespaceName(parent));
+ } else {
+ if (type.Namespace == null) {
+ return (String.Empty);
+ } else {
+ return (type.Namespace.Name);
+ }
+ }
+ }
+
+ private void ResetMscorlib(AssemblyNode assembly) {
+ TargetPlatform.Clear();
+ CoreSystemTypes.Clear();
+ CoreSystemTypes.SystemAssembly = assembly;
+ CoreSystemTypes.Initialize(true, false);
+ }
+
+ private void StoreType(TypeNode type) {
+ //Console.WriteLine("type: {0} ", type.Name);
+ /*
+ if (type.Name == null) {
+ // CCI seems to occasionally construct corrupted, phantom types, which we should reject
+ // Console.WriteLine("unidentified type rejected");
+ return;
+ }
+ */
+ string spaceName = GetNamespaceName(type);
+ //Console.WriteLine("in space: {0}", spaceName);
+ Namespace space;
+ if (!catalog.TryGetValue(spaceName, out space)) {
+ space = new Namespace(new Identifier(spaceName));
+ catalog.Add(spaceName, space);
+ }
+ if (space.Types == null) Console.WriteLine("null type list");
+ space.Types.Add(type);
+
+ //Console.WriteLine("getting members");
+ MemberList members = type.Members;
+ //Console.WriteLine("got {0} members", members.Count);
+ for (int i = 0; i < members.Count; i++) {
+ TypeNode nestedType = members[i] as TypeNode;
+ if (nestedType != null) {
+ //Console.WriteLine("nested type {0}", type.FullName);
+ StoreType(nestedType);
+ }
+ }
+ //Console.WriteLine("done storing type");
+ }
+
+ private void StoreTypes(TypeNodeList types) {
+ //Console.WriteLine("{0} types", types.Length);
+ for (int i = 0; i < types.Count; i++) {
+ StoreType(types[i]);
+ }
+ }
+
+ }
+
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/AssemblyReferenceEventArgs.cs b/tools/Sandcastle/Source/Reflection/AssemblyReferenceEventArgs.cs
new file mode 100644
index 0000000..feaa117
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/AssemblyReferenceEventArgs.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class AssemblyReferenceEventArgs : EventArgs {
+
+ private Module module;
+
+ private AssemblyReference reference;
+
+ public AssemblyReferenceEventArgs(AssemblyReference reference, Module module) {
+ this.reference = reference;
+ this.module = module;
+ }
+
+ public AssemblyReference Reference {
+ get {
+ return (reference);
+ }
+ }
+
+ public Module Referrer {
+ get {
+ return (module);
+ }
+ }
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/AssemblyResolver.cs b/tools/Sandcastle/Source/Reflection/AssemblyResolver.cs
new file mode 100644
index 0000000..116dcc8
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/AssemblyResolver.cs
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class AssemblyResolver {
+
+ private Dictionary < string, AssemblyNode > cache = new Dictionary < string, AssemblyNode >();
+
+ private bool useGac = true;
+
+ public AssemblyResolver() {
+
+ }
+
+ public AssemblyResolver(XPathNavigator configuration) {
+
+ string useGacValue = configuration.GetAttribute("use-gac", String.Empty);
+ if (!String.IsNullOrEmpty(useGacValue)) useGac = Convert.ToBoolean(useGacValue);
+
+ }
+
+ public event EventHandler < AssemblyReferenceEventArgs > UnresolvedAssemblyReference;
+
+ public bool UseGac {
+ get {
+ return (useGac);
+ }
+ set {
+ useGac = value;
+ }
+ }
+
+ public virtual void Add(AssemblyNode assembly) {
+ if (assembly == null) throw new ArgumentNullException("assembly");
+ string name = assembly.StrongName;
+ assembly.AssemblyReferenceResolution += new Module.AssemblyReferenceResolver(ResolveReference);
+ assembly.AssemblyReferenceResolutionAfterProbingFailed += new Module.AssemblyReferenceResolver(UnresolvedReference);
+ cache[name] = assembly;
+ //Console.WriteLine("added {0}; cache now contains {1}", name, cache.Count);
+ }
+
+ public virtual AssemblyNode ResolveReference(AssemblyReference reference, Module module) {
+
+ if (reference == null) throw new ArgumentNullException("reference");
+
+ //Console.WriteLine("resolving {0}", reference.StrongName);
+
+ // try to get it from the cache
+ string name = reference.StrongName;
+ if (cache.ContainsKey(name)) return (cache[name]);
+
+ // try to get it from the gac
+ if (useGac) {
+ string location = GlobalAssemblyCache.GetLocation(reference);
+ if (location != null) {
+ AssemblyNode assembly = AssemblyNode.GetAssembly(location, null, false, false, false, false);
+ if (assembly != null) {
+ Add(assembly);
+ return (assembly);
+ }
+ }
+ }
+
+ // couldn't find it; return null
+ // Console.WriteLine("returning null on request for {0}", reference.StrongName);
+ //OnUnresolvedAssemblyReference(reference, module);
+ return (null);
+
+ }
+
+ protected virtual void OnUnresolvedAssemblyReference(AssemblyReference reference, Module module) {
+ if (UnresolvedAssemblyReference != null) UnresolvedAssemblyReference(this, new AssemblyReferenceEventArgs(reference, module));
+ }
+
+ private AssemblyNode UnresolvedReference(AssemblyReference reference, Module module) {
+ OnUnresolvedAssemblyReference(reference, module);
+ return (null);
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/ExternalDocumentedFilter.cs b/tools/Sandcastle/Source/Reflection/ExternalDocumentedFilter.cs
new file mode 100644
index 0000000..e7f0cf7
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/ExternalDocumentedFilter.cs
@@ -0,0 +1,82 @@
+// 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 {
+
+ public ExternalDocumentedFilter() : base() { }
+
+ public ExternalDocumentedFilter(XPathNavigator configuration) : base(configuration) { }
+
+ public override bool IsExposedMember(Member member) {
+ if (member == null) throw new ArgumentNullException("member");
+ // if the member isn't visible, we certainly won't expose it...
+ if (!member.IsVisibleOutsideAssembly) return (false);
+ // ...but there are also some visible members we won't expose.
+ TypeNode type = member.DeclaringType;
+ // 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 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");
+ // expose any visible types allowed by the base filter
+ if (type.IsVisibleOutsideAssembly) {
+ return (base.IsExposedType(type));
+ } else {
+ return (false);
+ }
+ // return(type.IsVisibleOutsideAssembly);
+ }
+
+ private static bool NameContains(string name, string substring) {
+ return (name.Contains(substring));
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/ExternalFilter.cs b/tools/Sandcastle/Source/Reflection/ExternalFilter.cs
new file mode 100644
index 0000000..ff99bef
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/ExternalFilter.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ // exposes all APIs that are visible from outside the assembly
+
+ // this includes property and event accessors (e.g. get_), delegate methods (e.g. Invoke), as well as enumeration members
+
+ public class ExternalFilter : ApiFilter {
+
+ public override bool IsExposedMember(Member member) {
+ if (member == null) throw new ArgumentNullException("member");
+ // expose all visible members
+ return (member.IsVisibleOutsideAssembly);
+ }
+
+ // 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");
+ // expose all visible types
+ return (type.IsVisibleOutsideAssembly);
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/ExternalTopicFilter.cs b/tools/Sandcastle/Source/Reflection/ExternalTopicFilter.cs
new file mode 100644
index 0000000..ed6eae7
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/ExternalTopicFilter.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ // exposes all apis for which a topic exists
+ // this includes all documented members (see DocumentFilter) except for enumeration members
+
+ public class ExternalTopicFilter : ExternalDocumentedFilter {
+
+ public override bool IsExposedMember(Member member) {
+ // don't expose members of enumerations
+ if (member.DeclaringType.NodeType == NodeType.EnumNode) return (false);
+ // otherwise, agree with DocumentedFilter
+ return (base.IsExposedMember(member));
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/GlobalSuppressions.cs b/tools/Sandcastle/Source/Reflection/GlobalSuppressions.cs
new file mode 100644
index 0000000..aff5272
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/GlobalSuppressions.cs
@@ -0,0 +1,55 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ddue", Scope = "namespace", Target = "Microsoft.Ddue.Tools.Reflection")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Namer", Scope = "type", Target = "Microsoft.Ddue.Tools.Reflection.ApiNamer")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.Compare(System.String,System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#CompareMembers(System.Compiler.Member,System.Compiler.Member)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.Compare(System.String,System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#CompareNamespaces(System.Compiler.Namespace,System.Compiler.Namespace)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.Compare(System.String,System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#CompareTypes(System.Compiler.TypeNode,System.Compiler.TypeNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#CompareNamespaces(System.Compiler.Namespace,System.Compiler.Namespace)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#CompareTypes(System.Compiler.TypeNode,System.Compiler.TypeNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#ResetMscorlib(System.Compiler.AssemblyNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#Assemblies")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ApiVisitor.#AccessoryAssemblies")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer.#GetName(System.Compiler.Member)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ReflectionUtilities.#TypeMatch(System.Compiler.TypeNode,System.Compiler.TypeNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#GetName(System.Compiler.Member)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "argument", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer.#WriteType(System.Compiler.TypeNode,System.IO.TextWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "arguments", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ReflectionUtilities.#GetTemplateType(System.Compiler.TypeNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "argument", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#WriteType(System.Compiler.TypeNode,System.IO.TextWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer.#WriteType(System.Compiler.TypeNode,System.IO.TextWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#WriteType(System.Compiler.TypeNode,System.IO.TextWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Module", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.AssemblyResolver.#ResolveReference(System.Compiler.AssemblyReference,System.Compiler.Module)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Module", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.AssemblyResolver.#OnUnresolvedAssemblyReference(System.Compiler.AssemblyReference,System.Compiler.Module)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Namer", Scope = "type", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Namer", Scope = "type", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Gac", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.AssemblyResolver.#UseGac")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.AssemblyResolver.#.ctor(System.Xml.XPath.XPathNavigator)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.MemberFilter.#.ctor(System.Xml.XmlReader)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.NamespaceFilter.#.ctor(System.Xml.XmlReader)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.RootFilter.#.ctor(System.Xml.XmlReader)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToBoolean(System.String)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.TypeFilter.#.ctor(System.Xml.XmlReader)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.ReflectionUtilities.#GetTemplateType(System.Compiler.TypeNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#GetMemberName(System.Compiler.Member)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#GetName(System.Compiler.Member)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#GetNamespaceName(System.Compiler.Namespace)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#GetTypeName(System.Compiler.TypeNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#WriteEvent(System.Compiler.Event,System.IO.TextWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#WriteMethod(System.Compiler.Method,System.IO.TextWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.OrcasNamer.#WriteProperty(System.Compiler.Property,System.IO.TextWriter)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer.#GetMemberName(System.Compiler.Member)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer.#GetName(System.Compiler.Member)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer.#GetNamespaceName(System.Compiler.Namespace)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.WhidbeyNamer.#GetTypeName(System.Compiler.TypeNode)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.RootFilter.#NamespaceFilters")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.NamespaceFilter.#TypeFilters")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.NamespaceFilter.#IsExposedNamespace(System.Compiler.Namespace)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Scope = "member", Target = "Microsoft.Ddue.Tools.Reflection.TypeFilter.#IsExposedType(System.Compiler.TypeNode)")]
diff --git a/tools/Sandcastle/Source/Reflection/MemberFilter.cs b/tools/Sandcastle/Source/Reflection/MemberFilter.cs
new file mode 100644
index 0000000..051d589
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/MemberFilter.cs
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class MemberFilter
+ {
+
+#region Member Variables
+
+ private bool exposed;
+
+ private string name;
+
+#endregion
+
+#region Constructors
+ public MemberFilter(string name, bool exposed) {
+ if (name == null) throw new ArgumentNullException("name");
+ this.name = name;
+ this.exposed = exposed;
+ }
+
+ public MemberFilter(XmlReader configuration) {
+ if ((configuration.NodeType != XmlNodeType.Element) || (configuration.Name != "member")) throw new InvalidOperationException();
+ name = configuration.GetAttribute("name");
+ exposed = Convert.ToBoolean(configuration.GetAttribute("expose"));
+ }
+#endregion
+
+#region Public API
+ public bool? IsExposedMember(Member member) {
+ if (member.Name.Name == name) {
+ return (exposed);
+ } else {
+ return (null);
+ }
+ }
+#endregion
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/NamespaceFilter.cs b/tools/Sandcastle/Source/Reflection/NamespaceFilter.cs
new file mode 100644
index 0000000..9a8956c
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/NamespaceFilter.cs
@@ -0,0 +1,143 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class NamespaceFilter
+ {
+
+#region Member Variables
+
+ private bool exposed;
+ private string name;
+
+ private List < TypeFilter > typeFilters = new List < TypeFilter >();
+#endregion
+
+#region Constructors
+ public NamespaceFilter(string name, bool exposed) {
+ this.name = name;
+ this.exposed = exposed;
+ }
+
+ public NamespaceFilter(XmlReader configuration) {
+ if (configuration.Name != "namespace") throw new InvalidOperationException();
+ name = configuration.GetAttribute("name");
+ exposed = Convert.ToBoolean(configuration.GetAttribute("expose"));
+ XmlReader subtree = configuration.ReadSubtree();
+ while (subtree.Read()) {
+ if ((subtree.NodeType == XmlNodeType.Element) && (subtree.Name == "type")) {
+ TypeFilter typeFilter = new TypeFilter(subtree);
+ typeFilters.Add(typeFilter);
+ }
+ }
+ subtree.Close();
+ }
+#endregion
+
+#region Public API
+
+ /// <summary>
+ /// Gets the number of type filters
+ /// </summary>
+ public int TypeFilterCount
+ {
+ get
+ {
+ return typeFilters.Count;
+ }
+ }
+
+ public List < TypeFilter > TypeFilters {
+ get {
+ return (typeFilters);
+ {
+ }
+ }
+ }
+
+
+ //Find out if any are exposed incase this class is not exposed
+ public bool HasExposedMembers(TypeNode type)
+ {
+ Namespace space = ReflectionUtilities.GetNamespace(type);
+ if (IsExposedNamespace(space) != null)
+ {
+ foreach (TypeFilter typeFilter in typeFilters)
+ {
+ bool? result = typeFilter.IsExposedType(type);
+ if (result != null) //matched
+ {
+ return typeFilter.HasExposedMembers(type);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public bool? IsExposedMember(Member member) {
+ //Console.WriteLine("DEBUG: namespaceFilter.isExposedMemeber");
+ TypeNode type = ReflectionUtilities.GetTemplateType(member.DeclaringType);
+ Namespace space = ReflectionUtilities.GetNamespace(type);
+ if (IsExposedNamespace(space) != null) {
+ foreach (TypeFilter typeFilter in typeFilters) {
+ bool? result = typeFilter.IsExposedMember(member);
+ if (result != null) return (result);
+ }
+
+ //no filters matched this method, check if the type is exposed
+ bool? typeIsExposed = IsExposedType(type);
+ if (typeIsExposed != null) return typeIsExposed;
+
+ return (exposed); //if the namespace is exposed
+ } else {
+ return (null);
+ }
+ }
+
+ public bool? IsExposedNamespace(Namespace space) {
+ if (space.Name.Name == name) {
+ return (exposed);
+ } else {
+ return (null);
+ }
+ }
+
+ public bool? IsExposedType(TypeNode type) {
+ Namespace space = ReflectionUtilities.GetNamespace(type);
+ if (IsExposedNamespace(space) != null) {
+ foreach (TypeFilter typeFilter in typeFilters) {
+ bool? result = typeFilter.IsExposedType(type);
+ if (result != null) return (result);
+ }
+
+ //no filter matches for this type, check the parents since it could be nested
+ TypeNode parent = type.DeclaringType;
+ while (parent != null)
+ {
+ bool? parentExposed = IsExposedType(parent);
+
+ if (parentExposed != null)
+ return parentExposed;
+
+ parent = type.DeclaringType;
+ }
+
+ //no answer for the parents either, the top parent should pass this back above
+ return (exposed);
+ } else {
+ return (null);
+ }
+ }
+
+#endregion
+ }
+}
diff --git a/tools/Sandcastle/Source/Reflection/NoFilter.cs b/tools/Sandcastle/Source/Reflection/NoFilter.cs
new file mode 100644
index 0000000..0e7b7f5
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/NoFilter.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class NoFilter : ApiFilter {
+
+ public override bool IsExposedApi(Member api) {
+ return (true);
+ }
+
+ public override bool IsExposedMember(Member member) {
+ return (true);
+ }
+
+ public override bool IsExposedNamespace(Namespace space) {
+ return (true);
+ }
+
+ public override bool IsExposedType(TypeNode type) {
+ return (true);
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/Notes.txt b/tools/Sandcastle/Source/Reflection/Notes.txt
new file mode 100644
index 0000000..e5ab15c
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/Notes.txt
@@ -0,0 +1,215 @@
+Entity
+ Name : string
+ Visiblity :
+
+Namespace : Entity
+ Types : Type[]
+
+Type : Entity
+ Namespace : Namespace
+ Interfaces : Interface[]
+ Members : Member[]
+ TemplateArguments : Type[]
+ CustomAttributes : Attribute[]
+ SecurityAttributes :
+ ContainingType : Type
+ Assembly
+
+Class : Type
+ BaseClass : Class
+ DerivedClasses : Class[]
+ IsAbstract : bool
+ IsSealed : bool
+
+Structure : Type
+
+Interface : Type
+
+Delegate : Type
+ Parameters : Parameter[]
+ ReturnType : Type
+
+Enumeration : Type
+ UnderlyingType : Type
+
+TemplateParameter : Type
+ IsValueType : bool
+
+TypeArray : Type
+ Rank : int
+ UnderlyingType : Type
+
+TypePointer : Type
+ UnderlyingType : Type
+
+TypeReference : Type
+ UnderlyingType : Type
+
+Member : Entity
+ IsStatic : bool
+ IsSpecialName : bool
+ DeclaringType : Type
+ Overrides : Member
+ Attributes : Attribute[]
+
+Field : Member
+ Type : Type
+ IsLiteral : bool
+ IsInitOnly : bool
+ IsVolitile : bool
+
+Method : Member
+ Parameters : Parameter[]
+ ReturnType : Type
+ IsAbstract : bool
+ IsVirtual : bool
+ IsFinal : bool
+ IsExtern : bool
+ Implements : Member[]
+
+Constructor : Member
+ Parameters : Parameter[]
+
+Property : Member
+ Parameters : Parameter[]
+ Type : Type
+ IsAbstract : bool
+ IsVirtual : bool
+ IsFinal : bool
+ Implements : Property[]
+ Getter : Method
+ Setter : Method
+
+Event : Member
+ Handler : Delegate
+ IsAbstract : bool
+ IsVirtual : bool
+ IsFinal : bool
+ Implements : Event[]
+ Adder: Method
+ Remover : Method
+ Raiser : Method
+
+Parameter
+ Name : string
+ Type : Type
+ CustomAttributes : Attribute[]
+
+Attribute
+ Type : Type
+ Constructor : Constructor
+ Arguments : Object[]
+
+
+Namespace:
+ <apidata name="System.Web" group="namespace" />
+ <elements />
+
+Type:
+ <apidata name="System.String" group="type" subgroup="class" />
+ <typedata visibility="public" abstract="false" sealed="false" serializable="true" />
+ <containers namespace="N:System" assembly="mscorlib" />
+ <implements />
+ <elements />
+ <attributes />
+
+Class:
+ <classdata parent="T:System.Object" />
+
+Delegate:
+ <parameters />
+ <value />
+
+Enumeration:
+ <enumdata base />
+
+Member:
+ <apidata name="System.String.Length" group="member" subgroup="property" />
+ <memberdata visibility="public" static="false" special="false" />
+ <proceduredata abstract="false" virtual="false" final="false" />
+ <propertydata getter="M:System.String.get_Length" getter-visibility setter setter-visibility />
+ <containers namespace="N:System" type="T:System.String" assembly="mscorlib" />
+
+Field:
+ <fielddata literal initonly volative serialized />
+ <value />
+
+Method:
+ <templates />
+ <parameters />
+ <value />
+
+Event:
+ <eventdata handler adder remover args />
+
+
+
+Namespace:
+<entityProperties name="System.Web" group="namespace" />
+
+Class:
+<entityProperties name="Console" visibility="public" group="type" subgroup="class" />
+<typeProperties namespace="N:System" abstract="true" sealed="true" />
+
+Method:
+<entityProperties name="AsReadOnly" visiblity="public" group="member" subgroup="method" />
+<memberProperties type="T:System.Array" static="true" special="false" abstract="false" virtual="false" final="true" />
+
+
+entityProperties
+ name
+ group
+ subgroup
+ subsubgroup
+
+typeProperties
+ namespace
+ assembly
+ abstract
+ sealed
+ parent
+ container
+
+memberProperties
+ type
+ static
+ special
+ literal
+ initonly
+ volitile
+ abstract
+ virtual
+ final
+ extern
+
+
+<entityInfo name="Boo" visiblity="protected" group="type" />
+<typeInfo namespace="N:Foo" container="T:Foo.Barrel" assembly="mscorlib.dll" subgroup="class" />
+<classInfo base="T:System.Object" abstract="false" sealed="false" />
+<templates>
+ <template name="TKey" />
+ <template name="TValue" />
+</templates>
+<interfaces>
+ <interface type="T:Foo.IBoo" />
+</interfaces>
+<attributes>
+ <attribute type="T:Foo.MyAttribute" constructor="T:Foo.MyAttribute.#ctor(System.Boolean)" />
+ <parameter name="visible" type="T:System.Boolean" value="true" />
+ </attribute>
+</attributes>
+<members>
+ <member member="M:Foo.Boo.#ctor" />
+ <member member="P:Foo.Boo.Value" />
+</members>
+
+<entity name="Moo" visibility="protected" group="method" />
+<memberInfo type="T:Foo.Boo" static="false" special="false" subgroup="method" />
+<methodnfo abstract="false" virtual="true" />
+<parameters>
+ <parameter name="x" type="T:`0" />
+<parameters>
+<value type="T:System.Int32" />
+<implements>
+ <implement type="T:Foo.IBoo" member="M:Foo.IBoo.Choo" />
+</implements>
diff --git a/tools/Sandcastle/Source/Reflection/OrcasNamer.cs b/tools/Sandcastle/Source/Reflection/OrcasNamer.cs
new file mode 100644
index 0000000..806c7a2
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/OrcasNamer.cs
@@ -0,0 +1,376 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+// using System.Collections.Generic;
+using System.IO;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class OrcasNamer : ApiNamer {
+
+ public override string GetMemberName(Member member) {
+
+ using (TextWriter writer = new StringWriter()) {
+
+ switch (member.NodeType) {
+ case NodeType.Field:
+ writer.Write("F:");
+ WriteField((Field)member, writer);
+ break;
+ case NodeType.Property:
+ writer.Write("P:");
+ WriteProperty((Property)member, writer);
+ break;
+ case NodeType.Method:
+ writer.Write("M:");
+ WriteMethod((Method)member, writer);
+ break;
+ case NodeType.InstanceInitializer:
+ writer.Write("M:");
+ WriteConstructor((InstanceInitializer)member, writer);
+ break;
+ case NodeType.StaticInitializer:
+ writer.Write("M:");
+ WriteStaticConstructor((StaticInitializer)member, writer);
+ break;
+ case NodeType.Event:
+ writer.Write("E:");
+ WriteEvent((Event)member, writer);
+ break;
+ }
+
+ return (writer.ToString());
+
+ }
+
+ }
+
+ public override string GetNamespaceName(Namespace space) {
+ using (TextWriter writer = new StringWriter()) {
+ writer.Write("N:");
+ WriteNamespace(space, writer);
+ return (writer.ToString());
+ }
+ }
+
+ public override string GetTypeName(TypeNode type) {
+ using (TextWriter writer = new StringWriter()) {
+ writer.Write("T:");
+ WriteType(type, writer);
+ return (writer.ToString());
+ }
+ }
+
+
+ private static string GetName(Member entity) {
+
+ using (TextWriter writer = new StringWriter()) {
+
+ TypeNode type = entity as TypeNode;
+ if (type != null) {
+ writer.Write("T:");
+ WriteType(type, writer);
+ return (writer.ToString());
+ }
+
+ switch (entity.NodeType) {
+ case NodeType.Namespace:
+ writer.Write("N:");
+ WriteNamespace(entity as Namespace, writer);
+ break;
+ case NodeType.Field:
+ writer.Write("F:");
+ WriteField(entity as Field, writer);
+ break;
+ case NodeType.Property:
+ writer.Write("P:");
+ WriteProperty(entity as Property, writer);
+ break;
+ case NodeType.Method:
+ writer.Write("M:");
+ WriteMethod(entity as Method, writer);
+ break;
+ case NodeType.InstanceInitializer:
+ writer.Write("M:");
+ WriteConstructor(entity as InstanceInitializer, writer);
+ break;
+ case NodeType.StaticInitializer:
+ writer.Write("M:");
+ WriteStaticConstructor(entity as StaticInitializer, writer);
+ break;
+ case NodeType.Event:
+ writer.Write("E:");
+ WriteEvent(entity as Event, writer);
+ break;
+ }
+
+ return (writer.ToString());
+
+ }
+
+ }
+
+ private static void WriteConstructor(InstanceInitializer constructor, TextWriter writer) {
+ WriteType(constructor.DeclaringType, writer);
+ writer.Write(".#ctor");
+ WriteParameters(constructor.Parameters, writer);
+ }
+
+ private static void WriteEvent(Event trigger, TextWriter writer) {
+ WriteType(trigger.DeclaringType, writer);
+
+ Event eiiTrigger = null;
+ if (trigger.IsPrivate && trigger.IsVirtual) {
+ Event[] eiiTriggers = ReflectionUtilities.GetImplementedEvents(trigger);
+ if (eiiTriggers.Length > 0) eiiTrigger = eiiTriggers[0];
+ }
+
+ if (eiiTrigger != null) {
+ TypeNode eiiType = eiiTrigger.DeclaringType;
+ TextWriter eiiWriter = new StringWriter();
+
+ if (eiiType != null && eiiType.Template != null)
+ {
+ writer.Write(".");
+ WriteTemplate(eiiType, writer);
+ }
+ else
+ {
+ WriteType(eiiType, eiiWriter);
+ writer.Write(".");
+ writer.Write(eiiWriter.ToString().Replace('.', '#'));
+ }
+
+ writer.Write("#");
+ writer.Write(eiiTrigger.Name.Name);
+ } else {
+ writer.Write(".{0}", trigger.Name.Name);
+ }
+ }
+
+ private static void WriteField(Field field, TextWriter writer) {
+ WriteType(field.DeclaringType, writer);
+ writer.Write(".{0}", field.Name.Name);
+ }
+
+ private static void WriteMethod(Method method, TextWriter writer) {
+ string name = method.Name.Name;
+ WriteType(method.DeclaringType, writer);
+
+ Method eiiMethod = null;
+ if (method.IsPrivate && method.IsVirtual) {
+ MethodList eiiMethods = method.ImplementedInterfaceMethods;
+ if (eiiMethods.Count > 0) eiiMethod = eiiMethods[0];
+ }
+ if (eiiMethod != null) { //explicitly implemented interface
+ TypeNode eiiType = eiiMethod.DeclaringType;
+ TextWriter eiiWriter = new StringWriter();
+
+
+ //we need to keep the param names instead of turning them into numbers
+ //get the template to the right format
+ if (eiiType != null && eiiType.Template != null)
+ {
+ writer.Write(".");
+ WriteTemplate(eiiType, writer);
+ }
+ else //revert back to writing the type the old way if there is no template
+ {
+ WriteType(eiiType, eiiWriter);
+ writer.Write(".");
+ writer.Write(eiiWriter.ToString().Replace('.', '#'));
+ }
+
+ writer.Write("#");
+ writer.Write(eiiMethod.Name.Name);
+ } else {
+ writer.Write(".{0}", name);
+ }
+ if (method.IsGeneric) {
+ TypeNodeList genericParameters = method.TemplateParameters;
+ if (genericParameters != null) {
+ writer.Write("``{0}", genericParameters.Count);
+ }
+ }
+ WriteParameters(method.Parameters, writer);
+ // add ~ for conversion operators
+ if ((name == "op_Implicit") || (name == "op_Explicit")) {
+ writer.Write("~");
+ WriteType(method.ReturnType, writer);
+ }
+
+ }
+
+ // The actual logic to construct names
+
+ private static void WriteNamespace(Namespace space, TextWriter writer) {
+ writer.Write(space.Name);
+ }
+
+ private static void WriteParameters(ParameterList parameters, TextWriter writer) {
+ if ((parameters == null) || (parameters.Count == 0)) return;
+ writer.Write("(");
+ for (int i = 0; i < parameters.Count; i++) {
+ if (i > 0) writer.Write(",");
+ WriteType(parameters[i].Type, writer);
+ }
+ writer.Write(")");
+ }
+
+ private static void WriteProperty(Property property, TextWriter writer) {
+ WriteType(property.DeclaringType, writer);
+ //Console.WriteLine( "{0}::{1}", property.DeclaringType.FullName, property.Name );
+
+ Property eiiProperty = null;
+ if (property.IsPrivate && property.IsVirtual) {
+ Property[] eiiProperties = ReflectionUtilities.GetImplementedProperties(property);
+ if (eiiProperties.Length > 0) eiiProperty = eiiProperties[0];
+ }
+
+
+
+ if (eiiProperty != null) {
+ TypeNode eiiType = eiiProperty.DeclaringType;
+ TextWriter eiiWriter = new StringWriter();
+
+
+ if (eiiType != null && eiiType.Template != null)
+ {
+ writer.Write(".");
+ WriteTemplate(eiiType, writer);
+ }
+ else
+ {
+ WriteType(eiiType, eiiWriter);
+ writer.Write(".");
+ writer.Write(eiiWriter.ToString().Replace('.', '#'));
+ }
+
+ writer.Write("#");
+ writer.Write(eiiProperty.Name.Name);
+ } else {
+ writer.Write(".{0}", property.Name.Name);
+ }
+ ParameterList parameters = property.Parameters;
+ WriteParameters(parameters, writer);
+ }
+
+ private static void WriteStaticConstructor(StaticInitializer constructor, TextWriter writer) {
+ WriteType(constructor.DeclaringType, writer);
+ writer.Write(".#cctor");
+ WriteParameters(constructor.Parameters, writer);
+ }
+
+ /// <summary>
+ /// Used for explicitly implemented interfaces to convert the template to the
+ /// format used in the comments file.
+ /// </summary>
+ /// <param name="type">EII Type</param>
+ /// <param name="writer"></param>
+ private static void WriteTemplate(TypeNode eiiType, TextWriter writer)
+ {
+ string eiiClean = eiiType.Template.ToString();
+ eiiClean = eiiClean.Replace('.', '#');
+ eiiClean = eiiClean.Replace(',', '@'); //change the seperator between params
+ eiiClean = eiiClean.Replace('<', '{'); //change the parameter brackets
+ eiiClean = eiiClean.Replace('>', '}');
+ writer.Write(eiiClean);
+ }
+
+ private static void WriteType(TypeNode type, TextWriter writer) {
+ switch (type.NodeType) {
+ case NodeType.ArrayType:
+ ArrayType array = type as ArrayType;
+ WriteType(array.ElementType, writer);
+ writer.Write("[");
+ if (array.Rank > 1) {
+ for (int i = 0; i < array.Rank; i++) {
+ if (i > 0) writer.Write(",");
+ writer.Write("0:");
+ }
+ }
+ writer.Write("]");
+ break;
+ case NodeType.Reference:
+ Reference reference = type as Reference;
+ TypeNode referencedType = reference.ElementType;
+ WriteType(referencedType, writer);
+ writer.Write("@");
+ break;
+ case NodeType.Pointer:
+ Pointer pointer = type as Pointer;
+ WriteType(pointer.ElementType, writer);
+ writer.Write("*");
+ break;
+ case NodeType.OptionalModifier:
+ TypeModifier optionalModifierClause = type as TypeModifier;
+ WriteType(optionalModifierClause.ModifiedType, writer);
+ writer.Write("!");
+ WriteType(optionalModifierClause.Modifier, writer);
+ break;
+ case NodeType.RequiredModifier:
+ TypeModifier requiredModifierClause = type as TypeModifier;
+ WriteType(requiredModifierClause.ModifiedType, writer);
+ writer.Write("|");
+ WriteType(requiredModifierClause.Modifier, writer);
+ break;
+ default:
+ if (type.IsTemplateParameter) {
+ ITypeParameter gtp = (ITypeParameter)type;
+ if (gtp.DeclaringMember is TypeNode) {
+ writer.Write("`");
+ } else if (gtp.DeclaringMember is Method) {
+ writer.Write("``");
+ } else {
+ throw new InvalidOperationException("Generic parameter not on type or method.");
+ }
+ writer.Write(gtp.ParameterListIndex);
+ } else {
+ // namespace
+ TypeNode declaringType = type.DeclaringType;
+ if (declaringType != null) {
+ // names of nested types begin with outer type name
+ WriteType(declaringType, writer);
+ writer.Write(".");
+ } else {
+ // otherwise just prepend the namespace
+ Identifier space = type.Namespace;
+ if ((space != null) && !String.IsNullOrEmpty(space.Name)) {
+ //string space = type.Namespace.Name;
+ //if (space != null && space.Length > 0) {
+ writer.Write(space.Name);
+ writer.Write(".");
+ }
+ }
+ // name
+ writer.Write(type.GetUnmangledNameWithoutTypeParameters());
+ // generic parameters
+ if (type.IsGeneric) {
+ // number of parameters
+ TypeNodeList parameters = type.TemplateParameters;
+ if (parameters != null) {
+ writer.Write("`{0}", parameters.Count);
+ }
+ // arguments
+ TypeNodeList arguments = type.TemplateArguments;
+ if ((arguments != null) && (arguments.Count > 0)) {
+ writer.Write("{");
+ for (int i = 0; i < arguments.Count; i++) {
+ TypeNode argument = arguments[i];
+ if (i > 0) writer.Write(",");
+ WriteType(arguments[i], writer);
+ }
+ writer.Write("}");
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/Reflection/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a18dd70
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/Properties/AssemblyInfo.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Reflection")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Reflection")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2006")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: System.CLSCompliant(false)]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("649c6153-4fdf-419d-96d3-236bae5d5749")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("2.5.10626.00")]
+[assembly: AssemblyFileVersion("2.5.10626.00")]
diff --git a/tools/Sandcastle/Source/Reflection/Reflection.cs b/tools/Sandcastle/Source/Reflection/Reflection.cs
new file mode 100644
index 0000000..e646cc6
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/Reflection.cs
@@ -0,0 +1,298 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public static class ReflectionUtilities {
+
+ public static Event[] GetImplementedEvents(Event trigger) {
+ List < Event > list = new List < Event >();
+
+ // get the adder
+ Method adder = trigger.HandlerAdder;
+
+ // get interface methods corresponding to this adder
+ Method[] implementedAdders = GetImplementedMethods(adder);
+
+ // get the events corresponding to the implemented adders
+ foreach (Method implementedAdder in implementedAdders) {
+ Event implementedTrigger = GetEventFromAdder(implementedAdder);
+ if (implementedTrigger != null) list.Add(implementedTrigger);
+ }
+
+ return (list.ToArray());
+
+ }
+
+ public static Method[] GetImplementedMethods(Method method) {
+ List < Method > list = new List < Method >();
+
+ // Explicit implementations
+ MethodList explicitImplementations = method.ImplementedInterfaceMethods;
+ if (explicitImplementations != null) {
+ for (int i = 0; i < explicitImplementations.Count; i++) {
+ Method explicitImplementation = explicitImplementations[i];
+ list.Add(explicitImplementation);
+ }
+ }
+
+ // Implicit implementations
+ MethodList implicitImplementations = method.ImplicitlyImplementedInterfaceMethods;
+ if (implicitImplementations != null) {
+ for (int i = 0; i < implicitImplementations.Count; i++) {
+ Method implicitImplementation = implicitImplementations[i];
+ list.Add(implicitImplementation);
+ }
+ }
+
+ return (list.ToArray());
+ }
+
+ public static Property[] GetImplementedProperties(Property property) {
+ List < Property > list = new List < Property >();
+
+ // get an accessor
+ Method accessor = property.Getter;
+ if (accessor == null) accessor = property.Setter;
+ if (accessor == null) return (new Property[0]);
+
+ // get the interface methods corresponding to this accessor
+ Method[] methods = GetImplementedMethods(accessor);
+
+ // look for properties corresponding to these methods
+ for (int i = 0; i < methods.Length; i++) {
+ Method method = methods[i];
+ Property entry = GetPropertyFromAccessor(method);
+ if (entry != null) list.Add(entry);
+ }
+
+ return (list.ToArray());
+ }
+
+ public static Namespace GetNamespace(TypeNode type) {
+ if (type.DeclaringType != null) {
+ return (GetNamespace(type.DeclaringType));
+ } else {
+ return (new Namespace(type.Namespace));
+ }
+ }
+
+ public static Member GetTemplateMember(Member member) {
+
+ if (member == null) throw new ArgumentNullException("member");
+
+ // if the containing type isn't generic, the member is the template member
+ TypeNode type = member.DeclaringType;
+ if (!type.IsGeneric) return (member);
+
+ // if the containing type isn't specialized, the member is the template member
+ if (!IsSpecialized(type)) return (member);
+
+ // get the template type, and look for members with the same name
+ TypeNode template = ReflectionUtilities.GetTemplateType(member.DeclaringType);
+ Identifier name = member.Name;
+ MemberList candidates = template.GetMembersNamed(name);
+
+ // if no candidates, say so (this shouldn't happen)
+ if (candidates.Count == 0) throw new InvalidOperationException("No members in the template had the name found in the specialization. This is not possible, but apparently it happened.");
+
+ // if only one candidate, return it
+ if (candidates.Count == 1) return (candidates[0]);
+
+ // multiple candidates, so now we need to compare parameters
+ ParameterList parameters = GetParameters(member);
+
+ for (int i = 0; i < candidates.Count; i++) {
+ Member candidate = candidates[i];
+
+ // candidate must be same kind of node
+ if (candidate.NodeType != member.NodeType) continue;
+
+ // if parameters match, this is the one
+ if (ParametersMatch(parameters, GetParameters(candidate))) return (candidate);
+
+ }
+
+ Console.WriteLine(member.DeclaringType.FullName);
+ Console.WriteLine(member.FullName);
+ throw new InvalidOperationException("No members in the template matched the parameters of the specialization. This is not possible.");
+ }
+
+ public static TypeNode GetTemplateType(TypeNode type) {
+
+ if (type == null) throw new ArgumentNullException("type");
+ // Console.WriteLine(type.FullName);
+
+ // only generic types have templates
+ if (!type.IsGeneric) return (type);
+
+ if (type.DeclaringType == null) {
+ // if the type is not nested, life is simpler
+
+ // if the type is not specified, the type is the template
+ if (type.TemplateArguments == null) return (type);
+
+ // otherwise, construct the template type identifier and use it to fetch the template type
+ Module templateModule = type.DeclaringModule;
+ Identifier name = new Identifier(String.Format("{0}`{1}", type.GetUnmangledNameWithoutTypeParameters(), type.TemplateArguments.Count));
+ Identifier space = type.Namespace;
+ TypeNode template = templateModule.GetType(space, name);
+ return (template);
+ } else {
+ // if the type is nested, life is harder; we have to walk up the chain, constructing
+ // un-specialized identifiers as we go, then walk back down the chain, fetching
+ // template types as we go
+
+ // create a stack to keep track of identifiers
+ Stack < Identifier > identifiers = new Stack < Identifier >();
+
+ // populate the stack with the identifiers of all the types up to the outermost type
+ TypeNode current = type;
+ while (true) {
+ int count = 0;
+ if ((current.TemplateArguments != null) && (current.TemplateArguments.Count > count)) count = current.TemplateArguments.Count;
+ if ((current.TemplateParameters != null) && (current.TemplateParameters.Count > count)) count = current.TemplateParameters.Count;
+ TypeNodeList arguments = current.TemplateParameters;
+ if (count == 0) {
+ identifiers.Push(new Identifier(current.GetUnmangledNameWithoutTypeParameters()));
+ } else {
+ identifiers.Push(new Identifier(String.Format("{0}`{1}", current.GetUnmangledNameWithoutTypeParameters(), count)));
+ }
+ // Console.WriteLine("U {0} {1}", identifiers.Peek(), CountArguments(current));
+ if (current.DeclaringType == null) break;
+ current = current.DeclaringType;
+ }
+
+ // fetch a TypeNode representing that outermost type
+ Module module = current.DeclaringModule;
+ Identifier space = current.Namespace;
+ current = module.GetType(space, identifiers.Pop());
+
+ // move down the stack to the inner type we want
+ while (identifiers.Count > 0) {
+ current = (TypeNode)current.GetMembersNamed(identifiers.Pop())[0];
+ // Console.WriteLine("D {0} {1}", current.GetFullUnmangledNameWithTypeParameters(), CountArguments(current));
+ }
+
+ // whew, finally we've got it
+ return (current);
+ }
+
+ }
+
+ public static bool IsDefaultMember(Member member) {
+
+ if (member == null) throw new ArgumentNullException("member");
+ TypeNode type = member.DeclaringType;
+
+ MemberList defaultMembers = type.DefaultMembers;
+ for (int i = 0; i < defaultMembers.Count; i++) {
+ Member defaultMember = defaultMembers[i];
+ if (member == defaultMember) return (true);
+ }
+ return (false);
+
+ }
+
+ private static Event GetEventFromAdder(Method adder) {
+ if (adder == null) throw new ArgumentNullException("adder");
+ TypeNode type = adder.DeclaringType;
+ MemberList members = type.Members;
+ foreach (Member member in members) {
+ if (member.NodeType != NodeType.Event) continue;
+ Event trigger = member as Event;
+ if (trigger.HandlerAdder == adder) return (trigger);
+ }
+ return (null);
+ }
+
+ private static ParameterList GetParameters(Member member) {
+ Method method = member as Method;
+ if (method != null) return (method.Parameters);
+
+ Property property = member as Property;
+ if (property != null) return (property.Parameters);
+
+ return (new ParameterList());
+ }
+
+ private static Property GetPropertyFromAccessor(Method accessor) {
+ if (accessor == null) throw new ArgumentNullException("accessor");
+ TypeNode type = accessor.DeclaringType;
+ MemberList members = type.Members;
+ foreach (Member member in members) {
+ if (member.NodeType != NodeType.Property) continue;
+ Property property = member as Property;
+ if (property.Getter == accessor) return (property);
+ if (property.Setter == accessor) return (property);
+ }
+ return (null);
+ }
+
+ private static bool IsSpecialized(TypeNode type) {
+ for (TypeNode t = type; t != null; t = t.DeclaringType) {
+ TypeNodeList templates = t.TemplateArguments;
+ if ((templates != null) && (templates.Count > 0)) return (true);
+ }
+ return (false);
+ }
+
+ // parameters1 should be fully specialized; parameters2
+
+ private static bool ParametersMatch(ParameterList parameters1, ParameterList parameters2) {
+
+ if (parameters1.Count != parameters2.Count) return (false);
+
+ for (int i = 0; i < parameters1.Count; i++) {
+ TypeNode type1 = parameters1[i].Type;
+ TypeNode type2 = parameters2[i].Type;
+
+ // we can't determine the equivilence of template parameters; this is probably not good
+ if (type1.IsTemplateParameter || type2.IsTemplateParameter) continue;
+
+ // the node type must be the same; this is probably a fast check
+ if (type1.NodeType != type2.NodeType) return (false);
+
+ // if they are "normal" types, we will compare them
+ // comparing arrays, pointers, etc. is dangerous, because the types they contian may be template parameters
+ if ((type1.NodeType == NodeType.Class) || (type1.NodeType == NodeType.Struct) || (type1.NodeType == NodeType.Interface) ||
+ (type1.NodeType == NodeType.EnumNode) || (type1.NodeType == NodeType.DelegateNode)) {
+ type1 = GetTemplateType(type1);
+ type2 = GetTemplateType(type2);
+ if (!type2.IsStructurallyEquivalentTo(type1)) {
+ // Console.WriteLine("{0} !~ {1}", type1.FullName, type2.FullName);
+ return (false);
+ } else {
+ // Console.WriteLine("{0} ~ {1}", type1.FullName, type2.FullName);
+ }
+ }
+
+ }
+
+ return (true);
+ }
+
+ private static bool TypeMatch(TypeNode type1, TypeNode type2) {
+
+ // the two types must be of the same kind
+ if (type1.NodeType != type2.NodeType) return (false);
+
+ if (type1.NodeType == NodeType.ArrayType) {
+ // they are arrays, so check elements
+ ArrayType array1 = (ArrayType)type1;
+ ArrayType array2 = (ArrayType)type2;
+ return (TypeMatch(array1.ElementType, array2.ElementType));
+ } else {
+ // they are normal types
+ return (type1.IsStructurallyEquivalentTo(type2));
+ }
+ }
+
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/Reflection.csproj b/tools/Sandcastle/Source/Reflection/Reflection.csproj
new file mode 100644
index 0000000..9a88afa
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/Reflection.csproj
@@ -0,0 +1,107 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{74F5EB3F-DC99-4FBE-9495-EE378FC60F65}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Reflection</RootNamespace>
+ <AssemblyName>Reflection</AssemblyName>
+ <SccProjectName>
+ </SccProjectName>
+ <SccLocalPath>
+ </SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>
+ </SccProvider>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'WebDocsDebug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\WebDocsDebug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Sandcastle|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Sandcastle\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+ <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AllDocumentedFilter.cs" />
+ <Compile Include="AllTopicFilter.cs" />
+ <Compile Include="ApiFilter.cs" />
+ <Compile Include="ApiNamer.cs" />
+ <Compile Include="ApiVisitor.cs" />
+ <Compile Include="AssemblyReferenceEventArgs.cs" />
+ <Compile Include="AssemblyResolver.cs" />
+ <Compile Include="ExternalDocumentedFilter.cs" />
+ <Compile Include="ExternalFilter.cs" />
+ <Compile Include="ExternalTopicFilter.cs" />
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="MemberFilter.cs" />
+ <Compile Include="NamespaceFilter.cs" />
+ <Compile Include="NoFilter.cs" />
+ <Compile Include="OrcasNamer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Reflection.cs" />
+ <Compile Include="RootFilter.cs" />
+ <Compile Include="TestResolver.cs" />
+ <Compile Include="TypeFilter.cs" />
+ <Compile Include="WhidbeyNamer.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CCI\CCI.csproj">
+ <Project>{4CB332D6-976E-44F6-A320-A515A9D1D1D3}</Project>
+ <Name>CCI</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- Copy the output assemblies to a common binaries directory (ProductionTools). -->
+ <Target Name="AfterBuild">
+ <CreateItem Include="$(OutputPath)\$(AssemblyName).*">
+ <Output TaskParameter="Include" ItemName="ProductionFiles" />
+ </CreateItem>
+ <Copy SourceFiles="@(ProductionFiles)" DestinationFolder="..\..\ProductionTools" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/tools/Sandcastle/Source/Reflection/RootFilter.cs b/tools/Sandcastle/Source/Reflection/RootFilter.cs
new file mode 100644
index 0000000..63401a5
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/RootFilter.cs
@@ -0,0 +1,126 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class RootFilter
+ {
+
+#region Member Variables
+ private bool exposed;
+
+ private List < NamespaceFilter > namespaceFilters = new List < NamespaceFilter >();
+#endregion
+
+#region Constructors
+
+ public RootFilter(bool exposed) {
+ this.exposed = exposed;
+ }
+
+ public RootFilter(XmlReader configuration) {
+ exposed = Convert.ToBoolean(configuration.GetAttribute("expose"));
+ XmlReader subtree = configuration.ReadSubtree();
+ while (subtree.Read()) {
+ if ((subtree.NodeType == XmlNodeType.Element) && (subtree.Name == "namespace")) {
+ NamespaceFilter namespaceFilter = new NamespaceFilter(subtree);
+ namespaceFilters.Add(namespaceFilter);
+ }
+ }
+ subtree.Close();
+ }
+#endregion
+
+#region Public API
+
+ /// <summary>
+ /// Gets the exposed value from the config
+ /// </summary>
+ public bool ExposedFilterSetting
+ {
+ get
+ {
+ return exposed;
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of namespace filters
+ /// </summary>
+ public int NamespaceFilterCount
+ {
+ get
+ {
+ return namespaceFilters.Count;
+ }
+ }
+
+ public List < NamespaceFilter > NamespaceFilters {
+ get {
+ return (namespaceFilters);
+ }
+ }
+
+ //Find out if any are exposed incase this class is not exposed
+ public bool HasExposedMembers(TypeNode type)
+ {
+ foreach (NamespaceFilter namespaceFilter in namespaceFilters)
+ {
+ bool? result = namespaceFilter.IsExposedType(type);
+ if (result != null)
+ {
+ return namespaceFilter.HasExposedMembers(type);
+ }
+ }
+ return false;
+ }
+
+ public bool IsExposedApi(Member api) {
+
+ Namespace space = api as Namespace;
+ if (space != null) return (IsExposedNamespace(space));
+
+ TypeNode type = api as TypeNode;
+ if (type != null) return (IsExposedType(type));
+
+ return (IsExposedMember(api));
+
+ }
+
+
+ public bool IsExposedMember(Member member) {
+ //Console.WriteLine("DEBUG: root.IsExposedMember");
+ foreach (NamespaceFilter namespaceFilter in namespaceFilters) {
+ bool? result = namespaceFilter.IsExposedMember(member);
+ if (result != null) return ((bool)result);
+ }
+ return (exposed);
+ }
+
+ public bool IsExposedNamespace(Namespace space) {
+ foreach (NamespaceFilter namespaceFilter in namespaceFilters) {
+ bool? result = namespaceFilter.IsExposedNamespace(space);
+ if (result != null) return ((bool)result);
+ }
+ return (exposed);
+ }
+
+ public bool IsExposedType(TypeNode type) {
+ foreach (NamespaceFilter namespaceFilter in namespaceFilters) {
+ bool? result = namespaceFilter.IsExposedType(type);
+ if (result != null) return ((bool)result);
+ }
+
+ return (exposed);
+ }
+
+#endregion
+ }
+}
diff --git a/tools/Sandcastle/Source/Reflection/TestResolver.cs b/tools/Sandcastle/Source/Reflection/TestResolver.cs
new file mode 100644
index 0000000..5ad9c46
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/TestResolver.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class TestResolver : AssemblyResolver {
+
+ public TestResolver(XPathNavigator configuration) : base(configuration) { }
+
+ public override AssemblyNode ResolveReference(AssemblyReference reference, Module module) {
+ Console.WriteLine("test resolver: {0}", reference.StrongName);
+ return (base.ResolveReference(reference, module));
+ }
+ }
+
+}
diff --git a/tools/Sandcastle/Source/Reflection/TypeFilter.cs b/tools/Sandcastle/Source/Reflection/TypeFilter.cs
new file mode 100644
index 0000000..de7a3fa
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/TypeFilter.cs
@@ -0,0 +1,120 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using System.Xml.XPath;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class TypeFilter
+ {
+
+#region Member Variables
+
+ private bool exposed;
+
+ private List < MemberFilter > memberFilters = new List < MemberFilter >();
+
+ private string name;
+
+#endregion
+
+#region Constructors
+ public TypeFilter(string name, bool exposed) {
+ if (name == null) throw new ArgumentNullException("name");
+ this.name = name;
+ this.exposed = exposed;
+ }
+
+ public TypeFilter(XmlReader configuration) {
+ if ((configuration.NodeType != XmlNodeType.Element) || (configuration.Name != "type")) throw new InvalidOperationException();
+ name = configuration.GetAttribute("name");
+ exposed = Convert.ToBoolean(configuration.GetAttribute("expose"));
+ XmlReader subtree = configuration.ReadSubtree();
+ while (subtree.Read()) {
+ if ((subtree.NodeType == XmlNodeType.Element) && (subtree.Name == "member")) {
+ MemberFilter memberFilter = new MemberFilter(subtree);
+ memberFilters.Add(memberFilter);
+ }
+ }
+ subtree.Close();
+ }
+#endregion
+
+#region Public API
+
+ //Find out if any are exposed incase this class is not exposed
+ public bool HasExposedMembers(TypeNode type)
+ {
+ foreach (Member member in type.Members)
+ foreach (MemberFilter memberFilter in memberFilters)
+ if (memberFilter.IsExposedMember(member) == true)
+ return true;
+
+ return false;
+ }
+
+
+ public bool? IsExposedMember(Member member) {
+ //Console.WriteLine("DEBUG: typeFilter.IsExposedMember");
+ TypeNode type = ReflectionUtilities.GetTemplateType(member.DeclaringType);
+ if (IsExposedType(type) != null) {
+ foreach (MemberFilter memberFilter in memberFilters) {
+ bool? result = memberFilter.IsExposedMember(member);
+ if (result != null) return (result);
+ }
+
+ return (exposed); //return the type's exposed setting
+ } else {
+ return (null);
+ }
+ }
+
+ /**
+ * <summary>IsExposedType compares the given type to itself. If this filter
+ * contains a '.' designating it as for a nested class it will skip
+ * non-nested classes. Classes with no declaring types will not be compared to
+ * filters with a '.'
+ * </summary>
+ */
+ public bool? IsExposedType(TypeNode type)
+ {
+ bool? typeIsExposed = null;
+
+ //check if the type was nested
+ if (type.DeclaringType == null)
+ {
+ if (type.Name.Name == name)
+ typeIsExposed = exposed;
+ }
+ //if we are nested then check if this filter is for a nested class
+ //check that nothing used is null also.
+ //if the name attribute is not there in the config name can be null here.
+ else if (name != null && name.Contains("."))
+ {
+ //Get a stack of declaring type names
+ Stack < string > parentNames = new Stack < string >();
+ parentNames.Push(type.Name.Name); //start with this one
+
+ TypeNode parent = type.DeclaringType;
+ while (parent != null)
+ {
+ parentNames.Push(parent.Name.Name);
+ parent = parent.DeclaringType;
+ }
+
+ //put them back in the correct order and check the name
+ if (name.Equals(String.Join(".", parentNames.ToArray())))
+ typeIsExposed = exposed;
+ }
+
+ return typeIsExposed;
+ }
+
+#endregion
+ }
+}
diff --git a/tools/Sandcastle/Source/Reflection/WhidbeyNamer.cs b/tools/Sandcastle/Source/Reflection/WhidbeyNamer.cs
new file mode 100644
index 0000000..f6234a8
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/WhidbeyNamer.cs
@@ -0,0 +1,275 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+using System.Compiler;
+
+namespace Microsoft.Ddue.Tools.Reflection {
+
+ public class WhidbeyNamer : ApiNamer {
+
+ public override string GetMemberName(Member member) {
+
+ using (TextWriter writer = new StringWriter()) {
+
+ switch (member.NodeType) {
+ case NodeType.Field:
+ writer.Write("F:");
+ WriteField((Field)member, writer);
+ break;
+ case NodeType.Property:
+ writer.Write("P:");
+ WriteProperty((Property)member, writer);
+ break;
+ case NodeType.Method:
+ writer.Write("M:");
+ WriteMethod((Method)member, writer);
+ break;
+ case NodeType.InstanceInitializer:
+ writer.Write("M:");
+ WriteConstructor((InstanceInitializer)member, writer);
+ break;
+ case NodeType.StaticInitializer:
+ writer.Write("M:");
+ WriteStaticConstructor((StaticInitializer)member, writer);
+ break;
+ case NodeType.Event:
+ writer.Write("E:");
+ WriteEvent((Event)member, writer);
+ break;
+ }
+
+ return (writer.ToString());
+
+ }
+
+ }
+
+ public override string GetNamespaceName(Namespace space) {
+ using (TextWriter writer = new StringWriter()) {
+ writer.Write("N:");
+ WriteNamespace(space, writer);
+ return (writer.ToString());
+ }
+ }
+
+ public override string GetTypeName(TypeNode type) {
+ using (TextWriter writer = new StringWriter()) {
+ writer.Write("T:");
+ WriteType(type, writer);
+ return (writer.ToString());
+ }
+ }
+
+
+ private static string GetName(Member entity) {
+
+ using (TextWriter writer = new StringWriter()) {
+
+ TypeNode type = entity as TypeNode;
+ if (type != null) {
+ writer.Write("T:");
+ WriteType(type, writer);
+ return (writer.ToString());
+ }
+
+ switch (entity.NodeType) {
+ case NodeType.Namespace:
+ writer.Write("N:");
+ WriteNamespace(entity as Namespace, writer);
+ break;
+ case NodeType.Field:
+ writer.Write("F:");
+ WriteField(entity as Field, writer);
+ break;
+ case NodeType.Property:
+ writer.Write("P:");
+ WriteProperty(entity as Property, writer);
+ break;
+ case NodeType.Method:
+ writer.Write("M:");
+ WriteMethod(entity as Method, writer);
+ break;
+ case NodeType.InstanceInitializer:
+ writer.Write("M:");
+ WriteConstructor(entity as InstanceInitializer, writer);
+ break;
+ case NodeType.StaticInitializer:
+ writer.Write("M:");
+ WriteStaticConstructor(entity as StaticInitializer, writer);
+ break;
+ case NodeType.Event:
+ writer.Write("E:");
+ WriteEvent(entity as Event, writer);
+ break;
+ }
+
+ return (writer.ToString());
+
+ }
+
+ }
+
+ private static void WriteConstructor(InstanceInitializer constructor, TextWriter writer) {
+ WriteType(constructor.DeclaringType, writer);
+ writer.Write(".#ctor");
+ WriteParameters(constructor.Parameters, writer);
+ }
+
+ private static void WriteEvent(Event trigger, TextWriter writer) {
+ WriteType(trigger.DeclaringType, writer);
+ writer.Write(".{0}", trigger.Name.Name);
+ }
+
+ private static void WriteField(Field field, TextWriter writer) {
+ WriteType(field.DeclaringType, writer);
+ writer.Write(".{0}", field.Name.Name);
+ }
+
+ private static void WriteMethod(Method method, TextWriter writer) {
+ string name = method.Name.Name;
+ WriteType(method.DeclaringType, writer);
+ writer.Write(".{0}", name);
+ if (method.IsGeneric) {
+ TypeNodeList genericParameters = method.TemplateParameters;
+ if (genericParameters != null) {
+ writer.Write("``{0}", genericParameters.Count);
+ }
+ }
+ WriteParameters(method.Parameters, writer);
+ // add ~ for conversion operators
+ if ((name == "op_Implicit") || (name == "op_Explicit")) {
+ writer.Write("~");
+ WriteType(method.ReturnType, writer);
+ }
+
+ }
+
+ // The actual logic to construct names
+
+ private static void WriteNamespace(Namespace space, TextWriter writer) {
+ writer.Write(space.Name);
+ }
+
+ private static void WriteParameters(ParameterList parameters, TextWriter writer) {
+ if ((parameters == null) || (parameters.Count == 0)) return;
+ writer.Write("(");
+ for (int i = 0; i < parameters.Count; i++) {
+ if (i > 0) writer.Write(",");
+ WriteType(parameters[i].Type, writer);
+ }
+ writer.Write(")");
+ }
+
+ private static void WriteProperty(Property property, TextWriter writer) {
+ WriteType(property.DeclaringType, writer);
+ writer.Write(".{0}", property.Name.Name);
+ ParameterList parameters = property.Parameters;
+ WriteParameters(parameters, writer);
+ }
+
+ private static void WriteStaticConstructor(StaticInitializer constructor, TextWriter writer) {
+ WriteType(constructor.DeclaringType, writer);
+ writer.Write(".#cctor");
+ WriteParameters(constructor.Parameters, writer);
+ }
+
+ private static void WriteType(TypeNode type, TextWriter writer) {
+ switch (type.NodeType) {
+ case NodeType.ArrayType:
+ ArrayType array = type as ArrayType;
+ WriteType(array.ElementType, writer);
+ writer.Write("[");
+ for (int i = 1; i < array.Rank; i++) writer.Write(",");
+ writer.Write("]");
+ break;
+ case NodeType.Reference:
+ Reference reference = type as Reference;
+ TypeNode referencedType = reference.ElementType;
+ WriteType(referencedType, writer);
+
+ // DocStudio fails to add @ to template parameters or arrays of template
+ // parameters, so we have to mirror this bizarre behavior here
+ bool writeAt = true;
+ if (referencedType.IsTemplateParameter) writeAt = false;
+ if (referencedType.NodeType == NodeType.ArrayType) {
+ ArrayType referencedArray = referencedType as ArrayType;
+ if (referencedArray.ElementType.IsTemplateParameter) writeAt = false;
+ }
+ if (writeAt) writer.Write("@");
+ break;
+ case NodeType.Pointer:
+ Pointer pointer = type as Pointer;
+ WriteType(pointer.ElementType, writer);
+ writer.Write("*");
+ break;
+ case NodeType.OptionalModifier:
+ TypeModifier optionalModifierClause = type as TypeModifier;
+ WriteType(optionalModifierClause.ModifiedType, writer);
+ writer.Write("!");
+ WriteType(optionalModifierClause.Modifier, writer);
+ break;
+ case NodeType.RequiredModifier:
+ TypeModifier requiredModifierClause = type as TypeModifier;
+ WriteType(requiredModifierClause.ModifiedType, writer);
+ writer.Write("|");
+ WriteType(requiredModifierClause.Modifier, writer);
+ break;
+ default:
+ if (type.IsTemplateParameter) {
+ ITypeParameter gtp = (ITypeParameter)type;
+ if (gtp.DeclaringMember is TypeNode) {
+ writer.Write("`");
+ } else if (gtp.DeclaringMember is Method) {
+ writer.Write("``");
+ } else {
+ throw new InvalidOperationException("Generic parameter not on type or method.");
+ }
+ writer.Write(gtp.ParameterListIndex);
+ } else {
+ // namespace
+ TypeNode declaringType = type.DeclaringType;
+ if (declaringType != null) {
+ // names of nested types begin with outer type name
+ WriteType(declaringType, writer);
+ writer.Write(".");
+ } else {
+ // otherwise just prepend the namespace
+ string space = type.Namespace.Name;
+ if (space != null && space.Length > 0) {
+ writer.Write(space);
+ writer.Write(".");
+ }
+ }
+ // name
+ writer.Write(type.GetUnmangledNameWithoutTypeParameters());
+ // generic parameters
+ if (type.IsGeneric) {
+ // number of parameters
+ TypeNodeList parameters = type.TemplateParameters;
+ if (parameters != null) {
+ writer.Write("`{0}", parameters.Count);
+ }
+ // arguments
+ TypeNodeList arguments = type.TemplateArguments;
+ if ((arguments != null) && (arguments.Count > 0)) {
+ writer.Write("{");
+ for (int i = 0; i < arguments.Count; i++) {
+ TypeNode argument = arguments[i];
+ if (i > 0) writer.Write(",");
+ WriteType(arguments[i], writer);
+ }
+ writer.Write("}");
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ }
+
+}