You've already forked linux-packaging-mono
Imported Upstream version 6.6.0.89
Former-commit-id: b39a328747c2f3414dc52e009fb6f0aa80ca2492
This commit is contained in:
parent
cf815e07e0
commit
95fdb59ea6
217
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/AssemblySet.cs
vendored
Normal file
217
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/AssemblySet.cs
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Mono.Documentation.Updater.Frameworks
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a set of assemblies that we want to document
|
||||
/// </summary>
|
||||
public class AssemblySet : IDisposable
|
||||
{
|
||||
BaseAssemblyResolver resolver = new Frameworks.MDocResolver ();
|
||||
CachedResolver cachedResolver;
|
||||
IMetadataResolver metadataResolver;
|
||||
|
||||
HashSet<string> assemblyPaths = new HashSet<string> ();
|
||||
Dictionary<string, bool> assemblyPathsMap = new Dictionary<string, bool> ();
|
||||
HashSet<string> assemblySearchPaths = new HashSet<string> ();
|
||||
HashSet<string> forwardedTypes = new HashSet<string> ();
|
||||
IEnumerable<string> importPaths;
|
||||
public IEnumerable<DocumentationImporter> Importers { get; private set; }
|
||||
|
||||
FrameworkEntry fx;
|
||||
public FrameworkEntry Framework
|
||||
{
|
||||
get => fx;
|
||||
set
|
||||
{
|
||||
fx = value;
|
||||
fx.AddAssemblySet (this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>This is meant only for unit test access</summary>
|
||||
public IDictionary<string, bool> AssemblyMapsPath
|
||||
{
|
||||
get => assemblyPathsMap;
|
||||
}
|
||||
|
||||
private IDictionary<string, HashSet<MDocResolver.TypeForwardEventArgs>> forwardedTypesTo = new Dictionary<string, HashSet<MDocResolver.TypeForwardEventArgs>> ();
|
||||
|
||||
|
||||
public AssemblySet (IEnumerable<string> paths) : this ("Default", paths, new string[0]) { }
|
||||
|
||||
public AssemblySet (string name, IEnumerable<string> paths, IEnumerable<string> resolverSearchPaths, IEnumerable<string> imports = null, string version = null, string id = null)
|
||||
{
|
||||
cachedResolver = cachedResolver ?? new CachedResolver (resolver);
|
||||
metadataResolver = metadataResolver ?? new Frameworks.MDocMetadataResolver (cachedResolver);
|
||||
((MDocResolver)resolver).TypeExported += (sender, e) =>
|
||||
{
|
||||
TrackTypeExported (e);
|
||||
};
|
||||
|
||||
Name = name;
|
||||
Version = version;
|
||||
Id = id;
|
||||
|
||||
foreach (var path in paths)
|
||||
{
|
||||
assemblyPaths.Add (path);
|
||||
string pathName = Path.GetFileName (path);
|
||||
if (!assemblyPathsMap.ContainsKey (pathName))
|
||||
assemblyPathsMap.Add (pathName, true);
|
||||
}
|
||||
|
||||
// add default search paths
|
||||
var assemblyDirectories = paths
|
||||
.Where (p => p.Contains (Path.DirectorySeparatorChar))
|
||||
.Select (p => Path.GetDirectoryName (p));
|
||||
|
||||
foreach (var searchPath in assemblyDirectories.Union(resolverSearchPaths))
|
||||
assemblySearchPaths.Add (searchPath);
|
||||
|
||||
char oppositeSeparator = Path.DirectorySeparatorChar == '/' ? '\\' : '/';
|
||||
Func<string, string> sanitize = p =>
|
||||
p.Replace (oppositeSeparator, Path.DirectorySeparatorChar);
|
||||
|
||||
foreach (var searchPath in assemblySearchPaths.Select (sanitize))
|
||||
resolver.AddSearchDirectory (searchPath);
|
||||
|
||||
this.importPaths = imports;
|
||||
if (this.importPaths != null)
|
||||
{
|
||||
this.Importers = this.importPaths.Select (p => MDocUpdater.Instance.GetImporter (p, supportsEcmaDoc: false)).ToArray ();
|
||||
}
|
||||
else
|
||||
this.Importers = new DocumentationImporter[0];
|
||||
}
|
||||
|
||||
private void TrackTypeExported (MDocResolver.TypeForwardEventArgs e)
|
||||
{
|
||||
if (e.ForType == null) return;
|
||||
|
||||
// keep track of types that have been exported for this assemblyset
|
||||
if (!forwardedTypesTo.ContainsKey (e.ForType))
|
||||
{
|
||||
forwardedTypesTo.Add (e.ForType, new HashSet<MDocResolver.TypeForwardEventArgs> ());
|
||||
}
|
||||
|
||||
forwardedTypesTo[e.ForType].Add (e);
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
public string Version { get; private set; }
|
||||
public string Id { get; private set; }
|
||||
|
||||
IEnumerable<AssemblyDefinition> assemblies;
|
||||
public IEnumerable<AssemblyDefinition> Assemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.assemblies == null)
|
||||
this.assemblies = this.LoadAllAssemblies ().Where (a => a != null).ToArray ();
|
||||
|
||||
return this.assemblies;
|
||||
}
|
||||
}
|
||||
public IEnumerable<string> AssemblyPaths { get { return this.assemblyPaths; } }
|
||||
|
||||
/// <summary>Adds all subdirectories to the search directories for the resolver to look in.</summary>
|
||||
public void RecurseSearchDirectories ()
|
||||
{
|
||||
var directories = resolver
|
||||
.GetSearchDirectories ()
|
||||
.Select (d => new DirectoryInfo (d))
|
||||
.Where (d => d.Exists)
|
||||
.Select (d => d.FullName)
|
||||
.Distinct ()
|
||||
.ToDictionary (d => d, d => d);
|
||||
|
||||
var subdirs = directories.Keys
|
||||
.SelectMany (d => Directory.GetDirectories (d, ".", SearchOption.AllDirectories))
|
||||
.Where (d => !directories.ContainsKey (d));
|
||||
|
||||
foreach (var dir in subdirs)
|
||||
resolver.AddSearchDirectory (dir);
|
||||
}
|
||||
|
||||
/// <returns><c>true</c>, if in set was contained in the set of assemblies, <c>false</c> otherwise.</returns>
|
||||
/// <param name="name">An assembly file name</param>
|
||||
public bool Contains (string name)
|
||||
{
|
||||
return assemblyPathsMap.ContainsKey (name);//assemblyPaths.Any (p => Path.GetFileName (p) == name);
|
||||
}
|
||||
|
||||
/// <summary>Tells whether an already enumerated AssemblyDefinition, contains the type.</summary>
|
||||
/// <param name="name">Type name</param>
|
||||
public bool ContainsForwardedType (string name)
|
||||
{
|
||||
return forwardedTypes.Contains (name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forwardeds the assemblies.
|
||||
/// </summary>
|
||||
/// <returns>The assemblies.</returns>
|
||||
/// <param name="type">Type.</param>
|
||||
public IEnumerable<AssemblyNameReference> FullAssemblyChain(TypeDefinition type)
|
||||
{
|
||||
if (forwardedTypesTo.ContainsKey (type.FullName))
|
||||
{
|
||||
var list = forwardedTypesTo[type.FullName];
|
||||
var assemblies = (new[] { type.Module.Assembly.Name })
|
||||
.Union (list.Select (f => f.To))
|
||||
.Union (list.Select (f => f.From))
|
||||
.Distinct (anc);
|
||||
return assemblies;
|
||||
}
|
||||
else
|
||||
return new[] { type.Module.Assembly.Name };
|
||||
}
|
||||
|
||||
AssemblyNameComparer anc = new AssemblyNameComparer ();
|
||||
class AssemblyNameComparer : IEqualityComparer<AssemblyNameReference>
|
||||
{
|
||||
public bool Equals (AssemblyNameReference x, AssemblyNameReference y)
|
||||
{
|
||||
return x.FullName.Equals (y.FullName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public int GetHashCode (AssemblyNameReference obj)
|
||||
{
|
||||
return obj.FullName.GetHashCode ();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
this.assemblies = null;
|
||||
cachedResolver?.Dispose();
|
||||
cachedResolver = null;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return string.Format ("[AssemblySet: Name={0}, Assemblies={1}]", Name, assemblyPaths.Count);
|
||||
}
|
||||
|
||||
IEnumerable<AssemblyDefinition> LoadAllAssemblies ()
|
||||
{
|
||||
foreach (var path in this.assemblyPaths) {
|
||||
var assembly = MDocUpdater.Instance.LoadAssembly (path, metadataResolver, cachedResolver);
|
||||
if (assembly != null) {
|
||||
foreach (var type in assembly.MainModule.ExportedTypes.Where (t => t.IsForwarder).Cast<ExportedType>())
|
||||
{
|
||||
forwardedTypes.Add (type.FullName);
|
||||
TrackTypeExported (new MDocResolver.TypeForwardEventArgs (assembly.Name, (AssemblyNameReference)type.Scope, type?.FullName));
|
||||
}
|
||||
}
|
||||
yield return assembly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
118
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FXUtils.cs
vendored
Normal file
118
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FXUtils.cs
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
namespace Mono.Documentation.Updater.Frameworks
|
||||
{
|
||||
public static class FXUtils
|
||||
{
|
||||
public static string AddFXToList (string existingValue, string newFX)
|
||||
{
|
||||
var cachedValue = GetCache (existingValue, newFX, CacheAction.Add);
|
||||
if (!string.IsNullOrWhiteSpace (cachedValue))
|
||||
return cachedValue;
|
||||
|
||||
var splitValue = SplitList (existingValue);
|
||||
if (!splitValue.Contains (newFX)) splitValue.Add (newFX);
|
||||
var returnVal = JoinList (splitValue);
|
||||
|
||||
SetCache (existingValue, newFX, returnVal, CacheAction.Add);
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
public static string RemoveFXFromList (string existingValue, string FXToRemove)
|
||||
{
|
||||
var cachedValue = GetCache (existingValue, FXToRemove, CacheAction.Remove);
|
||||
if (!string.IsNullOrWhiteSpace (cachedValue))
|
||||
return cachedValue;
|
||||
|
||||
var splitValue = SplitList (existingValue);
|
||||
splitValue.Remove (FXToRemove);
|
||||
var returnVal = JoinList (splitValue);
|
||||
|
||||
SetCache (existingValue, FXToRemove, returnVal, CacheAction.Remove);
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
/// <summary>Returns a list of all previously processed frameworks (not including the current)</summary>
|
||||
internal static string PreviouslyProcessedFXString (FrameworkTypeEntry typeEntry)
|
||||
{
|
||||
if (typeEntry == null)
|
||||
return string.Empty;
|
||||
|
||||
return string.Join (";", typeEntry
|
||||
.PreviouslyProcessedFrameworkTypes
|
||||
.Select (previous => previous?.Framework?.Name)
|
||||
.Where (n => !string.IsNullOrWhiteSpace (n))
|
||||
.ToArray ());
|
||||
}
|
||||
|
||||
|
||||
static List<string> SplitList (string existingValue)
|
||||
{
|
||||
existingValue = existingValue ?? string.Empty;
|
||||
|
||||
return existingValue.Split (new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList ();
|
||||
}
|
||||
|
||||
static string JoinList (List<string> splitValue)
|
||||
{
|
||||
return string.Join (";", splitValue.ToArray ());
|
||||
}
|
||||
|
||||
#region Framework String Cache Stuff
|
||||
|
||||
/// <summary>Cache for modified framework strings</summary>
|
||||
static Dictionary<string, ValueTuple<Dictionary<string, string>, Dictionary<string, string>>> map = new Dictionary<string, ValueTuple<Dictionary<string, string>, Dictionary<string, string>>> ();
|
||||
enum CacheAction { Add, Remove }
|
||||
|
||||
static string GetCache (string currentValue, string value, CacheAction action)
|
||||
{
|
||||
ValueTuple<Dictionary<string, string>, Dictionary<string, string>> cacheKey;
|
||||
if (map.TryGetValue (currentValue, out cacheKey))
|
||||
{
|
||||
string cachedValue = string.Empty;
|
||||
switch (action)
|
||||
{
|
||||
case CacheAction.Add:
|
||||
cacheKey.Item1.TryGetValue (value, out cachedValue);
|
||||
break;
|
||||
case CacheAction.Remove:
|
||||
cacheKey.Item2.TryGetValue (value, out cachedValue);
|
||||
break;
|
||||
}
|
||||
return cachedValue;
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
static void SetCache (string currentValue, string value, string newValue, CacheAction action)
|
||||
{
|
||||
ValueTuple<Dictionary<string, string>, Dictionary<string, string>> outerCacheValue;
|
||||
if (!map.TryGetValue (currentValue, out outerCacheValue))
|
||||
{
|
||||
outerCacheValue = new ValueTuple<Dictionary<string, string>, Dictionary<string, string>> (new Dictionary<string, string> (), new Dictionary<string, string> ());
|
||||
map.Add (currentValue, outerCacheValue);
|
||||
}
|
||||
|
||||
Dictionary<string, string> innerCacheContainer = null;
|
||||
switch (action)
|
||||
{
|
||||
case CacheAction.Add:
|
||||
innerCacheContainer = outerCacheValue.Item1;
|
||||
break;
|
||||
case CacheAction.Remove:
|
||||
innerCacheContainer = outerCacheValue.Item2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!innerCacheContainer.ContainsKey (value))
|
||||
{
|
||||
innerCacheContainer.Add (value, newValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
215
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkEntry.cs
vendored
Normal file
215
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkEntry.cs
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Rocks;
|
||||
|
||||
namespace Mono.Documentation.Updater.Frameworks
|
||||
{
|
||||
public class FrameworkEntry
|
||||
{
|
||||
SortedSet<FrameworkTypeEntry> types = new SortedSet<FrameworkTypeEntry> ();
|
||||
|
||||
IList<FrameworkEntry> allcachedframeworks;
|
||||
IList<FrameworkEntry> allframeworks;
|
||||
ISet<AssemblySet> allAssemblies = new SortedSet<AssemblySet> ();
|
||||
|
||||
public int Index = 0;
|
||||
int _fxCount;
|
||||
public int FrameworksCount {
|
||||
get => _fxCount < 1 ? allframeworks.Count : _fxCount;
|
||||
}
|
||||
|
||||
public FrameworkEntry (IList<FrameworkEntry> frameworks, IList<FrameworkEntry> cachedfx) : this(frameworks, -1, cachedfx) {}
|
||||
|
||||
public FrameworkEntry (IList<FrameworkEntry> frameworks, int fxCount, IList<FrameworkEntry> cachedFx)
|
||||
{
|
||||
allframeworks = frameworks;
|
||||
if (allframeworks == null)
|
||||
{
|
||||
allframeworks = new List<FrameworkEntry> (1);
|
||||
allframeworks.Add (this);
|
||||
Index = 0;
|
||||
allcachedframeworks = allframeworks;
|
||||
}
|
||||
else
|
||||
{
|
||||
Index = allframeworks.Count;
|
||||
|
||||
allcachedframeworks = cachedFx;
|
||||
}
|
||||
_fxCount = fxCount;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>Gets a value indicating whether this <see cref="T:Mono.Documentation.Updater.Frameworks.FrameworkEntry"/> is last framework being processed.</summary>
|
||||
public bool IsLastFramework {
|
||||
get => Index == FrameworksCount - 1;
|
||||
}
|
||||
|
||||
/// <param name="assemblyName">should be the assembly name (without version and file extension)</param>
|
||||
public bool IsLastFrameworkForAssembly(string assemblyName)
|
||||
{
|
||||
if (this == Empty) return true;
|
||||
|
||||
var retval = this.allcachedframeworks
|
||||
.Where(f => f.AllProcessedAssemblies
|
||||
.Any(ass => ass.Assemblies
|
||||
.Any(a => a.Name.Name.Equals(assemblyName, StringComparison.OrdinalIgnoreCase))))
|
||||
.ToArray();
|
||||
|
||||
if (!retval.Any ()) return false;
|
||||
|
||||
var lastListed = retval.Last ();
|
||||
return lastListed.Name == this.Name;
|
||||
}
|
||||
|
||||
public bool IsLastFrameworkForType(FrameworkTypeEntry typeEntry)
|
||||
{
|
||||
if (this == Empty) return true;
|
||||
|
||||
var fxlist = this.allcachedframeworks.Where (f => f.FindTypeEntry (typeEntry) != null).ToArray();
|
||||
|
||||
if (!fxlist.Any ()) return false;
|
||||
|
||||
var lastListed = fxlist.Last ();
|
||||
return lastListed.Name == this.Name;
|
||||
}
|
||||
|
||||
public string AllFrameworksWithAssembly(string assemblyName)
|
||||
{
|
||||
if (this == Empty) return this.Name;
|
||||
|
||||
var fxlist = this.allcachedframeworks.Where (f => f.allAssemblies.Any (ass => ass.Assemblies.Any (a => a.Name.Name.Equals (assemblyName, StringComparison.OrdinalIgnoreCase))));
|
||||
return string.Join (";", fxlist.Select (f => f.Name).ToArray ());
|
||||
}
|
||||
|
||||
public string AllFrameworksWithType(FrameworkTypeEntry typeEntry)
|
||||
{
|
||||
if (this == Empty) return this.Name;
|
||||
|
||||
var fxlist = this.allcachedframeworks.Where (f => f.FindTypeEntry (typeEntry) != null);
|
||||
return string.Join (";", fxlist.Select (f => f.Name).ToArray ());
|
||||
}
|
||||
|
||||
string _allFxString = "";
|
||||
public string AllFrameworksString {
|
||||
get
|
||||
{
|
||||
Lazy<string> fxString = new Lazy<string>(() => string.Join (";", allcachedframeworks.Select (f => f.Name).ToArray ()));
|
||||
|
||||
if (!this.IsLastFramework) return fxString.Value;
|
||||
if (string.IsNullOrWhiteSpace(_allFxString))
|
||||
{
|
||||
_allFxString = fxString.Value;
|
||||
}
|
||||
return _allFxString;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly List<Tuple<string,string>> AssemblyNames = new List<Tuple<string, string>> ();
|
||||
|
||||
public void AddProcessedAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
AssemblyNames.Add (new Tuple<string, string>(assembly.Name.Name, assembly.Name.Version.ToString()));
|
||||
}
|
||||
|
||||
public IEnumerable<FrameworkEntry> PreviousFrameworks {
|
||||
get => allframeworks.Where (f => f.Index < this.Index);
|
||||
}
|
||||
|
||||
public ISet<AssemblySet> AllProcessedAssemblies { get => allAssemblies; }
|
||||
|
||||
public void AddAssemblySet (AssemblySet assemblySet)
|
||||
{
|
||||
allAssemblies.Add (assemblySet);
|
||||
}
|
||||
|
||||
/// <summary>Gets a value indicating whether this <see cref="T:Mono.Documentation.Updater.Frameworks.FrameworkEntry"/> is first framework being processed.</summary>
|
||||
public bool IsFirstFramework {
|
||||
get => this.Index == 0;
|
||||
}
|
||||
|
||||
public bool IsFirstFrameworkForType(FrameworkTypeEntry typeEntry)
|
||||
{
|
||||
if (this == Empty) return true;
|
||||
|
||||
var firstFx = this.allcachedframeworks.FirstOrDefault(f => f.FindTypeEntry(typeEntry) != null);
|
||||
|
||||
return firstFx == null || firstFx.Name == this.Name;
|
||||
}
|
||||
|
||||
/// <summary>Only Use in Unit Tests</summary>
|
||||
public string Replace="";
|
||||
|
||||
/// <summary>Only Use in Unit Tests</summary>
|
||||
public string With ="";
|
||||
|
||||
public IEnumerable<DocumentationImporter> Importers { get; set; }
|
||||
|
||||
public ISet<FrameworkTypeEntry> Types { get { return this.types; } }
|
||||
Dictionary<string, FrameworkTypeEntry> typeMap = new Dictionary<string, FrameworkTypeEntry> ();
|
||||
|
||||
public FrameworkTypeEntry FindTypeEntry (FrameworkTypeEntry type)
|
||||
{
|
||||
return FindTypeEntry (Str(type.Name));
|
||||
}
|
||||
|
||||
/// <param name="name">The value from <see cref="FrameworkTypeEntry.Name"/>.</param>
|
||||
public FrameworkTypeEntry FindTypeEntry (string name) {
|
||||
FrameworkTypeEntry entry;
|
||||
typeMap.TryGetValue (Str(name), out entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public IEnumerable<FrameworkEntry> Frameworks { get { return this.allframeworks; } }
|
||||
|
||||
public static readonly FrameworkEntry Empty = new EmptyFrameworkEntry () { Name = "Empty" };
|
||||
|
||||
public virtual FrameworkTypeEntry ProcessType (TypeDefinition type)
|
||||
{
|
||||
FrameworkTypeEntry entry;
|
||||
|
||||
if (!typeMap.TryGetValue (Str(type.FullName), out entry))
|
||||
{
|
||||
var docid = DocCommentId.GetDocCommentId (type);
|
||||
string nstouse = GetNamespace (type);
|
||||
entry = new FrameworkTypeEntry (this) { Id = Str (docid), Name = Str (type.FullName), Namespace = nstouse };
|
||||
types.Add (entry);
|
||||
|
||||
typeMap.Add (Str (entry.Name), entry);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
private string GetNamespace (TypeDefinition type)
|
||||
{
|
||||
var nstouse = Str (type.Namespace);
|
||||
if (string.IsNullOrWhiteSpace (nstouse) && type.DeclaringType != null)
|
||||
{
|
||||
return GetNamespace(type.DeclaringType);
|
||||
}
|
||||
|
||||
return nstouse;
|
||||
}
|
||||
|
||||
string Str(string value) {
|
||||
if (!string.IsNullOrWhiteSpace (Replace))
|
||||
return value.Replace (Replace, With);
|
||||
return value;
|
||||
}
|
||||
|
||||
public override string ToString () => Str(this.Name);
|
||||
|
||||
class EmptyFrameworkEntry : FrameworkEntry
|
||||
{
|
||||
public EmptyFrameworkEntry () : base (null, 1, null) { }
|
||||
public override FrameworkTypeEntry ProcessType (TypeDefinition type) { return FrameworkTypeEntry.Empty; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
140
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkIndex.cs
vendored
Normal file
140
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkIndex.cs
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Mono.Documentation.Updater.Frameworks
|
||||
{
|
||||
|
||||
public class FrameworkIndex
|
||||
{
|
||||
List<FrameworkEntry> frameworks = new List<FrameworkEntry> ();
|
||||
IList<FrameworkEntry> cachedFrameworks;
|
||||
|
||||
string path;
|
||||
|
||||
public FrameworkIndex (string pathToFrameworks, int fxCount, IList<FrameworkEntry> cachedfx)
|
||||
{
|
||||
path = pathToFrameworks;
|
||||
FrameworksCount = fxCount;
|
||||
cachedFrameworks = cachedfx ?? frameworks;
|
||||
}
|
||||
|
||||
public int FrameworksCount {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public IList<FrameworkEntry> Frameworks {
|
||||
get {
|
||||
return this.frameworks;
|
||||
}
|
||||
}
|
||||
|
||||
public FrameworkEntry StartProcessingAssembly (AssemblySet set, AssemblyDefinition assembly, IEnumerable<DocumentationImporter> importers, string Id, string Version)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace (this.path))
|
||||
{
|
||||
set.Framework = FrameworkEntry.Empty;
|
||||
return FrameworkEntry.Empty;
|
||||
}
|
||||
|
||||
string assemblyPath = assembly.MainModule.FileName;
|
||||
string shortPath = GetFrameworkNameFromPath (this.path, assemblyPath);
|
||||
|
||||
var entry = frameworks.FirstOrDefault (f => f.Name.Equals (shortPath));
|
||||
if (entry == null)
|
||||
{
|
||||
entry = new FrameworkEntry (frameworks, FrameworksCount, cachedFrameworks) { Name = shortPath, Importers = importers, Id = Id, Version = Version };
|
||||
frameworks.Add (entry);
|
||||
}
|
||||
|
||||
set.Framework = entry;
|
||||
entry.AddProcessedAssembly (assembly);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public static string GetFrameworkNameFromPath (string rootpath, string assemblyPath)
|
||||
{
|
||||
char otherSepChar = '/';
|
||||
if (Path.DirectorySeparatorChar == '/')
|
||||
otherSepChar = '\\';
|
||||
|
||||
if (rootpath.Contains(otherSepChar))
|
||||
rootpath = rootpath.Replace(otherSepChar, Path.DirectorySeparatorChar);
|
||||
|
||||
if (assemblyPath.Contains(otherSepChar))
|
||||
assemblyPath = assemblyPath.Replace(otherSepChar, Path.DirectorySeparatorChar);
|
||||
|
||||
var frameworksDirectory = rootpath.EndsWith ("frameworks.xml", StringComparison.OrdinalIgnoreCase)
|
||||
? Path.GetDirectoryName (rootpath) : rootpath;
|
||||
string relativePath = assemblyPath.Replace (frameworksDirectory, string.Empty);
|
||||
string shortPath = Path.GetDirectoryName (relativePath);
|
||||
if (shortPath.StartsWith (Path.DirectorySeparatorChar.ToString (), StringComparison.InvariantCultureIgnoreCase))
|
||||
shortPath = shortPath.Substring (1, shortPath.Length - 1);
|
||||
return shortPath;
|
||||
}
|
||||
|
||||
/// <summary>Writes the framework indices to disk.</summary>
|
||||
/// <param name="path">The folder where one file for every FrameworkEntry will be written.</param>
|
||||
public void WriteToDisk (string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace (this.path))
|
||||
return;
|
||||
|
||||
string outputPath = Path.Combine (path, Consts.FrameworksIndex);
|
||||
|
||||
if (!Directory.Exists (outputPath))
|
||||
Directory.CreateDirectory (outputPath);
|
||||
|
||||
foreach (var fx in this.frameworks)
|
||||
{
|
||||
XElement frameworkElement = new XElement("Framework", new XAttribute("Name", fx.Name));
|
||||
XDocument doc = new XDocument(
|
||||
frameworkElement
|
||||
);
|
||||
if (fx.Version!=null && fx.Id!= null)
|
||||
{
|
||||
frameworkElement.Add(new XElement("package", new XAttribute("Id", fx.Id),
|
||||
new XAttribute("Version", fx.Version)
|
||||
));
|
||||
}
|
||||
if (fx.AssemblyNames.Any())
|
||||
{
|
||||
frameworkElement.Add (
|
||||
new XElement (
|
||||
"Assemblies",
|
||||
fx.AssemblyNames.Distinct().Select(an =>
|
||||
new XElement("Assembly",
|
||||
new XAttribute("Name", an.Item1),
|
||||
new XAttribute("Version", an.Item2)
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
frameworkElement.Add(fx.Types.GroupBy(t => t.Namespace)
|
||||
.Select(g => new XElement("Namespace",
|
||||
new XAttribute("Name", g.Key),
|
||||
g.Select(t => new XElement("Type",
|
||||
new XAttribute("Name", t.Name),
|
||||
new XAttribute("Id", t.Id),
|
||||
t.Members.Select(m =>
|
||||
new XElement("Member",
|
||||
new XAttribute("Id", m))))))));
|
||||
// now save the document
|
||||
string filePath = Path.Combine (outputPath, fx.Name + ".xml");
|
||||
|
||||
MdocFile.DeleteFile (filePath);
|
||||
|
||||
var settings = new XmlWriterSettings { Indent = true };
|
||||
using (var writer = XmlWriter.Create (filePath, settings)) {
|
||||
doc.WriteTo (writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkTypeEntry.cs
vendored
Normal file
127
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkTypeEntry.cs
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Rocks;
|
||||
|
||||
namespace Mono.Documentation.Updater.Frameworks
|
||||
{
|
||||
public class FrameworkTypeEntry : IComparable<FrameworkTypeEntry>
|
||||
{
|
||||
Dictionary<string, string> sigMap = new Dictionary<string, string> ();
|
||||
|
||||
ILFullMemberFormatter formatter = new ILFullMemberFormatter ();
|
||||
DocIdFormatter docidFormatter = new DocIdFormatter ();
|
||||
|
||||
FrameworkEntry fx;
|
||||
|
||||
Lazy<FrameworkTypeEntry[]> previouslyProcessedFXTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all corresponding type entries,
|
||||
/// which have already been processed.
|
||||
/// </summary>
|
||||
public FrameworkTypeEntry[] PreviouslyProcessedFrameworkTypes {
|
||||
get
|
||||
{
|
||||
if (previouslyProcessedFXTypes == null)
|
||||
{
|
||||
if (this.Framework == null || this.Framework.Frameworks == null)
|
||||
{
|
||||
previouslyProcessedFXTypes = new Lazy<FrameworkTypeEntry[]> (() => new FrameworkTypeEntry[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
previouslyProcessedFXTypes = new Lazy<FrameworkTypeEntry[]> (
|
||||
() => this.Framework.Frameworks
|
||||
.Where (f => f.Index < this.Framework.Index)
|
||||
.Select (f => f.FindTypeEntry (this))
|
||||
.ToArray ()
|
||||
);
|
||||
}
|
||||
}
|
||||
return previouslyProcessedFXTypes.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public static FrameworkTypeEntry Empty = new EmptyTypeEntry (FrameworkEntry.Empty) { Name = "Empty" };
|
||||
|
||||
public FrameworkTypeEntry (FrameworkEntry fx)
|
||||
{
|
||||
this.fx = fx;
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Namespace { get; set; }
|
||||
public FrameworkEntry Framework { get { return fx; } }
|
||||
|
||||
public IEnumerable<string> Members {
|
||||
get {
|
||||
return this.sigMap.Values.OrderBy(v => v).Distinct();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ProcessMember (MemberReference member)
|
||||
{
|
||||
string key = null;
|
||||
|
||||
// this is for lookup purposes
|
||||
try
|
||||
{
|
||||
var sig = formatter.GetDeclaration(member);
|
||||
if (sig != null && !sigMap.ContainsKey (sig))
|
||||
{
|
||||
sigMap.Add (sig, string.Empty);
|
||||
key = sig;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (key == null)
|
||||
return;
|
||||
|
||||
var resolvedMember = member.Resolve ();
|
||||
if (resolvedMember != null) {
|
||||
var docid = docidFormatter.GetDeclaration (member);
|
||||
sigMap[key] = docid;
|
||||
}
|
||||
else
|
||||
sigMap[key] = member.FullName;
|
||||
|
||||
}
|
||||
|
||||
public bool ContainsCSharpSig (string sig)
|
||||
{
|
||||
return sigMap.ContainsKey (sig);
|
||||
}
|
||||
|
||||
public override string ToString () => $"{this.Name} in {this.fx.Name}";
|
||||
|
||||
public int CompareTo (FrameworkTypeEntry other)
|
||||
{
|
||||
if (other == null) return -1;
|
||||
if (this.Name == null) return 1;
|
||||
|
||||
return string.Compare (this.Name, other.Name, StringComparison.CurrentCulture);
|
||||
}
|
||||
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
FrameworkTypeEntry other = obj as FrameworkTypeEntry;
|
||||
if (other == null) return false;
|
||||
return this.Name.Equals (other.Name);
|
||||
}
|
||||
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return this.Name?.GetHashCode () ?? base.GetHashCode ();
|
||||
}
|
||||
|
||||
class EmptyTypeEntry : FrameworkTypeEntry
|
||||
{
|
||||
public EmptyTypeEntry (FrameworkEntry fx) : base (fx) { }
|
||||
public override void ProcessMember (MemberReference member) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
122
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/MDocMetadataResolver.cs
vendored
Normal file
122
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/MDocMetadataResolver.cs
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace Mono.Documentation.Updater.Frameworks
|
||||
{
|
||||
public class MDocMetadataResolver : MetadataResolver
|
||||
{
|
||||
public MDocMetadataResolver (CachedResolver r) : base (r) { }
|
||||
|
||||
ReaderParameters parameters = new ReaderParameters ();
|
||||
|
||||
public override TypeDefinition Resolve (TypeReference type)
|
||||
{
|
||||
type = type.GetElementType ();
|
||||
|
||||
var scope = type.Scope;
|
||||
|
||||
if (scope == null)
|
||||
return null;
|
||||
|
||||
CachedResolver assembly_resolver = this.AssemblyResolver as CachedResolver;
|
||||
parameters.AssemblyResolver = assembly_resolver;
|
||||
parameters.MetadataResolver = this;
|
||||
|
||||
try {
|
||||
|
||||
switch (scope.MetadataScopeType)
|
||||
{
|
||||
case MetadataScopeType.AssemblyNameReference:
|
||||
var assembly = assembly_resolver.ResolveCore ((AssemblyNameReference)scope, parameters, type);
|
||||
if (assembly == null)
|
||||
return null;
|
||||
|
||||
return GetType (assembly.MainModule, type);
|
||||
case MetadataScopeType.ModuleDefinition:
|
||||
return GetType ((ModuleDefinition)scope, type);
|
||||
case MetadataScopeType.ModuleReference:
|
||||
var modules = type.Module.Assembly.Modules;
|
||||
var module_ref = (ModuleReference)scope;
|
||||
for (int i = 0; i < modules.Count; i++)
|
||||
{
|
||||
var netmodule = modules[i];
|
||||
if (netmodule.Name == module_ref.Name)
|
||||
return GetType (netmodule, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(AssemblyResolutionException are)
|
||||
{
|
||||
throw new MDocException ($"Failed to resolve type '{type.FullName}'", are);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new NotSupportedException ($"metadata scope type {scope.MetadataScopeType.ToString("G")} is not supported");
|
||||
}
|
||||
static TypeDefinition GetType (ModuleDefinition module, TypeReference reference)
|
||||
{
|
||||
var type = GetTypeDefinition (module, reference);
|
||||
if (type != null)
|
||||
return type;
|
||||
|
||||
if (!module.HasExportedTypes)
|
||||
return null;
|
||||
|
||||
var exported_types = module.ExportedTypes;
|
||||
|
||||
for (int i = 0; i < exported_types.Count; i++)
|
||||
{
|
||||
var exported_type = exported_types[i];
|
||||
if (exported_type.Name != reference.Name)
|
||||
continue;
|
||||
|
||||
if (exported_type.Namespace != reference.Namespace)
|
||||
continue;
|
||||
|
||||
return exported_type.Resolve ();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static TypeDefinition GetTypeDefinition (ModuleDefinition module, TypeReference type)
|
||||
{
|
||||
if (!type.IsNested)
|
||||
return module.GetType (type.Namespace, type.Name);
|
||||
|
||||
var declaring_type = type.DeclaringType.Resolve ();
|
||||
if (declaring_type == null)
|
||||
return null;
|
||||
|
||||
return GetNestedType (declaring_type, TypeFullName(type));
|
||||
}
|
||||
|
||||
public static TypeDefinition GetNestedType (TypeDefinition self, string fullname)
|
||||
{
|
||||
if (!self.HasNestedTypes)
|
||||
return null;
|
||||
|
||||
var nested_types = self.NestedTypes;
|
||||
|
||||
for (int i = 0; i < nested_types.Count; i++)
|
||||
{
|
||||
var nested_type = nested_types[i];
|
||||
|
||||
if (TypeFullName(nested_type) == fullname)
|
||||
return nested_type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public static string TypeFullName (TypeReference self)
|
||||
{
|
||||
return string.IsNullOrEmpty (self.Namespace)
|
||||
? self.Name
|
||||
: self.Namespace + '.' + self.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
697
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/MDocResolver.cs
vendored
Normal file
697
external/api-doc-tools/mdoc/Mono.Documentation/Updater/Frameworks/MDocResolver.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user