using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using Mono.Cecil; namespace Mono.Documentation { /// /// Represents a set of assemblies that we want to document /// class AssemblySet : IDisposable { readonly DefaultAssemblyResolver resolver = new DefaultAssemblyResolver (); HashSet assemblyPaths = new HashSet (); HashSet assemblySearchPaths = new HashSet (); HashSet forwardedTypes = new HashSet (); public AssemblySet (string path) : this (new string[] { path }) { } public AssemblySet (IEnumerable paths) : this ("Default", paths, new string[0]) { } public AssemblySet (string name, IEnumerable paths, IEnumerable resolverSearchPaths) { Name = name; foreach (var path in paths) assemblyPaths.Add (path); // add default search paths var assemblyDirectories = paths .Where (p => p.Contains (Path.DirectorySeparatorChar)) .Select (p => Path.GetDirectoryName (p)); foreach (var searchPath in resolverSearchPaths.Union(assemblyDirectories)) assemblySearchPaths.Add (searchPath); char oppositeSeparator = Path.DirectorySeparatorChar == '/' ? '\\' : '/'; Func sanitize = p => p.Replace (oppositeSeparator, Path.DirectorySeparatorChar); foreach (var searchPath in assemblySearchPaths.Select(sanitize)) resolver.AddSearchDirectory (searchPath); } public string Name { get; private set; } public IEnumerable Assemblies { get { return this.LoadAllAssemblies ().Where(a => a != null); } } public IEnumerable AssemblyPaths { get { return this.assemblyPaths; } } /// true, if in set was contained in the set of assemblies, false otherwise. /// An assembly file name public bool Contains (string name) { return assemblyPaths.Any (p => Path.GetFileName (p) == name); } /// Tells whether an already enumerated AssemblyDefinition, contains the type. /// Type name public bool ContainsForwardedType (string name) { return forwardedTypes.Contains (name); } public void Dispose () => resolver.Dispose (); public override string ToString () { return string.Format ("[AssemblySet: Name={0}, Assemblies={1}]", Name, assemblyPaths.Count); } IEnumerable LoadAllAssemblies () { foreach (var path in this.assemblyPaths) { var assembly = MDocUpdater.Instance.LoadAssembly (path, this.resolver); if (assembly != null) { foreach (var type in assembly.MainModule.ExportedTypes.Where (t => t.IsForwarder).Select (t => t.FullName)) forwardedTypes.Add (type); } yield return assembly; } } } }