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;
}
}
}
}