diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-09-20 21:18:59 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-09-21 08:06:22 -0700 |
commit | bbe3f9cc9c8a1e5909273c1a162a63ea7a66afd8 (patch) | |
tree | c91f66e642c4d26fca266e226b3f2765f546d700 /tools/Sandcastle/Source/Reflection/ApiVisitor.cs | |
parent | 627014f0bbc3fd576277375e70f8391d150b0a67 (diff) | |
download | DotNetOpenAuth-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.cs | 333 |
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]); + } + } + + } + + +} |