Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/api-doc-tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mdoc/Mono.Documentation/Updater/Frameworks')
-rw-r--r--mdoc/Mono.Documentation/Updater/Frameworks/AssemblySet.cs111
-rw-r--r--mdoc/Mono.Documentation/Updater/Frameworks/FrameworkEntry.cs52
-rw-r--r--mdoc/Mono.Documentation/Updater/Frameworks/FrameworkIndex.cs91
-rw-r--r--mdoc/Mono.Documentation/Updater/Frameworks/FrameworkTypeEntry.cs80
-rw-r--r--mdoc/Mono.Documentation/Updater/Frameworks/UwpResolver.cs25
5 files changed, 359 insertions, 0 deletions
diff --git a/mdoc/Mono.Documentation/Updater/Frameworks/AssemblySet.cs b/mdoc/Mono.Documentation/Updater/Frameworks/AssemblySet.cs
new file mode 100644
index 00000000..524e39a7
--- /dev/null
+++ b/mdoc/Mono.Documentation/Updater/Frameworks/AssemblySet.cs
@@ -0,0 +1,111 @@
+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>
+ class AssemblySet : IDisposable
+ {
+ readonly DefaultAssemblyResolver resolver = new Frameworks.UwpResolver ();
+ HashSet<string> assemblyPaths = new HashSet<string> ();
+ HashSet<string> assemblySearchPaths = new HashSet<string> ();
+ HashSet<string> forwardedTypes = new HashSet<string> ();
+ IEnumerable<string> importPaths;
+ public IEnumerable<DocumentationImporter> Importers { get; private set; }
+
+ public AssemblySet (IEnumerable<string> paths) : this ("Default", paths, new string[0], null) { }
+
+ public AssemblySet (string name, IEnumerable<string> paths, IEnumerable<string> resolverSearchPaths, IEnumerable<string> imports)
+ {
+ 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<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));
+ }
+ else
+ this.Importers = new DocumentationImporter[0];
+ }
+
+ public string Name { get; private set; }
+
+ public IEnumerable<AssemblyDefinition> Assemblies { get { return this.LoadAllAssemblies ().Where(a => a != null); } }
+ 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)
+ .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 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);
+ }
+
+ public void Dispose () => resolver.Dispose ();
+
+ 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, 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;
+ }
+ }
+ }
+}
diff --git a/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkEntry.cs b/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkEntry.cs
new file mode 100644
index 00000000..c6684d51
--- /dev/null
+++ b/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkEntry.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Rocks;
+
+namespace Mono.Documentation.Updater.Frameworks
+{
+ class FrameworkEntry
+ {
+ SortedSet<FrameworkTypeEntry> types = new SortedSet<FrameworkTypeEntry> ();
+
+ List<FrameworkEntry> allframeworks;
+
+ public FrameworkEntry (List<FrameworkEntry> frameworks)
+ {
+ allframeworks = frameworks;
+ if (allframeworks == null)
+ allframeworks = new List<FrameworkEntry> (0);
+ }
+
+ public string Name { get; set; }
+
+ public IEnumerable<DocumentationImporter> Importers { get; set; }
+
+ public ISet<FrameworkTypeEntry> Types { get { return this.types; } }
+
+ public IEnumerable<FrameworkEntry> Frameworks { get { return this.allframeworks; } }
+
+ public static readonly FrameworkEntry Empty = new EmptyFrameworkEntry () { Name = "Empty" };
+
+ public virtual FrameworkTypeEntry ProcessType (TypeDefinition type)
+ {
+
+ var entry = types.FirstOrDefault (t => t.Name.Equals (type.FullName));
+ if (entry == null) {
+ var docid = DocCommentId.GetDocCommentId (type);
+ entry = new FrameworkTypeEntry (this) { Id = docid, Name = type.FullName, Namespace = type.Namespace };
+ types.Add (entry);
+ }
+ return entry;
+ }
+
+ public override string ToString () => this.Name;
+
+ class EmptyFrameworkEntry : FrameworkEntry
+ {
+ public EmptyFrameworkEntry () : base (null) { }
+ public override FrameworkTypeEntry ProcessType (TypeDefinition type) { return FrameworkTypeEntry.Empty; }
+ }
+ }
+}
diff --git a/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkIndex.cs b/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkIndex.cs
new file mode 100644
index 00000000..e392f585
--- /dev/null
+++ b/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkIndex.cs
@@ -0,0 +1,91 @@
+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
+{
+
+ class FrameworkIndex
+ {
+ List<FrameworkEntry> frameworks = new List<FrameworkEntry> ();
+ string path;
+
+ public FrameworkIndex (string pathToFrameworks)
+ {
+ path = pathToFrameworks;
+ }
+
+ public IList<FrameworkEntry> Frameworks {
+ get {
+ return this.frameworks;
+ }
+ }
+
+ public FrameworkEntry StartProcessingAssembly (AssemblyDefinition assembly, IEnumerable<DocumentationImporter> importers)
+ {
+ if (string.IsNullOrWhiteSpace (this.path))
+ return FrameworkEntry.Empty;
+
+ string assemblyPath = assembly.MainModule.FileName;
+ var frameworksDirectory = this.path.EndsWith ("frameworks.xml", StringComparison.OrdinalIgnoreCase)
+ ? Path.GetDirectoryName (this.path) : this.path;
+ 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);
+
+
+ var entry = frameworks.FirstOrDefault (f => f.Name.Equals (shortPath));
+ if (entry == null) {
+ entry = new FrameworkEntry (frameworks) { Name = shortPath, Importers = importers };
+ frameworks.Add (entry);
+ }
+ return entry;
+ }
+
+ /// <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, "FrameworksIndex");
+ if (!Directory.Exists (outputPath))
+ Directory.CreateDirectory (outputPath);
+
+ foreach (var fx in this.frameworks) {
+
+ XDocument doc = new XDocument (
+ new XElement("Framework",
+ new XAttribute ("Name", fx.Name),
+ 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");
+
+ if (File.Exists (filePath))
+ File.Delete (filePath);
+
+ var settings = new XmlWriterSettings { Indent = true };
+ using (var writer = XmlWriter.Create (filePath, settings)) {
+ doc.WriteTo (writer);
+ }
+ }
+ }
+ }
+}
diff --git a/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkTypeEntry.cs b/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkTypeEntry.cs
new file mode 100644
index 00000000..67bcee86
--- /dev/null
+++ b/mdoc/Mono.Documentation/Updater/Frameworks/FrameworkTypeEntry.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using Mono.Cecil;
+using Mono.Cecil.Rocks;
+
+namespace Mono.Documentation.Updater.Frameworks
+{
+ class FrameworkTypeEntry : IComparable<FrameworkTypeEntry>
+ {
+ SortedSet<string> members = new SortedSet<string> ();
+ SortedSet<string> memberscsharpsig = new SortedSet<string> ();
+
+ ILFullMemberFormatter formatter = new ILFullMemberFormatter ();
+
+ FrameworkEntry fx;
+
+ 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 ISet<string> Members {
+ get {
+ return this.members;
+ }
+ }
+
+ public virtual void ProcessMember (MemberReference member)
+ {
+ var resolvedMember = member.Resolve ();
+ if (resolvedMember != null) {
+ var docid = DocCommentId.GetDocCommentId (resolvedMember);
+ members.Add (docid);
+ }
+ else
+ members.Add (member.FullName);
+
+ // this is for lookup purposes
+ try {
+ memberscsharpsig.Add(formatter.GetDeclaration(member));
+ }
+ catch {}
+ }
+
+ public bool ContainsCSharpSig (string sig)
+ {
+ return memberscsharpsig.Contains (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);
+ }
+
+ class EmptyTypeEntry : FrameworkTypeEntry
+ {
+ public EmptyTypeEntry (FrameworkEntry fx) : base (fx) { }
+ public override void ProcessMember (MemberReference member) { }
+ }
+ }
+}
diff --git a/mdoc/Mono.Documentation/Updater/Frameworks/UwpResolver.cs b/mdoc/Mono.Documentation/Updater/Frameworks/UwpResolver.cs
new file mode 100644
index 00000000..4dbbec82
--- /dev/null
+++ b/mdoc/Mono.Documentation/Updater/Frameworks/UwpResolver.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Microsoft.Win32;
+using Mono.Cecil;
+
+namespace Mono.Documentation.Updater.Frameworks
+{
+ /// <summary>Mono.Cecil resolver for the windows universal platform</summary>
+ class UwpResolver : DefaultAssemblyResolver
+ {
+ public override AssemblyDefinition Resolve (AssemblyNameReference name)
+ {
+ var ver = name.Version;
+ if (ver.Major == 255 && ver.Minor == 255 && ver.Revision == 255 && name.Name == "mscorlib")
+ {
+ var v = new Version (4, 5, 0);
+ var anr = new AssemblyNameReference (name.Name, v);
+ return base.Resolve (anr);
+ }
+ else
+ return base.Resolve (name);
+ }
+ }
+} \ No newline at end of file