summaryrefslogtreecommitdiffstats
path: root/tools/Sandcastle/Source/Reflection/ApiVisitor.cs
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-09-20 21:18:59 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-09-21 08:06:22 -0700
commitbbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8 (patch)
treec91f66e642c4d26fca266e226b3f2765f546d700 /tools/Sandcastle/Source/Reflection/ApiVisitor.cs
parent627014f0bbc3fd576277375e70f8391d150b0a67 (diff)
downloadDotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.zip
DotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.tar.gz
DotNetOpenAuth-bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8.tar.bz2
Switched out the Sandcastle binaries for the source code.
Diffstat (limited to 'tools/Sandcastle/Source/Reflection/ApiVisitor.cs')
-rw-r--r--tools/Sandcastle/Source/Reflection/ApiVisitor.cs333
1 files changed, 333 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/Reflection/ApiVisitor.cs b/tools/Sandcastle/Source/Reflection/ApiVisitor.cs
new file mode 100644
index 0000000..8fef266
--- /dev/null
+++ b/tools/Sandcastle/Source/Reflection/ApiVisitor.cs
@@ -0,0 +1,333 @@
+// 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 virtual void Dispose() {
+ 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.Length];
+ for (int i = 0; i < members.Length; 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.Length];
+ for (int i = 0; i < spaces.Length; 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.Length];
+ for (int i = 0; i < types.Length; 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.Length; 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.Length; i++) {
+ StoreType(types[i]);
+ }
+ }
+
+ }
+
+
+}