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
path: root/mdoc
diff options
context:
space:
mode:
authorJoel Martinez <joelmartinez@gmail.com>2017-03-03 21:51:13 +0300
committerJoel Martinez <joelmartinez@gmail.com>2017-03-03 22:32:17 +0300
commit6b00abca5aa0d4375ba28eb933d5ac7ebdc7e49c (patch)
treef528e79685d7837154ef27c665c746d1db9ca34b /mdoc
parent0b6f479891f2730783cc680faa24793c5a1e6e89 (diff)
Frameworks Mode for Update Commandpreview-5.0.0.6
mdoc now supports documenting multiple frameworks. You can use this new functionality by passing the path to a configuration file in the `-frameworks` (or `-fx` for short) parameter. ``` mdoc update -o path/to/documentationXML -frameworks path/to/frameworks.xml ``` This command will result in one XML file per framework in the `path/to/documentationXML/FrameworksIndex` folder. ``` xml <?xml version="1.0" encoding="utf-8"?> <Framework Name="Two"> <Namespace Name="MyFramework.MyOtherNamespace"> <Type Name="MyFramework.MyOtherNamespace.MyOtherClass" Id="T:MyFramework.MyOtherNamespace.MyOtherClass"> <Member Id="M:MyFramework.MyOtherNamespace.MyOtherClass.#ctor" /> ... </Type> </Namespace> </Framework> ``` Configuration File This is a sample configuration file: ``` xml <?xml version="1.0" encoding="utf-8"?> <Frameworks> <Framework Name="One" Source="One"> <assemblySearchPath>dependencies/One</assemblySearchPath> </Framework> <Framework Name="Two" Source="Two"> <assemblySearchPath>dependencies/Two</assemblySearchPath> </Framework> </Frameworks> ``` Note that the `assemblySearchPath` is meant to house dependent assemblies that mono.cecil must be able to resolve. You can have as many as you need for each framework if you happen to have them separated into multiple folders. Also the `-L` parameter applies globally to every framework. Frameworks Config Bootstrap To simplify the tedium of creating the configuration file, a simple command was added that will use the folder structure to create a basic configuration file: ``` csharp mdoc fx-bootstrap path/to/frameworks ``` This will create a file at `path/to/frameworks/frameworks.xml`, using the folders in `path/to/frameworks` as the names/paths DocId Signatures You can now pass a flag to add a `DocId` signature to every `Type` and `Member` node. ``` mdoc update -o out/path some.dll -use-docid ``` _please note_: framework index files will _always_ use the DocId as their identifiers. Frameworks Index files Grouped by Namespace Framework index files now have types grouped by namespace. Example: ``` xml <?xml version="1.0" encoding="utf-8"?> <Framework Name="Two"> <Namespace Name="MyFramework.MyOtherNamespace"> <Type Name="MyFramework.MyOtherNamespace.MyOtherClass" Id="T:MyFramework.MyOtherNamespace.MyOtherClass"> <Member Id="M:MyFramework.MyOtherNamespace.MyOtherClass.#ctor" /> ... </Type> </Namespace> </Framework> ``` Bug Fixes and Enhancements - Resolves #13 - Resolves #27 - Resolves #31 - Resolves #33
Diffstat (limited to 'mdoc')
-rw-r--r--mdoc/.gitignore1
-rw-r--r--mdoc/Consts.cs2
-rw-r--r--mdoc/Makefile25
-rw-r--r--mdoc/Mono.Documentation/Frameworks/AssemblySet.cs81
-rw-r--r--mdoc/Mono.Documentation/Frameworks/FrameworkEntry.cs38
-rw-r--r--mdoc/Mono.Documentation/Frameworks/FrameworkIndex.cs89
-rw-r--r--mdoc/Mono.Documentation/Frameworks/FrameworkTypeEntry.cs57
-rw-r--r--mdoc/Mono.Documentation/frameworksbootstrapper.cs56
-rw-r--r--mdoc/Mono.Documentation/mdoc.cs2
-rw-r--r--mdoc/Mono.Documentation/monodocer.cs309
-rw-r--r--mdoc/Mono.Documentation/preserver.cs37
-rw-r--r--mdoc/Test/en.expected-docid/FrameworksIndex/One.xml20
-rw-r--r--mdoc/Test/en.expected-docid/FrameworksIndex/Two.xml16
-rw-r--r--mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClass.xml92
-rw-r--r--mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClassExtensions.xml41
-rw-r--r--mdoc/Test/en.expected-docid/MyFramework.MyOtherNamespace/MyOtherClass.xml74
-rw-r--r--mdoc/Test/en.expected-docid/MyNamespace/MyClass.xml57
-rw-r--r--mdoc/Test/en.expected-docid/index.xml73
-rw-r--r--mdoc/Test/en.expected-docid/ns-MyFramework.MyNamespace.xml6
-rw-r--r--mdoc/Test/en.expected-docid/ns-MyFramework.MyOtherNamespace.xml6
-rw-r--r--mdoc/Test/en.expected-docid/ns-MyNamespace.xml6
-rw-r--r--mdoc/Test/en.expected-frameworks/FrameworksIndex/One.xml20
-rw-r--r--mdoc/Test/en.expected-frameworks/FrameworksIndex/Two.xml16
-rw-r--r--mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClass.xml87
-rw-r--r--mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClassExtensions.xml39
-rw-r--r--mdoc/Test/en.expected-frameworks/MyFramework.MyOtherNamespace/MyOtherClass.xml70
-rw-r--r--mdoc/Test/en.expected-frameworks/MyNamespace/MyClass.xml54
-rw-r--r--mdoc/Test/en.expected-frameworks/index.xml72
-rw-r--r--mdoc/Test/en.expected-frameworks/ns-MyFramework.MyNamespace.xml6
-rw-r--r--mdoc/Test/en.expected-frameworks/ns-MyFramework.MyOtherNamespace.xml6
-rw-r--r--mdoc/Test/en.expected-frameworks/ns-MyNamespace.xml6
-rw-r--r--mdoc/mdoc.csproj9
32 files changed, 1296 insertions, 177 deletions
diff --git a/mdoc/.gitignore b/mdoc/.gitignore
index 26820987..a293042c 100644
--- a/mdoc/.gitignore
+++ b/mdoc/.gitignore
@@ -2,5 +2,6 @@
/Test/html.*/
/Test/DocTest.*
/Test/*.dll*
+/Test/FrameworkTestData/
/.v2.txt
/.v0.txt \ No newline at end of file
diff --git a/mdoc/Consts.cs b/mdoc/Consts.cs
index 13674483..2737f497 100644
--- a/mdoc/Consts.cs
+++ b/mdoc/Consts.cs
@@ -4,6 +4,6 @@ namespace Mono.Documentation
public static class Consts
{
// this is only a placeholder
- public static string MonoVersion = "0.0.0.0";
+ public static string MonoVersion = "5.0.0.6";
}
}
diff --git a/mdoc/Makefile b/mdoc/Makefile
index 745a8f7d..67ff7774 100644
--- a/mdoc/Makefile
+++ b/mdoc/Makefile
@@ -118,6 +118,27 @@ Test/DocTest.dll-v2:
Test/DocTest-enumerations.dll:
$(CSCOMPILE) $(TEST_CSCFLAGS) -unsafe -debug -optimize -target:library -out:$@ Test/DocTest-enumerations.cs
+Test/FrameworkTestData: Test/DocTest-addNonGeneric.dll Test/DocTest-DropNS-classic.dll Test/DocTest-DropNS-classic-secondary.dll
+ rm -rf Test/FrameworkTestData
+ mkdir Test/FrameworkTestData
+ mkdir Test/FrameworkTestData/One
+ mkdir Test/FrameworkTestData/Two
+ cp Test/DocTest-addNonGeneric.dll Test/FrameworkTestData/One/
+ cp Test/DocTest-DropNS-classic.dll Test/FrameworkTestData/One/
+ cp Test/DocTest-addNonGeneric.dll Test/FrameworkTestData/Two/
+ cp Test/DocTest-DropNS-classic-secondary.dll Test/FrameworkTestData/Two/
+ $(MONO) $(PROGRAM) fx-bootstrap Test/FrameworkTestData
+
+check-monodocer-frameworks: Test/FrameworkTestData
+ -rm -Rf Test/en.actual
+ $(MONO) $(PROGRAM) update -o Test/en.actual -frameworks Test/FrameworkTestData
+ $(DIFF) Test/en.expected-frameworks Test/en.actual
+
+check-monodocer-docid: Test/FrameworkTestData
+ -rm -Rf Test/en.actual
+ $(MONO) $(PROGRAM) update -use-docid -o Test/en.actual -frameworks Test/FrameworkTestData
+ $(DIFF) Test/en.expected-docid Test/en.actual
+
check-monodocer-addNonGeneric:
-rm -Rf Test/en.actual
# first, make a docset with the generic method
@@ -396,7 +417,9 @@ check-doc-tools: check-monodocer-since \
check-monodocer-ignore-invalid-assemblies \
check-monodocer-enumerations \
check-monodocer-dropns-multi \
- check-monodocer-dropns-multi-withexisting
+ check-monodocer-dropns-multi-withexisting \
+ check-monodocer-frameworks \
+ check-monodocer-docid
check-doc-tools-update: check-monodocer-since-update \
check-monodocer-importecmadoc-update \
diff --git a/mdoc/Mono.Documentation/Frameworks/AssemblySet.cs b/mdoc/Mono.Documentation/Frameworks/AssemblySet.cs
new file mode 100644
index 00000000..4ca6f201
--- /dev/null
+++ b/mdoc/Mono.Documentation/Frameworks/AssemblySet.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Mono.Cecil;
+
+namespace Mono.Documentation
+{
+ /// <summary>
+ /// Represents a set of assemblies that we want to document
+ /// </summary>
+ class AssemblySet : IDisposable
+ {
+ readonly DefaultAssemblyResolver resolver = new DefaultAssemblyResolver ();
+ HashSet<string> assemblyPaths = new HashSet<string> ();
+ HashSet<string> assemblySearchPaths = new HashSet<string> ();
+ HashSet<string> forwardedTypes = new HashSet<string> ();
+
+ public AssemblySet (string path) : this (new string[] { path }) { }
+
+ public AssemblySet (IEnumerable<string> paths) : this ("Default", paths, new string[0]) { }
+
+ public AssemblySet (string name, IEnumerable<string> paths, IEnumerable<string> 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);
+
+ foreach (var searchPath in assemblySearchPaths)
+ resolver.AddSearchDirectory (searchPath);
+ }
+
+ 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; } }
+
+ /// <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/Frameworks/FrameworkEntry.cs b/mdoc/Mono.Documentation/Frameworks/FrameworkEntry.cs
new file mode 100644
index 00000000..bcd7c2b4
--- /dev/null
+++ b/mdoc/Mono.Documentation/Frameworks/FrameworkEntry.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Rocks;
+
+namespace Mono.Documentation
+{
+ class FrameworkEntry
+ {
+ SortedSet<FrameworkTypeEntry> types = new SortedSet<FrameworkTypeEntry> ();
+
+ public string Name { get; set; }
+
+ public ISet<FrameworkTypeEntry> Types { get { return this.types; } }
+
+ 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 override FrameworkTypeEntry ProcessType (TypeDefinition type) { return FrameworkTypeEntry.Empty; }
+ }
+ }
+}
diff --git a/mdoc/Mono.Documentation/Frameworks/FrameworkIndex.cs b/mdoc/Mono.Documentation/Frameworks/FrameworkIndex.cs
new file mode 100644
index 00000000..d595428a
--- /dev/null
+++ b/mdoc/Mono.Documentation/Frameworks/FrameworkIndex.cs
@@ -0,0 +1,89 @@
+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
+{
+
+ 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)
+ {
+ if (string.IsNullOrWhiteSpace (this.path))
+ return FrameworkEntry.Empty;
+
+ string assemblyPath = assembly.MainModule.FileName;
+ string relativePath = assemblyPath.Replace (this.path, 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 { Name = shortPath };
+ 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/Frameworks/FrameworkTypeEntry.cs b/mdoc/Mono.Documentation/Frameworks/FrameworkTypeEntry.cs
new file mode 100644
index 00000000..cae47692
--- /dev/null
+++ b/mdoc/Mono.Documentation/Frameworks/FrameworkTypeEntry.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using Mono.Cecil;
+using Mono.Cecil.Rocks;
+
+namespace Mono.Documentation
+{
+ class FrameworkTypeEntry : IComparable<FrameworkTypeEntry>
+ {
+ SortedSet<string> members = new SortedSet<string> ();
+ 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 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);
+ }
+
+ 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);
+ }
+
+ class EmptyTypeEntry : FrameworkTypeEntry
+ {
+ public EmptyTypeEntry (FrameworkEntry fx) : base (fx) { }
+ public override void ProcessMember (MemberReference member) { }
+ }
+ }
+}
diff --git a/mdoc/Mono.Documentation/frameworksbootstrapper.cs b/mdoc/Mono.Documentation/frameworksbootstrapper.cs
new file mode 100644
index 00000000..4ce8c178
--- /dev/null
+++ b/mdoc/Mono.Documentation/frameworksbootstrapper.cs
@@ -0,0 +1,56 @@
+// Command to preserve member documentation for types that are changing in a subsequent version
+// By Joel Martinez <joel.martinez@xamarin.com
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using System.Xml.Linq;
+using Mono.Options;
+
+namespace Mono.Documentation
+{
+ public class MDocFrameworksBootstrapper : MDocCommand
+ {
+ public override void Run (IEnumerable<string> args)
+ {
+ args = args.Skip (1);
+ if (args.Count () != 1)
+ Error ("Need to supply a single directory, which contain folders that represent frameworks.");
+
+ string frameworkPath = args.Single ();
+ int slashOffset = frameworkPath.EndsWith (Path.DirectorySeparatorChar.ToString (), StringComparison.InvariantCultureIgnoreCase) ? 0 : 1;
+
+ if (!Directory.Exists(frameworkPath))
+ Error ($"Path not found: {frameworkPath}");
+
+ var data = Directory.GetDirectories (frameworkPath)
+ .Select (d => new {
+ Path = d.Substring (frameworkPath.Length + slashOffset, d.Length - frameworkPath.Length - slashOffset),
+ Name = Path.GetFileName(d)
+ }).ToArray();
+
+ foreach (var d in data)
+ Console.WriteLine (d.Name);
+
+ var doc = new XDocument (
+ new XElement("Frameworks",
+ data.Select(d => new XElement(
+ "Framework",
+ new XAttribute("Name", d.Name),
+ new XAttribute("Source", d.Path),
+ new XElement("assemblySearchPath", Path.Combine("dependencies", d.Name)))))
+ );
+
+ var configPath = Path.Combine (frameworkPath, "frameworks.xml");
+ var settings = new XmlWriterSettings { Indent = true };
+ using (var writer = XmlWriter.Create (configPath, settings)) {
+ doc.WriteTo (writer);
+ }
+
+ Console.WriteLine ($"Framework configuration file written to {configPath}");
+ }
+ }
+}
+
diff --git a/mdoc/Mono.Documentation/mdoc.cs b/mdoc/Mono.Documentation/mdoc.cs
index 207d6cb4..bb1c4c65 100644
--- a/mdoc/Mono.Documentation/mdoc.cs
+++ b/mdoc/Mono.Documentation/mdoc.cs
@@ -48,7 +48,7 @@ namespace Mono.Documentation {
{ "update-ecma-xml", new MDocUpdateEcmaXml () },
{ "validate", new MDocValidator () },
{ "index", new MDocIndex () },
- { "preserve", new MDocPreserve () }
+ { "fx-bootstrap", new MDocFrameworksBootstrapper () }
};
bool showVersion = false;
diff --git a/mdoc/Mono.Documentation/monodocer.cs b/mdoc/Mono.Documentation/monodocer.cs
index ae5161cc..71451c53 100644
--- a/mdoc/Mono.Documentation/monodocer.cs
+++ b/mdoc/Mono.Documentation/monodocer.cs
@@ -12,9 +12,11 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
+using System.Xml.Linq;
using System.Xml.XPath;
using Mono.Cecil;
+using Mono.Cecil.Rocks;
using Mono.Options;
using MyXmlNodeList = System.Collections.Generic.List<System.Xml.XmlNode>;
@@ -130,9 +132,9 @@ namespace Mono.Documentation {
class MDocUpdater : MDocCommand
{
string srcPath;
- List<AssemblyDefinition> assemblies;
- readonly DefaultAssemblyResolver assemblyResolver = new DefaultAssemblyResolver();
-
+ List<AssemblySet> assemblies = new List<AssemblySet>();
+ StringList globalSearchPaths = new StringList ();
+
string apistyle = string.Empty;
bool isClassicRun;
@@ -166,8 +168,6 @@ class MDocUpdater : MDocCommand
MyXmlNodeList extensionMethods = new MyXmlNodeList ();
- HashSet<string> forwardedTypes = new HashSet<string> ();
-
public static string droppedNamespace = string.Empty;
public static bool HasDroppedNamespace(TypeDefinition forType)
@@ -199,9 +199,13 @@ class MDocUpdater : MDocCommand
/// assemblies for a given type/method.</summary>
public bool IsMultiAssembly {
get {
- return apistyle == "classic" || apistyle == "unified";
+ return apistyle == "classic" || apistyle == "unified" || !string.IsNullOrWhiteSpace(FrameworksPath);
}
}
+
+ /// <summary>Path which contains multiple folders with assemblies. Each folder contained will represent one framework.</summary>
+ string FrameworksPath = string.Empty;
+ FrameworkIndex frameworks;
static List<string> droppedAssemblies = new List<string>();
@@ -254,7 +258,7 @@ class MDocUpdater : MDocCommand
v => AddImporter (v) },
{ "L|lib=",
"Check for assembly references in {DIRECTORY}.",
- v => assemblyResolver.AddSearchDirectory (v) },
+ v => globalSearchPaths.Add (v) },
{ "library=",
"Ignored for compatibility with update-ecma-xml.",
v => {} },
@@ -264,7 +268,7 @@ class MDocUpdater : MDocCommand
{ "r=",
"Search for dependent assemblies in the directory containing {ASSEMBLY}.\n" +
"(Equivalent to '-L `dirname ASSEMBLY`'.)",
- v => assemblyResolver.AddSearchDirectory (Path.GetDirectoryName (v)) },
+ v => globalSearchPaths.Add (Path.GetDirectoryName (v)) },
{ "since=",
"Manually specify the assembly {VERSION} that new members were added in.",
v => since = v },
@@ -290,14 +294,56 @@ class MDocUpdater : MDocCommand
v => PreserveTag = "true" },
{ "api-style=",
"Denotes the apistyle. Currently, only `classic` and `unified` are supported. `classic` set of assemblies should be run first, immediately followed by 'unified' assemblies with the `dropns` parameter.",
- v => { apistyle = v.ToLowerInvariant (); }},
+ v => apistyle = v.ToLowerInvariant () },
+ { "fx|frameworks=",
+ "Configuration XML file, that points to directories which contain libraries that span multiple frameworks.",
+ v => FrameworksPath = v },
+ { "use-docid",
+ "Add 'DocId' to the list of type and member signatures",
+ v =>
+ {
+ typeFormatters = typeFormatters.Union (new MemberFormatter[] { new DocIdFormatter () }).ToArray ();
+ memberFormatters = memberFormatters.Union (new MemberFormatter[] { new DocIdFormatter () }).ToArray ();
+ } },
};
- var assemblies = Parse (p, args, "update",
+ var assemblyPaths = Parse (p, args, "update",
"[OPTIONS]+ ASSEMBLIES",
"Create or update documentation from ASSEMBLIES.");
- if (assemblies == null)
+
+ if (!string.IsNullOrWhiteSpace (FrameworksPath)) {
+ var configPath = FrameworksPath;
+ var frameworksDir = FrameworksPath;
+ if (!configPath.EndsWith ("frameworks.xml", StringComparison.InvariantCultureIgnoreCase))
+ configPath = Path.Combine (configPath, "frameworks.xml");
+ else
+ frameworksDir = Path.GetDirectoryName (configPath);
+
+ var fxconfig = XDocument.Load (configPath);
+ var fxd = fxconfig.Root
+ .Elements ("Framework")
+ .Select (f => new {
+ Name = f.Attribute ("Name").Value,
+ Path = Path.Combine(frameworksDir,f.Attribute("Source").Value),
+ SearchPaths = f.Elements("assemblySearchPath")
+ .Select(a => Path.Combine(frameworksDir, a.Value))
+ .ToArray()
+ });
+
+ var sets = fxd.Select (d => new AssemblySet (
+ d.Name,
+ Directory.GetFiles (d.Path, "*.dll"),
+ this.globalSearchPaths.Union(d.SearchPaths)
+ ));
+ this.assemblies.AddRange (sets);
+ assemblyPaths.AddRange(sets.SelectMany (s => s.AssemblyPaths));
+ }
+ else {
+ this.assemblies.Add (new AssemblySet ("Default", assemblyPaths, this.globalSearchPaths));
+ }
+
+ if (assemblyPaths == null)
return;
- if (assemblies.Count == 0)
+ if (assemblyPaths.Count == 0)
Error ("No assemblies specified.");
// validation for the api-style parameter
@@ -309,47 +355,33 @@ class MDocUpdater : MDocCommand
} else if (!string.IsNullOrWhiteSpace (apistyle))
Error ("api-style '{0}' is not currently supported", apistyle);
-
- foreach (var dir in assemblies
- .Where (a => a.Contains (Path.DirectorySeparatorChar))
- .Select (a => Path.GetDirectoryName (a)))
- assemblyResolver.AddSearchDirectory (dir);
-
// PARSE BASIC OPTIONS AND LOAD THE ASSEMBLY TO DOCUMENT
if (srcPath == null)
throw new InvalidOperationException("The --out option is required.");
- this.assemblies = assemblies.Select (a => LoadAssembly (a)).Where(a => a != null).ToList ();
-
- if (assemblies.Count == 0)
- Error ("No valid assemblies specified.");
-
- // Store types that have been forwarded to avoid duplicate generation
- GatherForwardedTypes ();
-
docEnum = docEnum ?? new DocumentationEnumerator ();
-
+
// PERFORM THE UPDATES
-
+ frameworks = new FrameworkIndex (FrameworksPath);
+
if (types.Count > 0) {
types.Sort ();
DoUpdateTypes (srcPath, types, srcPath);
}
-#if false
- else if (opts.@namespace != null)
- DoUpdateNS (opts.@namespace, Path.Combine (opts.path, opts.@namespace),
- Path.Combine (dest_dir, opts.@namespace));
-#endif
else
DoUpdateAssemblies (srcPath, srcPath);
+ if (!string.IsNullOrWhiteSpace (FrameworksPath))
+ frameworks.WriteToDisk (srcPath);
+
Console.WriteLine("Members Added: {0}, Members Deleted: {1}", additions, deletions);
}
- public static bool IsInAssemblies(string name) {
- var query = Instance.assemblies.Where (a => a.MainModule.Name == name).ToArray ();
- return query.Length > 0;
- }
+
+ public static bool IsInAssemblies(string name) {
+ return Instance.assemblies.Any(a => a.Contains(name));
+ }
+
void AddImporter (string path)
{
try {
@@ -377,13 +409,6 @@ class MDocUpdater : MDocCommand
}
}
- void GatherForwardedTypes ()
- {
- foreach (var asm in assemblies)
- foreach (var type in asm.MainModule.ExportedTypes.Where (t => t.IsForwarder).Select (t => t.FullName))
- forwardedTypes.Add (type);
- }
-
static ExceptionLocations ParseExceptionLocations (string s)
{
ExceptionLocations loc = ExceptionLocations.Member;
@@ -406,7 +431,7 @@ class MDocUpdater : MDocCommand
Message (TraceLevel.Warning, "mdoc: " + format, args);
}
- private AssemblyDefinition LoadAssembly (string name)
+ internal AssemblyDefinition LoadAssembly (string name, IAssemblyResolver assemblyResolver)
{
AssemblyDefinition assembly = null;
try {
@@ -537,21 +562,29 @@ class MDocUpdater : MDocCommand
var index = CreateIndexForTypes (dest);
var found = new HashSet<string> ();
- foreach (AssemblyDefinition assembly in assemblies) {
- foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, typenames)) {
- string relpath = DoUpdateType (type, basepath, dest);
- if (relpath == null)
- continue;
+ foreach (var assemblySet in this.assemblies) {
+ using (assemblySet) {
+ foreach (AssemblyDefinition assembly in assemblySet.Assemblies) {
+ var frameworkEntry = frameworks.StartProcessingAssembly (assembly);
- found.Add (type.FullName);
+ foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, typenames)) {
+ var typeEntry = frameworkEntry.ProcessType (type);
- if (index == null)
- continue;
+ string relpath = DoUpdateType (type, typeEntry, basepath, dest);
+ if (relpath == null)
+ continue;
+
+ found.Add (type.FullName);
+
+ if (index == null)
+ continue;
- index.Add (assembly);
- index.Add (type);
+ index.Add (assembly);
+ index.Add (type);
+ }
+ }
+ }
}
- }
if (index != null)
index.Write ();
@@ -625,7 +658,7 @@ class MDocUpdater : MDocCommand
return file.Exists;
}
- public string DoUpdateType (TypeDefinition type, string basepath, string dest)
+ public string DoUpdateType (TypeDefinition type, FrameworkTypeEntry typeEntry, string basepath, string dest)
{
if (type.Namespace == null)
Warning ("warning: The type `{0}' is in the root namespace. This may cause problems with display within monodoc.",
@@ -698,7 +731,7 @@ class MDocUpdater : MDocCommand
throw new InvalidOperationException("Error loading " + typefile + ": " + e.Message, e);
}
- DoUpdateType2("Updating", basefile, type, output, false);
+ DoUpdateType2("Updating", basefile, type, typeEntry, output, false);
} else {
// Stub
XmlElement td = StubType(type, output);
@@ -707,50 +740,6 @@ class MDocUpdater : MDocCommand
}
return reltypefile;
}
-
- public void DoUpdateNS (string ns, string nspath, string outpath)
- {
- Dictionary<TypeDefinition, object> seenTypes = new Dictionary<TypeDefinition,object> ();
- AssemblyDefinition assembly = assemblies [0];
-
- foreach (System.IO.FileInfo file in new System.IO.DirectoryInfo(nspath).GetFiles("*.xml")) {
- XmlDocument basefile = new XmlDocument();
- string typefile = Path.Combine(nspath, file.Name);
- try {
- basefile.Load(typefile);
- } catch (Exception e) {
- throw new InvalidOperationException("Error loading " + typefile + ": " + e.Message, e);
- }
-
- string typename =
- GetTypeFileName (basefile.SelectSingleNode("Type/@FullName").InnerText);
- TypeDefinition type = assembly.GetType(typename);
- if (type == null) {
- // --
- if (!string.IsNullOrWhiteSpace (droppedNamespace)) {
- string nameWithNs = string.Format ("{0}.{1}", droppedNamespace, typename);
- type = assembly.GetType (nameWithNs);
- if (type == null) {
- Warning ("Type no longer in assembly: " + typename);
- continue;
- }
- }
- //--
- }
-
- seenTypes[type] = seenTypes;
- DoUpdateType2("Updating", basefile, type, Path.Combine(outpath, file.Name), false);
- }
-
- // Stub types not in the directory
- foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, null)) {
- if (type.Namespace != ns || seenTypes.ContainsKey(type))
- continue;
-
- XmlElement td = StubType(type, Path.Combine(outpath, GetTypeFileName(type) + ".xml"));
- if (td == null) continue;
- }
- }
private static string GetTypeFileName (TypeReference type)
{
@@ -867,11 +856,6 @@ class MDocUpdater : MDocCommand
index = CreateIndexStub();
}
- string defaultTitle = "Untitled";
- if (assemblies.Count == 1)
- defaultTitle = assemblies[0].Name.Name;
- WriteElementInitialText(index.DocumentElement, "Title", defaultTitle);
-
XmlElement index_types = WriteElement(index.DocumentElement, "Types");
XmlElement index_assemblies = WriteElement(index.DocumentElement, "Assemblies");
if (!IsMultiAssembly)
@@ -880,11 +864,22 @@ class MDocUpdater : MDocCommand
HashSet<string> goodfiles = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
- foreach (AssemblyDefinition assm in assemblies) {
- AddIndexAssembly (assm, index_assemblies);
- DoUpdateAssembly (assm, index_types, source, dest, goodfiles);
+ int processedAssemblyCount = 0;
+ foreach (var assemblySet in assemblies) {
+ using (assemblySet) {
+ foreach (AssemblyDefinition assm in assemblySet.Assemblies) {
+ AddIndexAssembly (assm, index_assemblies);
+ DoUpdateAssembly (assemblySet, assm, index_types, source, dest, goodfiles);
+ processedAssemblyCount++;
+ }
+ }
}
+ string defaultTitle = "Untitled";
+ if (processedAssemblyCount == 1)
+ defaultTitle = assemblies[0].Assemblies.First ().Name.Name;
+ WriteElementInitialText (index.DocumentElement, "Title", defaultTitle);
+
SortIndexEntries (index_types);
CleanupFiles (dest, goodfiles);
@@ -897,14 +892,18 @@ class MDocUpdater : MDocCommand
private static char[] InvalidFilenameChars = {'\\', '/', ':', '*', '?', '"', '<', '>', '|'};
- private void DoUpdateAssembly (AssemblyDefinition assembly, XmlElement index_types, string source, string dest, HashSet<string> goodfiles)
+ private void DoUpdateAssembly (AssemblySet assemblySet, AssemblyDefinition assembly, XmlElement index_types, string source, string dest, HashSet<string> goodfiles)
{
+ var frameworkEntry = frameworks.StartProcessingAssembly (assembly);
+
foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, null)) {
string typename = GetTypeFileName(type);
- if (!IsPublic (type) || typename.IndexOfAny (InvalidFilenameChars) >= 0 || forwardedTypes.Contains (type.FullName))
+ if (!IsPublic (type) || typename.IndexOfAny (InvalidFilenameChars) >= 0 || assemblySet.ContainsForwardedType (type.FullName))
continue;
- string reltypepath = DoUpdateType (type, source, dest);
+ var typeEntry = frameworkEntry.ProcessType (type);
+
+ string reltypepath = DoUpdateType (type, typeEntry, source, dest);
if (reltypepath == null)
continue;
@@ -1030,7 +1029,7 @@ class MDocUpdater : MDocCommand
private void CleanupFiles (string dest, HashSet<string> goodfiles)
{
// Look for files that no longer correspond to types
- foreach (System.IO.DirectoryInfo nsdir in new System.IO.DirectoryInfo(dest).GetDirectories("*")) {
+ foreach (System.IO.DirectoryInfo nsdir in new System.IO.DirectoryInfo(dest).GetDirectories("*").Where(d => Path.GetFileName(d.FullName) != "FrameworksIndex")) {
foreach (System.IO.FileInfo typefile in nsdir.GetFiles("*.xml")) {
string relTypeFile = Path.Combine(nsdir.Name, typefile.Name);
if (!goodfiles.Contains (relTypeFile)) {
@@ -1043,17 +1042,22 @@ class MDocUpdater : MDocCommand
continue;
}
string assemblyName = assemblyNameNode.InnerText;
- AssemblyDefinition assembly = assemblies.FirstOrDefault (a => a.Name.Name == assemblyName);
+
Action saveDoc = () => {
using (TextWriter writer = OpenWrite (typefile.FullName, FileMode.Truncate))
WriteXml(doc.DocumentElement, writer);
};
- if (e != null && !no_assembly_versions && assembly != null && assemblyName != null && UpdateAssemblyVersions (e, assembly, GetAssemblyVersions(assemblyName), false)) {
- saveDoc ();
- goodfiles.Add (relTypeFile);
- continue;
+ if (!IsMultiAssembly) { // only do this for "regular" runs
+ AssemblyDefinition assembly = assemblies
+ .SelectMany (aset => aset.Assemblies)
+ .FirstOrDefault (a => a.Name.Name == assemblyName);
+ if (e != null && !no_assembly_versions && assembly != null && assemblyName != null && UpdateAssemblyVersions (e, assembly, GetAssemblyVersions (assemblyName), false)) {
+ saveDoc ();
+ goodfiles.Add (relTypeFile);
+ continue;
+ }
}
Action actuallyDelete = () => {
@@ -1120,7 +1124,7 @@ class MDocUpdater : MDocCommand
private string[] GetAssemblyVersions (string assemblyName)
{
- return (from a in assemblies
+ return (from a in assemblies.SelectMany(aset => aset.Assemblies)
where a.Name.Name == assemblyName
select GetAssemblyVersion (a)).ToArray ();
}
@@ -1180,7 +1184,7 @@ class MDocUpdater : MDocCommand
static readonly XmlNodeComparer DefaultExtensionMethodComparer = new ExtensionMethodComparer ();
- public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition type, string output, bool insertSince)
+ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition type, FrameworkTypeEntry typeEntry, string output, bool insertSince)
{
Console.WriteLine(message + ": " + type.FullName);
@@ -1236,13 +1240,16 @@ class MDocUpdater : MDocCommand
}
// Update signature information
- UpdateMember(info);
+ UpdateMember(info, typeEntry);
// get all apistyles of sig from info.Node
var styles = oldmember.GetElementsByTagName ("MemberSignature").Cast<XmlElement> ()
.Where (x => x.GetAttribute ("Language") == "C#" && !seenmembers.ContainsKey(x.GetAttribute("Value")))
.Select (x => x.GetAttribute ("Value"));
+
+ typeEntry.ProcessMember (info.Member);
+
foreach (var stylesig in styles) {
seenmembers.Add (stylesig, oldmember);
}
@@ -1284,7 +1291,7 @@ class MDocUpdater : MDocCommand
})
.ToArray();
foreach (MemberReference m in typemembers) {
- XmlElement mm = MakeMember(basefile, new DocsNodeInfo (null, m));
+ XmlElement mm = MakeMember(basefile, new DocsNodeInfo (null, m), typeEntry);
if (mm == null) continue;
if (MDocUpdater.SwitchingToMagicTypes || MDocUpdater.HasDroppedNamespace (m)) {
@@ -1294,7 +1301,6 @@ class MDocUpdater : MDocCommand
}
members.AppendChild( mm );
-
Console.WriteLine("Member Added: " + mm.SelectSingleNode("MemberSignature/@Value").InnerText);
additions++;
}
@@ -1539,7 +1545,9 @@ class MDocUpdater : MDocCommand
XmlElement root = doc.CreateElement("Type");
doc.AppendChild (root);
- DoUpdateType2 ("New Type", doc, type, output, true);
+ var frameworkEntry = frameworks.StartProcessingAssembly (type.Module.Assembly);
+ var typeEntry = frameworkEntry.ProcessType (type);
+ DoUpdateType2 ("New Type", doc, type, typeEntry, output, true);
return root;
}
@@ -1746,11 +1754,11 @@ class MDocUpdater : MDocCommand
return l;
}
- private void UpdateMember (DocsNodeInfo info)
+ private void UpdateMember (DocsNodeInfo info, FrameworkTypeEntry typeEntry)
{
XmlElement me = (XmlElement) info.Node;
MemberReference mi = info.Member;
-
+ typeEntry.ProcessMember (mi);
foreach (MemberFormatter f in memberFormatters) {
string element = "MemberSignature[@Language='" + f.Language + "']";
@@ -1766,7 +1774,6 @@ class MDocUpdater : MDocCommand
return newNode;
},
mi);
-
}
WriteElementText(me, "MemberType", GetMemberType(mi));
@@ -2048,8 +2055,13 @@ class MDocUpdater : MDocCommand
XmlElement targets = member.OwnerDocument.CreateElement ("Targets");
member.PrependChild (targets);
if (!(info.Parameters [0].ParameterType is GenericParameter)) {
- AppendElementAttributeText (targets, "Target", "Type",
- slashdocFormatter.GetDeclaration (info.Parameters [0].ParameterType));
+ var reference = info.Parameters[0].ParameterType;
+ TypeReference typeReference = reference as TypeReference;
+ var declaration = reference != null ?
+ slashdocFormatter.GetDeclaration (typeReference) :
+ slashdocFormatter.GetDeclaration (reference);
+
+ AppendElementAttributeText (targets, "Target", "Type", declaration);
}
else {
GenericParameter gp = (GenericParameter) info.Parameters [0].ParameterType;
@@ -2753,7 +2765,7 @@ class MDocUpdater : MDocCommand
throw new ArgumentException(mi + " is a " + mi.GetType().FullName);
}
- private XmlElement MakeMember(XmlDocument doc, DocsNodeInfo info)
+ private XmlElement MakeMember(XmlDocument doc, DocsNodeInfo info, FrameworkTypeEntry typeEntry)
{
MemberReference mi = info.Member;
if (mi is TypeDefinition) return null;
@@ -2772,7 +2784,7 @@ class MDocUpdater : MDocCommand
me.SetAttribute("MemberName", GetMemberName (mi));
info.Node = me;
- UpdateMember(info);
+ UpdateMember(info, typeEntry);
if (exceptions.HasValue &&
(exceptions.Value & ExceptionLocations.AddedMembers) != 0)
UpdateExceptions (info.Node, info.Member);
@@ -4350,15 +4362,23 @@ public abstract class MemberFormatter {
{
return e.Name;
}
-
- public string GetDeclaration (MemberReference mreference)
+
+ public virtual string GetDeclaration (TypeReference tref)
{
- var typeSpec = mreference as TypeSpecification;
- if (typeSpec != null && typeSpec.Resolve() == null && typeSpec.IsArray && typeSpec.ContainsGenericParameter) {
+ var typeSpec = tref as TypeSpecification;
+ if (typeSpec != null && typeSpec.Resolve () == null && typeSpec.IsArray && typeSpec.ContainsGenericParameter) {
//HACK: there's really no good reference for a generic parameter array, so we're going to use object
return "T:System.Array";
}
+ TypeDefinition def = tref.Resolve ();
+ if (def != null)
+ return GetTypeDeclaration (def);
+ else
+ return GetTypeName (tref);
+ }
+ public virtual string GetDeclaration (MemberReference mreference)
+ {
return GetDeclaration (mreference.Resolve ());
}
@@ -4482,6 +4502,23 @@ public abstract class MemberFormatter {
}
}
+class DocIdFormatter : MemberFormatter
+{
+ public override string Language
+ {
+ get { return "DocId"; }
+ }
+
+ public override string GetDeclaration (TypeReference tref)
+ {
+ return DocCommentId.GetDocCommentId (tref.Resolve ());
+ }
+ public override string GetDeclaration (MemberReference mreference)
+ {
+ return DocCommentId.GetDocCommentId (mreference.Resolve ());
+ }
+}
+
class ILFullMemberFormatter : MemberFormatter {
public override string Language {
diff --git a/mdoc/Mono.Documentation/preserver.cs b/mdoc/Mono.Documentation/preserver.cs
deleted file mode 100644
index 8d1488a5..00000000
--- a/mdoc/Mono.Documentation/preserver.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Command to preserve member documentation for types that are changing in a subsequent version
-// By Joel Martinez <joel.martinez@xamarin.com
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Mono.Options;
-
-namespace Mono.Documentation
-{
- [Obsolete ("This functionality is no longer supported.")]
- public class MDocPreserve : MDocCommand
- {
- MDocUpdater updater;
-
- public MDocPreserve ()
- {
- updater = new MDocUpdater ();
- }
-
- public override void Run (IEnumerable<string> args)
- {
- Message (System.Diagnostics.TraceLevel.Warning, "This functionality is no longer supported, and will be removed in a future release.");
-
- string preserveName = string.Empty;
- var p = new OptionSet () { { "name=",
- "Root {DIRECTORY} to generate/update documentation.",
- v => preserveName = v
- }
- };
-
- updater.PreserveTag = preserveName;
-
- updater.Run (args);
- }
- }
-}
-
diff --git a/mdoc/Test/en.expected-docid/FrameworksIndex/One.xml b/mdoc/Test/en.expected-docid/FrameworksIndex/One.xml
new file mode 100644
index 00000000..a60754a0
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/FrameworksIndex/One.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Framework Name="One">
+ <Namespace Name="MyFramework.MyNamespace">
+ <Type Name="MyFramework.MyNamespace.MyClass" Id="T:MyFramework.MyNamespace.MyClass">
+ <Member Id="M:MyFramework.MyNamespace.MyClass.#ctor" />
+ <Member Id="M:MyFramework.MyNamespace.MyClass.Hello(System.Int32)" />
+ <Member Id="P:MyFramework.MyNamespace.MyClass.MyProperty" />
+ <Member Id="P:MyFramework.MyNamespace.MyClass.OnlyInClassic" />
+ </Type>
+ <Type Name="MyFramework.MyNamespace.MyClassExtensions" Id="T:MyFramework.MyNamespace.MyClassExtensions">
+ <Member Id="M:MyFramework.MyNamespace.MyClassExtensions.AnExtension(MyFramework.MyNamespace.MyClass)" />
+ </Type>
+ </Namespace>
+ <Namespace Name="MyNamespace">
+ <Type Name="MyNamespace.MyClass" Id="T:MyNamespace.MyClass">
+ <Member Id="M:MyNamespace.MyClass.#ctor" />
+ <Member Id="M:MyNamespace.MyClass.SomeMethod``1" />
+ </Type>
+ </Namespace>
+</Framework> \ No newline at end of file
diff --git a/mdoc/Test/en.expected-docid/FrameworksIndex/Two.xml b/mdoc/Test/en.expected-docid/FrameworksIndex/Two.xml
new file mode 100644
index 00000000..cd43c153
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/FrameworksIndex/Two.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Framework Name="Two">
+ <Namespace Name="MyFramework.MyOtherNamespace">
+ <Type Name="MyFramework.MyOtherNamespace.MyOtherClass" Id="T:MyFramework.MyOtherNamespace.MyOtherClass">
+ <Member Id="M:MyFramework.MyOtherNamespace.MyOtherClass.#ctor" />
+ <Member Id="M:MyFramework.MyOtherNamespace.MyOtherClass.Hello(System.Int32)" />
+ <Member Id="P:MyFramework.MyOtherNamespace.MyOtherClass.MyProperty" />
+ </Type>
+ </Namespace>
+ <Namespace Name="MyNamespace">
+ <Type Name="MyNamespace.MyClass" Id="T:MyNamespace.MyClass">
+ <Member Id="M:MyNamespace.MyClass.#ctor" />
+ <Member Id="M:MyNamespace.MyClass.SomeMethod``1" />
+ </Type>
+ </Namespace>
+</Framework> \ No newline at end of file
diff --git a/mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClass.xml b/mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClass.xml
new file mode 100644
index 00000000..11a86064
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClass.xml
@@ -0,0 +1,92 @@
+<Type Name="MyClass" FullName="MyFramework.MyNamespace.MyClass">
+ <TypeSignature Language="C#" Value="public class MyClass" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MyClass extends System.Object" />
+ <TypeSignature Language="DocId" Value="T:MyFramework.MyNamespace.MyClass" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MyClass ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyFramework.MyNamespace.MyClass.#ctor" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Hello">
+ <MemberSignature Language="C#" Value="public float Hello (int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance float32 Hello(int32 value) cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyFramework.MyNamespace.MyClass.Hello(System.Int32)" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Single</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MyProperty">
+ <MemberSignature Language="C#" Value="public string MyProperty { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string MyProperty" />
+ <MemberSignature Language="DocId" Value="P:MyFramework.MyNamespace.MyClass.MyProperty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnlyInClassic">
+ <MemberSignature Language="C#" Value="public double OnlyInClassic { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 OnlyInClassic" />
+ <MemberSignature Language="DocId" Value="P:MyFramework.MyNamespace.MyClass.OnlyInClassic" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClassExtensions.xml b/mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClassExtensions.xml
new file mode 100644
index 00000000..d33261e8
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/MyFramework.MyNamespace/MyClassExtensions.xml
@@ -0,0 +1,41 @@
+<Type Name="MyClassExtensions" FullName="MyFramework.MyNamespace.MyClassExtensions">
+ <TypeSignature Language="C#" Value="public static class MyClassExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit MyClassExtensions extends System.Object" />
+ <TypeSignature Language="DocId" Value="T:MyFramework.MyNamespace.MyClassExtensions" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="AnExtension">
+ <MemberSignature Language="C#" Value="public static bool AnExtension (this MyFramework.MyNamespace.MyClass value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AnExtension(class MyFramework.MyNamespace.MyClass value) cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyFramework.MyNamespace.MyClassExtensions.AnExtension(MyFramework.MyNamespace.MyClass)" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="MyFramework.MyNamespace.MyClass" RefType="this" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-docid/MyFramework.MyOtherNamespace/MyOtherClass.xml b/mdoc/Test/en.expected-docid/MyFramework.MyOtherNamespace/MyOtherClass.xml
new file mode 100644
index 00000000..3b23719c
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/MyFramework.MyOtherNamespace/MyOtherClass.xml
@@ -0,0 +1,74 @@
+<Type Name="MyOtherClass" FullName="MyFramework.MyOtherNamespace.MyOtherClass">
+ <TypeSignature Language="C#" Value="public class MyOtherClass" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MyOtherClass extends System.Object" />
+ <TypeSignature Language="DocId" Value="T:MyFramework.MyOtherNamespace.MyOtherClass" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MyOtherClass ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyFramework.MyOtherNamespace.MyOtherClass.#ctor" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Hello">
+ <MemberSignature Language="C#" Value="public float Hello (int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance float32 Hello(int32 value) cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyFramework.MyOtherNamespace.MyOtherClass.Hello(System.Int32)" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Single</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MyProperty">
+ <MemberSignature Language="C#" Value="public string MyProperty { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string MyProperty" />
+ <MemberSignature Language="DocId" Value="P:MyFramework.MyOtherNamespace.MyOtherClass.MyProperty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-docid/MyNamespace/MyClass.xml b/mdoc/Test/en.expected-docid/MyNamespace/MyClass.xml
new file mode 100644
index 00000000..9fac6c11
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/MyNamespace/MyClass.xml
@@ -0,0 +1,57 @@
+<Type Name="MyClass" FullName="MyNamespace.MyClass">
+ <TypeSignature Language="C#" Value="public class MyClass" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MyClass extends System.Object" />
+ <TypeSignature Language="DocId" Value="T:MyNamespace.MyClass" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-addNonGeneric</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MyClass ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyNamespace.MyClass.#ctor" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-addNonGeneric</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SomeMethod&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public string SomeMethod&lt;T&gt; ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance string SomeMethod&lt;T&gt;() cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyNamespace.MyClass.SomeMethod``1" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-addNonGeneric</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Parameters />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-docid/index.xml b/mdoc/Test/en.expected-docid/index.xml
new file mode 100644
index 00000000..bd4b84cf
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/index.xml
@@ -0,0 +1,73 @@
+<Overview>
+ <Assemblies>
+ <Assembly Name="DocTest-DropNS-classic" Version="0.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ <Assembly Name="DocTest-DropNS-classic-secondary" Version="0.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ <Assembly Name="DocTest-addNonGeneric" Version="0.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ </Assemblies>
+ <Remarks>To be added.</Remarks>
+ <Copyright>To be added.</Copyright>
+ <Types>
+ <Namespace Name="MyFramework.MyNamespace">
+ <Type Name="MyClass" Kind="Class" />
+ <Type Name="MyClassExtensions" Kind="Class" />
+ </Namespace>
+ <Namespace Name="MyFramework.MyOtherNamespace">
+ <Type Name="MyOtherClass" Kind="Class" />
+ </Namespace>
+ <Namespace Name="MyNamespace">
+ <Type Name="MyClass" Kind="Class" />
+ </Namespace>
+ </Types>
+ <Title>Untitled</Title>
+ <ExtensionMethods>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:MyFramework.MyNamespace.MyClass" />
+ </Targets>
+ <Member MemberName="AnExtension">
+ <MemberSignature Language="C#" Value="public static bool AnExtension (this MyFramework.MyNamespace.MyClass value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AnExtension(class MyFramework.MyNamespace.MyClass value) cil managed" />
+ <MemberSignature Language="DocId" Value="M:MyFramework.MyNamespace.MyClassExtensions.AnExtension(MyFramework.MyNamespace.MyClass)" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="MyFramework.MyNamespace.MyClass" RefType="this" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ </Docs>
+ <Link Type="MyFramework.MyNamespace.MyClassExtensions" Member="M:MyFramework.MyNamespace.MyClassExtensions.AnExtension(MyFramework.MyNamespace.MyClass)" />
+ </Member>
+ </ExtensionMethod>
+ </ExtensionMethods>
+</Overview>
diff --git a/mdoc/Test/en.expected-docid/ns-MyFramework.MyNamespace.xml b/mdoc/Test/en.expected-docid/ns-MyFramework.MyNamespace.xml
new file mode 100644
index 00000000..74df75af
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/ns-MyFramework.MyNamespace.xml
@@ -0,0 +1,6 @@
+<Namespace Name="MyFramework.MyNamespace">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/mdoc/Test/en.expected-docid/ns-MyFramework.MyOtherNamespace.xml b/mdoc/Test/en.expected-docid/ns-MyFramework.MyOtherNamespace.xml
new file mode 100644
index 00000000..8bdef1c7
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/ns-MyFramework.MyOtherNamespace.xml
@@ -0,0 +1,6 @@
+<Namespace Name="MyFramework.MyOtherNamespace">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/mdoc/Test/en.expected-docid/ns-MyNamespace.xml b/mdoc/Test/en.expected-docid/ns-MyNamespace.xml
new file mode 100644
index 00000000..bd8d4316
--- /dev/null
+++ b/mdoc/Test/en.expected-docid/ns-MyNamespace.xml
@@ -0,0 +1,6 @@
+<Namespace Name="MyNamespace">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/mdoc/Test/en.expected-frameworks/FrameworksIndex/One.xml b/mdoc/Test/en.expected-frameworks/FrameworksIndex/One.xml
new file mode 100644
index 00000000..a60754a0
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/FrameworksIndex/One.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Framework Name="One">
+ <Namespace Name="MyFramework.MyNamespace">
+ <Type Name="MyFramework.MyNamespace.MyClass" Id="T:MyFramework.MyNamespace.MyClass">
+ <Member Id="M:MyFramework.MyNamespace.MyClass.#ctor" />
+ <Member Id="M:MyFramework.MyNamespace.MyClass.Hello(System.Int32)" />
+ <Member Id="P:MyFramework.MyNamespace.MyClass.MyProperty" />
+ <Member Id="P:MyFramework.MyNamespace.MyClass.OnlyInClassic" />
+ </Type>
+ <Type Name="MyFramework.MyNamespace.MyClassExtensions" Id="T:MyFramework.MyNamespace.MyClassExtensions">
+ <Member Id="M:MyFramework.MyNamespace.MyClassExtensions.AnExtension(MyFramework.MyNamespace.MyClass)" />
+ </Type>
+ </Namespace>
+ <Namespace Name="MyNamespace">
+ <Type Name="MyNamespace.MyClass" Id="T:MyNamespace.MyClass">
+ <Member Id="M:MyNamespace.MyClass.#ctor" />
+ <Member Id="M:MyNamespace.MyClass.SomeMethod``1" />
+ </Type>
+ </Namespace>
+</Framework> \ No newline at end of file
diff --git a/mdoc/Test/en.expected-frameworks/FrameworksIndex/Two.xml b/mdoc/Test/en.expected-frameworks/FrameworksIndex/Two.xml
new file mode 100644
index 00000000..cd43c153
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/FrameworksIndex/Two.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Framework Name="Two">
+ <Namespace Name="MyFramework.MyOtherNamespace">
+ <Type Name="MyFramework.MyOtherNamespace.MyOtherClass" Id="T:MyFramework.MyOtherNamespace.MyOtherClass">
+ <Member Id="M:MyFramework.MyOtherNamespace.MyOtherClass.#ctor" />
+ <Member Id="M:MyFramework.MyOtherNamespace.MyOtherClass.Hello(System.Int32)" />
+ <Member Id="P:MyFramework.MyOtherNamespace.MyOtherClass.MyProperty" />
+ </Type>
+ </Namespace>
+ <Namespace Name="MyNamespace">
+ <Type Name="MyNamespace.MyClass" Id="T:MyNamespace.MyClass">
+ <Member Id="M:MyNamespace.MyClass.#ctor" />
+ <Member Id="M:MyNamespace.MyClass.SomeMethod``1" />
+ </Type>
+ </Namespace>
+</Framework> \ No newline at end of file
diff --git a/mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClass.xml b/mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClass.xml
new file mode 100644
index 00000000..57e2c54f
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClass.xml
@@ -0,0 +1,87 @@
+<Type Name="MyClass" FullName="MyFramework.MyNamespace.MyClass">
+ <TypeSignature Language="C#" Value="public class MyClass" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MyClass extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MyClass ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Hello">
+ <MemberSignature Language="C#" Value="public float Hello (int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance float32 Hello(int32 value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Single</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MyProperty">
+ <MemberSignature Language="C#" Value="public string MyProperty { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string MyProperty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="OnlyInClassic">
+ <MemberSignature Language="C#" Value="public double OnlyInClassic { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance float64 OnlyInClassic" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Double</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClassExtensions.xml b/mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClassExtensions.xml
new file mode 100644
index 00000000..07333a55
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/MyFramework.MyNamespace/MyClassExtensions.xml
@@ -0,0 +1,39 @@
+<Type Name="MyClassExtensions" FullName="MyFramework.MyNamespace.MyClassExtensions">
+ <TypeSignature Language="C#" Value="public static class MyClassExtensions" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit MyClassExtensions extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName="AnExtension">
+ <MemberSignature Language="C#" Value="public static bool AnExtension (this MyFramework.MyNamespace.MyClass value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AnExtension(class MyFramework.MyNamespace.MyClass value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="MyFramework.MyNamespace.MyClass" RefType="this" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-frameworks/MyFramework.MyOtherNamespace/MyOtherClass.xml b/mdoc/Test/en.expected-frameworks/MyFramework.MyOtherNamespace/MyOtherClass.xml
new file mode 100644
index 00000000..612a9e0e
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/MyFramework.MyOtherNamespace/MyOtherClass.xml
@@ -0,0 +1,70 @@
+<Type Name="MyOtherClass" FullName="MyFramework.MyOtherNamespace.MyOtherClass">
+ <TypeSignature Language="C#" Value="public class MyOtherClass" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MyOtherClass extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MyOtherClass ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="Hello">
+ <MemberSignature Language="C#" Value="public float Hello (int value);" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance float32 Hello(int32 value) cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.Single</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="System.Int32" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="MyProperty">
+ <MemberSignature Language="C#" Value="public string MyProperty { get; set; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance string MyProperty" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-DropNS-classic-secondary</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-frameworks/MyNamespace/MyClass.xml b/mdoc/Test/en.expected-frameworks/MyNamespace/MyClass.xml
new file mode 100644
index 00000000..20a7104b
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/MyNamespace/MyClass.xml
@@ -0,0 +1,54 @@
+<Type Name="MyClass" FullName="MyNamespace.MyClass">
+ <TypeSignature Language="C#" Value="public class MyClass" />
+ <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit MyClass extends System.Object" />
+ <AssemblyInfo>
+ <AssemblyName>DocTest-addNonGeneric</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Base>
+ <BaseTypeName>System.Object</BaseTypeName>
+ </Base>
+ <Interfaces />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ <Members>
+ <Member MemberName=".ctor">
+ <MemberSignature Language="C#" Value="public MyClass ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+ <MemberType>Constructor</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-addNonGeneric</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <Parameters />
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ <Member MemberName="SomeMethod&lt;T&gt;">
+ <MemberSignature Language="C#" Value="public string SomeMethod&lt;T&gt; ();" />
+ <MemberSignature Language="ILAsm" Value=".method public hidebysig instance string SomeMethod&lt;T&gt;() cil managed" />
+ <MemberType>Method</MemberType>
+ <AssemblyInfo>
+ <AssemblyName>DocTest-addNonGeneric</AssemblyName>
+ <AssemblyVersion>0.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>System.String</ReturnType>
+ </ReturnValue>
+ <TypeParameters>
+ <TypeParameter Name="T" />
+ </TypeParameters>
+ <Parameters />
+ <Docs>
+ <typeparam name="T">To be added.</typeparam>
+ <summary>To be added.</summary>
+ <returns>To be added.</returns>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
+ </Members>
+</Type>
diff --git a/mdoc/Test/en.expected-frameworks/index.xml b/mdoc/Test/en.expected-frameworks/index.xml
new file mode 100644
index 00000000..6abf1402
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/index.xml
@@ -0,0 +1,72 @@
+<Overview>
+ <Assemblies>
+ <Assembly Name="DocTest-DropNS-classic" Version="0.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ <Assembly Name="DocTest-DropNS-classic-secondary" Version="0.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ <Assembly Name="DocTest-addNonGeneric" Version="0.0.0.0">
+ <Attributes>
+ <Attribute>
+ <AttributeName>System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute+DebuggingModes.IgnoreSymbolStoreSequencePoints)</AttributeName>
+ </Attribute>
+ <Attribute>
+ <AttributeName>System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows=true)</AttributeName>
+ </Attribute>
+ </Attributes>
+ </Assembly>
+ </Assemblies>
+ <Remarks>To be added.</Remarks>
+ <Copyright>To be added.</Copyright>
+ <Types>
+ <Namespace Name="MyFramework.MyNamespace">
+ <Type Name="MyClass" Kind="Class" />
+ <Type Name="MyClassExtensions" Kind="Class" />
+ </Namespace>
+ <Namespace Name="MyFramework.MyOtherNamespace">
+ <Type Name="MyOtherClass" Kind="Class" />
+ </Namespace>
+ <Namespace Name="MyNamespace">
+ <Type Name="MyClass" Kind="Class" />
+ </Namespace>
+ </Types>
+ <Title>Untitled</Title>
+ <ExtensionMethods>
+ <ExtensionMethod>
+ <Targets>
+ <Target Type="T:MyFramework.MyNamespace.MyClass" />
+ </Targets>
+ <Member MemberName="AnExtension">
+ <MemberSignature Language="C#" Value="public static bool AnExtension (this MyFramework.MyNamespace.MyClass value);" />
+ <MemberSignature Language="ILAsm" Value=".method public static hidebysig bool AnExtension(class MyFramework.MyNamespace.MyClass value) cil managed" />
+ <MemberType>ExtensionMethod</MemberType>
+ <ReturnValue>
+ <ReturnType>System.Boolean</ReturnType>
+ </ReturnValue>
+ <Parameters>
+ <Parameter Name="value" Type="MyFramework.MyNamespace.MyClass" RefType="this" />
+ </Parameters>
+ <Docs>
+ <param name="value">To be added.</param>
+ <summary>To be added.</summary>
+ </Docs>
+ <Link Type="MyFramework.MyNamespace.MyClassExtensions" Member="M:MyFramework.MyNamespace.MyClassExtensions.AnExtension(MyFramework.MyNamespace.MyClass)" />
+ </Member>
+ </ExtensionMethod>
+ </ExtensionMethods>
+</Overview>
diff --git a/mdoc/Test/en.expected-frameworks/ns-MyFramework.MyNamespace.xml b/mdoc/Test/en.expected-frameworks/ns-MyFramework.MyNamespace.xml
new file mode 100644
index 00000000..74df75af
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/ns-MyFramework.MyNamespace.xml
@@ -0,0 +1,6 @@
+<Namespace Name="MyFramework.MyNamespace">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/mdoc/Test/en.expected-frameworks/ns-MyFramework.MyOtherNamespace.xml b/mdoc/Test/en.expected-frameworks/ns-MyFramework.MyOtherNamespace.xml
new file mode 100644
index 00000000..8bdef1c7
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/ns-MyFramework.MyOtherNamespace.xml
@@ -0,0 +1,6 @@
+<Namespace Name="MyFramework.MyOtherNamespace">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/mdoc/Test/en.expected-frameworks/ns-MyNamespace.xml b/mdoc/Test/en.expected-frameworks/ns-MyNamespace.xml
new file mode 100644
index 00000000..bd8d4316
--- /dev/null
+++ b/mdoc/Test/en.expected-frameworks/ns-MyNamespace.xml
@@ -0,0 +1,6 @@
+<Namespace Name="MyNamespace">
+ <Docs>
+ <summary>To be added.</summary>
+ <remarks>To be added.</remarks>
+ </Docs>
+</Namespace>
diff --git a/mdoc/mdoc.csproj b/mdoc/mdoc.csproj
index edb21d8b..12281574 100644
--- a/mdoc/mdoc.csproj
+++ b/mdoc/mdoc.csproj
@@ -69,9 +69,13 @@
<Compile Include="Mono.Documentation\XhtmlWriter.cs" />
<Compile Include="Mono.Documentation\exceptions.cs" />
<Compile Include="Mono.Documentation\index.cs" />
- <Compile Include="Mono.Documentation\preserver.cs" />
+ <Compile Include="Mono.Documentation\frameworksbootstrapper.cs" />
<Compile Include="Consts.cs" />
<Compile Include="Options.cs" />
+ <Compile Include="Mono.Documentation\Frameworks\FrameworkIndex.cs" />
+ <Compile Include="Mono.Documentation\Frameworks\FrameworkEntry.cs" />
+ <Compile Include="Mono.Documentation\Frameworks\FrameworkTypeEntry.cs" />
+ <Compile Include="Mono.Documentation\Frameworks\AssemblySet.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\defaulttemplate.xsl">
@@ -110,4 +114,7 @@
<Name>monodoc</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="Mono.Documentation\Frameworks\" />
+ </ItemGroup>
</Project> \ No newline at end of file