diff options
author | Mikhail Melnikov <mikhail_melnikov@epam.com> | 2017-10-25 15:02:52 +0300 |
---|---|---|
committer | Joel Martinez <joelmartinez@gmail.com> | 2017-10-25 17:30:41 +0300 |
commit | bc635e48317843fb126c4be0875d50ab1eeb61db (patch) | |
tree | 3926845a8877ef48d0bab5aa3fd45ad6ef6b4275 /mdoc | |
parent | c173a8b596b5a9dc6d2746dabc7fe46f82478ef7 (diff) |
mdoc: Analytics mode
Added -statistics CLI argument with required parameter <path>.
Statistics module counts how many namespaces/types/members are added/removed/total.
If <path> parameter just points to a folder the default filename "statistics.txt" is appended. If the path can't be resolved a warning message is printed ("mdoc: Unable to save statistics file: Could not find a part of the path 'Z:\'.")
Unit tests for new classes are added; "check-monodocer-fx-statistics-remove" integration test is added, 2 other tests check statistics result file as well.
Closes #100
Diffstat (limited to 'mdoc')
-rw-r--r-- | mdoc/Makefile | 26 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/MDocUpdater.cs | 104 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/Updater/Statistics/StatisticsCollector.cs | 33 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/Updater/Statistics/StatisticsFormatter.cs | 31 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/Updater/Statistics/StatisticsItem.cs | 9 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/Updater/Statistics/StatisticsMetrics.cs | 9 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/Updater/Statistics/StatisticsSaver.cs | 23 | ||||
-rw-r--r-- | mdoc/Mono.Documentation/Updater/Statistics/StatisticsStorage.cs | 30 | ||||
-rw-r--r-- | mdoc/Test/expected_fx_remove_statistics.txt | 14 | ||||
-rw-r--r-- | mdoc/Test/expected_remove_statistics.txt | 14 | ||||
-rw-r--r-- | mdoc/Test/expected_statistics.txt | 28 | ||||
-rw-r--r-- | mdoc/Test/fx-statistics-remove-configuration.xml | 6 | ||||
-rw-r--r-- | mdoc/mdoc.Test/StatisticsTests.cs | 88 | ||||
-rw-r--r-- | mdoc/mdoc.Test/mdoc.Test.csproj | 147 | ||||
-rw-r--r-- | mdoc/mdoc.csproj | 6 |
15 files changed, 485 insertions, 83 deletions
diff --git a/mdoc/Makefile b/mdoc/Makefile index 5bb56f29..e1d23a7e 100644 --- a/mdoc/Makefile +++ b/mdoc/Makefile @@ -227,6 +227,7 @@ check-monodocer-dropns-multi-withexisting: check-monodocer-dropns-delete: -rm -Rf Test/en.actual + -rm -Rf Test/actual_statistics.txt rm -Rf Test/DocTest-DropNS-classic-deletetest.dll rm -Rf Test/DocTest-DropNS-unified-deletetest.dll $(MAKE) Test/DocTest-DropNS-classic-deletetest.dll @@ -236,8 +237,9 @@ check-monodocer-dropns-delete: $(MAKE) Test/DocTest-DropNS-classic-deletetest-V2.dll $(MONO) $(PROGRAM) update --delete --exceptions=all -o Test/en.actual Test/DocTest-DropNS-classic-deletetest.dll --api-style=classic $(MAKE) Test/DocTest-DropNS-unified-deletetest-V2.dll - $(MONO) $(PROGRAM) update --delete --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified-deletetest.dll --api-style=unified --dropns Test/DocTest-DropNS-unified-deletetest.dll=MyFramework + $(MONO) $(PROGRAM) update --delete --exceptions=all -o Test/en.actual Test/DocTest-DropNS-unified-deletetest.dll --api-style=unified --dropns Test/DocTest-DropNS-unified-deletetest.dll=MyFramework -statistics Test/actual_statistics.txt $(DIFF) Test/en.expected-dropns-delete Test/en.actual + $(DIFF) Test/expected_remove_statistics.txt Test/actual_statistics.txt check-monodocer-dropns-classic-withsecondary: # tests case where a secondary assembly is included with a --dropns parameter @@ -364,6 +366,7 @@ check-monodocer-importecmadoc: check-monodocer-import-fx-work: Test/DocTest.dll-v1 Test/DocTest-DropNS-classic-secondary.dll Test/DocTest-DropNS-classic.dll rm -Rf Test/en.actual rm -Rf Test/fx-import + rm -Rf Test/actual_statistics.txt mkdir Test/fx-import mkdir Test/fx-import/one mkdir Test/fx-import/two @@ -375,7 +378,25 @@ check-monodocer-import-fx-work: Test/DocTest.dll-v1 Test/DocTest-DropNS-classic- cp Test/DocTest.xml Test/fx-import/TestEcmaDocs.xml cp Test/CLILibraryTypes.dtd Test/fx-import/ cp Test/fx-import-configuration.xml Test/fx-import/frameworks.xml + $(MONO) $(PROGRAM) update -o Test/en.actual -frameworks Test/fx-import -statistics Test/actual_statistics.txt + $(DIFF) Test/expected_statistics.txt Test/actual_statistics.txt + + +check-monodocer-fx-statistics-remove: + rm -Rf Test/en.actual + rm -Rf Test/fx-import + rm -Rf Test/actual_statistics.txt + mkdir Test/fx-import + mkdir Test/fx-import/one + cp Test/fx-statistics-remove-configuration.xml Test/fx-import/frameworks.xml + $(MAKE) Test/DocTest-DropNS-unified-deletetest.dll + cp Test/DocTest-DropNS-unified-deletetest.dll Test/fx-import/one/DocTest.dll $(MONO) $(PROGRAM) update -o Test/en.actual -frameworks Test/fx-import + $(MAKE) Test/DocTest-DropNS-unified.dll + rm -rf Test/fx-import/one/DocTest.dll + cp Test/DocTest-DropNS-unified.dll Test/fx-import/one/DocTest.dll + $(MONO) $(PROGRAM) update -o Test/en.actual -frameworks Test/fx-import -statistics Test/actual_statistics.txt + $(DIFF) Test/expected_fx_remove_statistics.txt Test/actual_statistics.txt .PHONY: check-monodocer-import-fx check-monodocer-import-fx: check-monodocer-import-fx-work @@ -498,7 +519,8 @@ check-doc-tools: check-monodocer-since \ check-monodocer-frameworks \ check-monodocer-frameworks-inheritance \ check-monodocer-docid \ - check-monodocer-operators + check-monodocer-operators \ + check-monodocer-fx-statistics-remove check-doc-tools-update: check-monodocer-since-update \ check-monodocer-importecmadoc-update \ diff --git a/mdoc/Mono.Documentation/MDocUpdater.cs b/mdoc/Mono.Documentation/MDocUpdater.cs index d789e9af..8a347c72 100644 --- a/mdoc/Mono.Documentation/MDocUpdater.cs +++ b/mdoc/Mono.Documentation/MDocUpdater.cs @@ -12,14 +12,15 @@ using System.Xml.XPath; using Mono.Cecil; using Mono.Documentation.Updater; -using Mono.Documentation.Updater.Frameworks;
+using Mono.Documentation.Updater.Frameworks; +using Mono.Documentation.Updater.Statistics; using Mono.Documentation.Util; using Mono.Options; using MyXmlNodeList = System.Collections.Generic.List<System.Xml.XmlNode>; using StringList = System.Collections.Generic.List<string>; using StringToXmlNodeMap = System.Collections.Generic.Dictionary<string, System.Xml.XmlNode>; -
+ namespace Mono.Documentation { class MDocUpdater : MDocCommand @@ -63,6 +64,8 @@ namespace Mono.Documentation public static string droppedNamespace = string.Empty; + private HashSet<string> memberSet; + public static bool HasDroppedNamespace (TypeDefinition forType) { return HasDroppedNamespace (forType.Module); @@ -102,11 +105,16 @@ namespace Mono.Documentation string FrameworksPath = string.Empty; FrameworkIndex frameworks; FrameworkIndex frameworksCache; + IEnumerable<XDocument> oldFrameworkXmls; + + private StatisticsCollector statisticsCollector = new StatisticsCollector(); static List<string> droppedAssemblies = new List<string> (); public string PreserveTag { get; set; } public bool DisableSearchDirectoryRecurse = false; + private bool statisticsEnabled = false; + private string statisticsFilePath; public static MDocUpdater Instance { get; private set; } public static bool SwitchingToMagicTypes { get; private set; } @@ -129,7 +137,10 @@ namespace Mono.Documentation " for NEW types/members\n" + "If nothing is specified, then only exceptions from the member will " + "be listed.", - v => exceptions = ParseExceptionLocations (v) }, + v => + { + exceptions = ParseExceptionLocations(v); + } }, { "f=", "Specify a {FLAG} to alter behavior. See later -f* options for available flags.", v => { @@ -205,6 +216,15 @@ namespace Mono.Documentation { "disable-searchdir-recurse", "Default behavior for adding search directories ('-L') is to recurse them and search in all subdirectories. This disables that", v => DisableSearchDirectoryRecurse = true }, + { + "statistics=", + "Save statistics to the specified file", + v => + { + statisticsEnabled = true; + if (!string.IsNullOrEmpty(v)) + statisticsFilePath = v; + } }, }; var assemblyPaths = Parse (p, args, "update", "[OPTIONS]+ ASSEMBLIES", @@ -235,6 +255,17 @@ namespace Mono.Documentation }) .Where (f => Directory.Exists (f.Path)); + oldFrameworkXmls = fxconfig.Root + .Elements("Framework") + .Select(f => new + { + Name = f.Attribute("Name").Value, + Source = f.Attribute("Source").Value, + XmlPath = Path.Combine(srcPath, "FrameworksIndex", f.Attribute("Source").Value + ".xml"), + }) + .Where(f => File.Exists(f.XmlPath)) + .Select(f => XDocument.Load(f.XmlPath)); + Func<string, string, IEnumerable<string>> getFiles = (string path, string filters) => { return filters @@ -327,6 +358,18 @@ namespace Mono.Documentation if (!string.IsNullOrWhiteSpace (FrameworksPath)) frameworks.WriteToDisk (srcPath); + if (statisticsEnabled) + { + try + { + StatisticsSaver.Save(statisticsCollector, statisticsFilePath); + } + catch (Exception exception) + { + Warning($"Unable to save statistics file: {exception.Message}"); + } + } + Console.WriteLine ("Members Added: {0}, Members Deleted: {1}", additions, deletions); } @@ -554,6 +597,10 @@ namespace Mono.Documentation { foreach (AssemblyDefinition assembly in assemblySet.Assemblies) { + var typeSet = new HashSet<string> (); + var namespacesSet = new HashSet<string> (); + memberSet = new HashSet<string> (); + var frameworkEntry = frameworks.StartProcessingAssembly (assembly, assemblySet.Importers); foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, typenames)) @@ -571,7 +618,14 @@ namespace Mono.Documentation index.Add (assembly); index.Add (type); + + namespacesSet.Add (type.Namespace); + typeSet.Add (type.FullName); } + + statisticsCollector.AddMetric (frameworkEntry.Name, StatisticsItem.Types, StatisticsMetrics.Total, typeSet.Count); + statisticsCollector.AddMetric (frameworkEntry.Name, StatisticsItem.Namespaces, StatisticsMetrics.Total, namespacesSet.Count); + statisticsCollector.AddMetric (frameworkEntry.Name, StatisticsItem.Members, StatisticsMetrics.Total, memberSet.Count); } } } @@ -579,6 +633,7 @@ namespace Mono.Documentation if (index != null) index.Write (); + if (ignore_missing_types) return; @@ -664,8 +719,8 @@ namespace Mono.Documentation // Find the file, if it exists string[] searchLocations = new string[] { - nsname - }; + nsname + }; if (MDocUpdater.HasDroppedNamespace (type)) { @@ -914,8 +969,11 @@ namespace Mono.Documentation private void DoUpdateAssembly (AssemblySet assemblySet, AssemblyDefinition assembly, XmlElement index_types, string source, string dest, HashSet<string> goodfiles) { - var frameworkEntry = frameworks.StartProcessingAssembly (assembly, assemblySet.Importers); + var namespacesSet = new HashSet<string> (); + var typeSet = new HashSet<string> (); + memberSet = new HashSet<string> (); + var frameworkEntry = frameworks.StartProcessingAssembly (assembly, assemblySet.Importers); foreach (TypeDefinition type in docEnum.GetDocumentationTypes (assembly, null)) { string typename = GetTypeFileName (type); @@ -939,6 +997,7 @@ namespace Mono.Documentation } string onsdoc = DocUtils.PathCombine (dest, namespaceToUse + ".xml"); string nsdoc = DocUtils.PathCombine (dest, "ns-" + namespaceToUse + ".xml"); + namespacesSet.Add (namespaceToUse); if (File.Exists (onsdoc)) { File.Move (onsdoc, nsdoc); @@ -946,12 +1005,17 @@ namespace Mono.Documentation if (!File.Exists (nsdoc)) { + statisticsCollector.AddMetric (frameworkEntry.Name, StatisticsItem.Namespaces, StatisticsMetrics.Added); Console.WriteLine ("New Namespace File: " + type.Namespace); WriteNamespaceStub (namespaceToUse, dest); } goodfiles.Add (reltypepath); + typeSet.Add (type.FullName); } + statisticsCollector.AddMetric (frameworkEntry.Name, StatisticsItem.Types, StatisticsMetrics.Total, typeSet.Count); + statisticsCollector.AddMetric (frameworkEntry.Name, StatisticsItem.Namespaces, StatisticsMetrics.Total, namespacesSet.Count); + statisticsCollector.AddMetric (frameworkEntry.Name, StatisticsItem.Members, StatisticsMetrics.Total, memberSet.Count); } private static void SortIndexEntries (XmlElement indexTypes) @@ -1068,6 +1132,7 @@ namespace Mono.Documentation XmlDocument doc = new XmlDocument (); doc.Load (typefile.FullName); XmlElement e = doc.SelectSingleNode ("/Type") as XmlElement; + var typeFullName = e.GetAttribute("FullName"); var assemblyNameNode = doc.SelectSingleNode ("/Type/AssemblyInfo/AssemblyName"); if (assemblyNameNode == null) { @@ -1102,6 +1167,23 @@ namespace Mono.Documentation try { System.IO.File.Delete (newname); } catch (Exception) { Warning ("Unable to delete existing file: {0}", newname); } try { typefile.MoveTo (newname); } catch (Exception) { Warning ("Unable to rename to: {0}", newname); } Console.WriteLine ("Class no longer present; file renamed: " + Path.Combine (nsdir.Name, typefile.Name)); + + // Here we don't know the framwork which contained the removed type. So, we determine it by the old frameworks XML-file + // If there is only one framework, use it as a default value + var defaultFramework = frameworks.Frameworks.SingleOrDefault(); + // If there is no frameworks (no frameworks mode) or there is more than one framework + if (defaultFramework == null) + // Use FrameworkEntry.Empty as the default value (as well as in FrameworkIndex/StartProcessingAssembly) + defaultFramework = FrameworkEntry.Empty; + var frameworkName = defaultFramework.Name; + // Try to find the removed type in the old frameworks XML-file + var frameworkXml = oldFrameworkXmls?.FirstOrDefault + (i => i.XPathSelectElements($"Framework/Namespace/Type[@Name='{typeFullName}']").Any()); + var frameworkNameAttribute = frameworkXml?.Root?.Attribute ("Name"); + // If the removed type is found in the old frameworks XML-file, use this framework name + if (frameworkNameAttribute != null) + frameworkName = frameworkNameAttribute.Value; + statisticsCollector.AddMetric (frameworkName, StatisticsItem.Types, StatisticsMetrics.Removed); }; if (string.IsNullOrWhiteSpace (PreserveTag)) @@ -1242,7 +1324,6 @@ namespace Mono.Documentation public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition type, FrameworkTypeEntry typeEntry, string output, bool insertSince) { Console.WriteLine (message + ": " + type.FullName); - StringToXmlNodeMap seenmembers = new StringToXmlNodeMap (); // Update type metadata @@ -1308,6 +1389,7 @@ namespace Mono.Documentation continue; DeleteMember ("Member Removed", output, oldmember, todelete, type); + statisticsCollector.AddMetric(typeEntry.Framework.Name, StatisticsItem.Members, StatisticsMetrics.Removed); continue; } @@ -1319,13 +1401,16 @@ namespace Mono.Documentation // ignore, already seen } else + { DeleteMember ("Duplicate Member Found", output, oldmember, todelete, type); - + statisticsCollector.AddMetric(typeEntry.Framework.Name, StatisticsItem.Members, StatisticsMetrics.Removed); + } continue; } // Update signature information UpdateMember (info, typeEntry); + memberSet.Add (info.Member.FullName); // get all apistyles of sig from info.Node var styles = oldmember.GetElementsByTagName ("MemberSignature").Cast<XmlElement> () @@ -1394,6 +1479,8 @@ namespace Mono.Documentation mm.AddApiStyle (ApiStyle.Unified); } + statisticsCollector.AddMetric (typeEntry.Framework.Name, StatisticsItem.Members, StatisticsMetrics.Added); + memberSet.Add (m.FullName); Console.WriteLine ("Member Added: " + mm.SelectSingleNode ("MemberSignature/@Value").InnerText); additions++; } @@ -1686,6 +1773,7 @@ namespace Mono.Documentation var frameworkEntry = frameworks.StartProcessingAssembly (type.Module.Assembly, importers); var typeEntry = frameworkEntry.ProcessType (type); DoUpdateType2 ("New Type", doc, type, typeEntry, output, true); + statisticsCollector.AddMetric (typeEntry.Framework.Name, StatisticsItem.Types, StatisticsMetrics.Added); return root; } diff --git a/mdoc/Mono.Documentation/Updater/Statistics/StatisticsCollector.cs b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsCollector.cs new file mode 100644 index 00000000..c5200f10 --- /dev/null +++ b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsCollector.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace Mono.Documentation.Updater.Statistics +{ + /// <summary> + /// The class stores statistics for different frameworks + /// </summary> + public class StatisticsCollector + { + /// <summary> + /// Collected statistics for each framework + /// </summary> + public Dictionary<string, StatisticsStorage> Storages { get; } = + new Dictionary<string, StatisticsStorage>(); + + /// <summary> + /// Change metric value for the item + /// </summary> + /// <param name="framework">The framework name which statistics is being collected</param> + /// <param name="item">The item which metrics value is changing</param> + /// <param name="metrics">The metrics which value is changing</param> + /// <param name="delta">The value by which the metrics value should be changed</param> + public void AddMetric(string framework, StatisticsItem item, StatisticsMetrics metrics, int delta = 1) + { + if (!Storages.ContainsKey(framework)) + { + Storages[framework] = new StatisticsStorage(); + } + + Storages[framework].AddMetric(item, metrics, delta); + } + } +}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Statistics/StatisticsFormatter.cs b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsFormatter.cs new file mode 100644 index 00000000..430807c4 --- /dev/null +++ b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsFormatter.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.Text; + +namespace Mono.Documentation.Updater.Statistics +{ + public static class StatisticsFormatter + { + public static string Format(Dictionary<string, StatisticsStorage> input) + { + var result = new StringBuilder(); + foreach (var statisticsStoragePair in input) + { + var framework = statisticsStoragePair.Key; + var statisticsStorage = statisticsStoragePair.Value; + result.AppendLine($"Framework: {framework}"); + result.AppendLine("--------"); + foreach (var statistics in statisticsStorage.Values) + { + var staticsItem = statistics.Key; + foreach (var statisticsValuePair in statistics.Value) + { + result.AppendLine($"{staticsItem} {statisticsValuePair.Key}: {statisticsValuePair.Value}"); + } + result.AppendLine(); + } + } + + return result.ToString(); + } + } +}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Statistics/StatisticsItem.cs b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsItem.cs new file mode 100644 index 00000000..68ff2e22 --- /dev/null +++ b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsItem.cs @@ -0,0 +1,9 @@ +namespace Mono.Documentation.Updater.Statistics +{ + public enum StatisticsItem + { + Types, + Namespaces, + Members + } +}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Statistics/StatisticsMetrics.cs b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsMetrics.cs new file mode 100644 index 00000000..cef043d7 --- /dev/null +++ b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsMetrics.cs @@ -0,0 +1,9 @@ +namespace Mono.Documentation.Updater.Statistics +{ + public enum StatisticsMetrics + { + Added, + Removed, + Total + } +}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Statistics/StatisticsSaver.cs b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsSaver.cs new file mode 100644 index 00000000..d8c9cc23 --- /dev/null +++ b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsSaver.cs @@ -0,0 +1,23 @@ +using System; +using System.IO; + +namespace Mono.Documentation.Updater.Statistics +{ + public static class StatisticsSaver + { + private const string DefaltStatisticsFileName = "statistics.txt"; + + /// <summary> + /// Save statistics to the file + /// </summary> + /// <param name="statisticsCollector">Statistics values which should be saved</param> + /// <param name="statisticsFilePath">Path to the file where statistics should be saved</param> + public static void Save(StatisticsCollector statisticsCollector, string statisticsFilePath) + { + if (Directory.Exists(statisticsFilePath)) + statisticsFilePath = Path.Combine(statisticsFilePath, DefaltStatisticsFileName); + File.WriteAllText(statisticsFilePath, StatisticsFormatter.Format(statisticsCollector.Storages)); + Console.WriteLine($"Statistics saved to {statisticsFilePath}"); + } + } +}
\ No newline at end of file diff --git a/mdoc/Mono.Documentation/Updater/Statistics/StatisticsStorage.cs b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsStorage.cs new file mode 100644 index 00000000..d7bac0da --- /dev/null +++ b/mdoc/Mono.Documentation/Updater/Statistics/StatisticsStorage.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace Mono.Documentation.Updater.Statistics +{ + /// <summary> + /// The class stores statistics: int value for each StatisticsItem-StatisticsMetrics pair + /// </summary> + public class StatisticsStorage + { + public Dictionary<StatisticsItem, Dictionary<StatisticsMetrics, int>> Values { get; } = new Dictionary<StatisticsItem, Dictionary<StatisticsMetrics, int>>(); + + public StatisticsStorage() + { + foreach (var statisticsItem in Enum.GetValues(typeof(StatisticsItem))) + { + var metrics = Values[(StatisticsItem)statisticsItem] = new Dictionary<StatisticsMetrics, int>(); + foreach (var statisticsMetrics in Enum.GetValues(typeof(StatisticsMetrics))) + { + metrics[(StatisticsMetrics) statisticsMetrics] = 0; + } + } + } + + public void AddMetric(StatisticsItem item, StatisticsMetrics metrics, int delta = 1) + { + Values[item][metrics] += delta; + } + } +}
\ No newline at end of file diff --git a/mdoc/Test/expected_fx_remove_statistics.txt b/mdoc/Test/expected_fx_remove_statistics.txt new file mode 100644 index 00000000..82b80e4d --- /dev/null +++ b/mdoc/Test/expected_fx_remove_statistics.txt @@ -0,0 +1,14 @@ +Framework: One +-------- +Types Added: 0 +Types Removed: 1 +Types Total: 2 + +Namespaces Added: 0 +Namespaces Removed: 0 +Namespaces Total: 1 + +Members Added: 0 +Members Removed: 5 +Members Total: 5 + diff --git a/mdoc/Test/expected_remove_statistics.txt b/mdoc/Test/expected_remove_statistics.txt new file mode 100644 index 00000000..6ba550d0 --- /dev/null +++ b/mdoc/Test/expected_remove_statistics.txt @@ -0,0 +1,14 @@ +Framework: Empty +-------- +Types Added: 0 +Types Removed: 1 +Types Total: 3 + +Namespaces Added: 0 +Namespaces Removed: 0 +Namespaces Total: 1 + +Members Added: 1 +Members Removed: 6 +Members Total: 10 + diff --git a/mdoc/Test/expected_statistics.txt b/mdoc/Test/expected_statistics.txt new file mode 100644 index 00000000..aea1339d --- /dev/null +++ b/mdoc/Test/expected_statistics.txt @@ -0,0 +1,28 @@ +Framework: one +-------- +Types Added: 31 +Types Removed: 0 +Types Total: 31 + +Namespaces Added: 4 +Namespaces Removed: 0 +Namespaces Total: 4 + +Members Added: 127 +Members Removed: 0 +Members Total: 127 + +Framework: two +-------- +Types Added: 3 +Types Removed: 0 +Types Total: 3 + +Namespaces Added: 2 +Namespaces Removed: 0 +Namespaces Total: 2 + +Members Added: 9 +Members Removed: 0 +Members Total: 9 + diff --git a/mdoc/Test/fx-statistics-remove-configuration.xml b/mdoc/Test/fx-statistics-remove-configuration.xml new file mode 100644 index 00000000..47c3a1f5 --- /dev/null +++ b/mdoc/Test/fx-statistics-remove-configuration.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<Frameworks> + <Framework Name="One" Source="One"> + <assemblySearchPath>One</assemblySearchPath> + </Framework> +</Frameworks>
\ No newline at end of file diff --git a/mdoc/mdoc.Test/StatisticsTests.cs b/mdoc/mdoc.Test/StatisticsTests.cs new file mode 100644 index 00000000..222e2ea0 --- /dev/null +++ b/mdoc/mdoc.Test/StatisticsTests.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using NUnit.Framework; + +using Mono.Documentation.Updater.Statistics; + +namespace mdoc.Test +{ + [TestFixture()] + public class StatisticsTests + { + const string FRAMEWORK_NAME = "frameworkName"; + + [Test()] + public void StatisticsStorage_Increment() + { + var statisticsStorage = new StatisticsStorage(); + + statisticsStorage.AddMetric(StatisticsItem.Members, StatisticsMetrics.Added); + + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Members][StatisticsMetrics.Added], 1); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Members][StatisticsMetrics.Removed], 0); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Namespaces][StatisticsMetrics.Added], 0); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Namespaces][StatisticsMetrics.Removed], 0); + } + + [Test()] + public void StatisticsStorage_ManyIncrements() + { + var statisticsStorage = new StatisticsStorage(); + + statisticsStorage.AddMetric(StatisticsItem.Members, StatisticsMetrics.Added); + statisticsStorage.AddMetric(StatisticsItem.Members, StatisticsMetrics.Added); + statisticsStorage.AddMetric(StatisticsItem.Members, StatisticsMetrics.Added); + + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Members][StatisticsMetrics.Added], 3); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Members][StatisticsMetrics.Removed], 0); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Namespaces][StatisticsMetrics.Added], 0); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Namespaces][StatisticsMetrics.Removed], 0); + } + + [Test()] + public void StatisticsStorage_IncrementDelta() + { + var statisticsStorage = new StatisticsStorage(); + + statisticsStorage.AddMetric(StatisticsItem.Members, StatisticsMetrics.Added, 5); + + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Members][StatisticsMetrics.Added], 5); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Members][StatisticsMetrics.Removed], 0); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Namespaces][StatisticsMetrics.Added], 0); + Assert.AreEqual(statisticsStorage.Values[StatisticsItem.Namespaces][StatisticsMetrics.Removed], 0); + } + + [Test()] + public void StatisticsCollector_Increment() + { + var statisticsCollector = new StatisticsCollector(); + + statisticsCollector.AddMetric(FRAMEWORK_NAME, StatisticsItem.Members, StatisticsMetrics.Added); + + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Members][StatisticsMetrics.Added], 1); + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Members][StatisticsMetrics.Removed], 0); + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Namespaces][StatisticsMetrics.Added], 0); + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Namespaces][StatisticsMetrics.Removed], 0); + } + + [Test()] + public void StatisticsCollector_IncrementDelta() + { + var statisticsCollector = new StatisticsCollector(); + + statisticsCollector.AddMetric(FRAMEWORK_NAME, StatisticsItem.Members, StatisticsMetrics.Added, 7); + + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Members][StatisticsMetrics.Added], 7); + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Members][StatisticsMetrics.Removed], 0); + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Namespaces][StatisticsMetrics.Added], 0); + Assert.AreEqual( + statisticsCollector.Storages[FRAMEWORK_NAME].Values[StatisticsItem.Namespaces][StatisticsMetrics.Removed], 0); + } + } +}
\ No newline at end of file diff --git a/mdoc/mdoc.Test/mdoc.Test.csproj b/mdoc/mdoc.Test/mdoc.Test.csproj index 1278af31..a610b28f 100644 --- a/mdoc/mdoc.Test/mdoc.Test.csproj +++ b/mdoc/mdoc.Test/mdoc.Test.csproj @@ -1,77 +1,78 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>{5ADDEFB6-930C-46BC-8B2B-FDE5C7E3B5AD}</ProjectGuid>
- <OutputType>Library</OutputType>
- <RootNamespace>mdoc.Test</RootNamespace>
- <AssemblyName>mdoc.Test</AssemblyName>
- <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug</OutputPath>
- <DefineConstants>DEBUG;</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="nunit.framework">
- <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="Mono.Cecil, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
- <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.dll</HintPath>
- </Reference>
- <Reference Include="Mono.Cecil.Mdb, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
- <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Mdb.dll</HintPath>
- </Reference>
- <Reference Include="Mono.Cecil.Pdb, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
- <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Pdb.dll</HintPath>
- </Reference>
- <Reference Include="Mono.Cecil.Rocks, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
- <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Rocks.dll</HintPath>
- </Reference>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="FormatterTests.cs" />
- <Compile Include="SampleClasses\TestClass.cs" />
- <Compile Include="SampleClasses\TestPrivateClass.cs" />
- <Compile Include="SampleClasses\TestClassTwo.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
- <None Include="cppcli\cppcli\cppcli.h">
- <Link>SampleClasses\cppcli.h</Link>
- </None>
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\mdoc.csproj">
- <Project>{7DA7CD97-614F-4BCD-A2FA-B379590CEA48}</Project>
- <Name>mdoc</Name>
- </ProjectReference>
- <ProjectReference Include="..\..\monodoc\monodoc.csproj">
- <Project>{6E644802-B579-4037-9809-9CF4C7172C9D}</Project>
- <Name>monodoc</Name>
- </ProjectReference>
- </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{5ADDEFB6-930C-46BC-8B2B-FDE5C7E3B5AD}</ProjectGuid> + <OutputType>Library</OutputType> + <RootNamespace>mdoc.Test</RootNamespace> + <AssemblyName>mdoc.Test</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug</OutputPath> + <DefineConstants>DEBUG;</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <Optimize>true</Optimize> + <OutputPath>bin\Release</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="nunit.framework"> + <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Mdb, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Mdb.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Pdb, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Pdb.dll</HintPath> + </Reference> + <Reference Include="Mono.Cecil.Rocks, Version=0.10.0.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Mono.Cecil.0.10.0-beta5\lib\net40\Mono.Cecil.Rocks.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="FormatterTests.cs" /> + <Compile Include="SampleClasses\TestClass.cs" /> + <Compile Include="SampleClasses\TestPrivateClass.cs" /> + <Compile Include="SampleClasses\TestClassTwo.cs" /> + <Compile Include="StatisticsTests.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + <None Include="cppcli\cppcli\cppcli.h"> + <Link>SampleClasses\cppcli.h</Link> + </None> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\mdoc.csproj"> + <Project>{7DA7CD97-614F-4BCD-A2FA-B379590CEA48}</Project> + <Name>mdoc</Name> + </ProjectReference> + <ProjectReference Include="..\..\monodoc\monodoc.csproj"> + <Project>{6E644802-B579-4037-9809-9CF4C7172C9D}</Project> + <Name>monodoc</Name> + </ProjectReference> + </ItemGroup> <ItemGroup>
<Folder Include="SampleClasses\" />
</ItemGroup>
- <ItemGroup>
- <Content Include="cppcli\Debug\cppcli.dll">
- <Link>SampleClasses\cppcli.dll</Link>
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- </ItemGroup>
- <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup> + <Content Include="cppcli\Debug\cppcli.dll"> + <Link>SampleClasses\cppcli.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/mdoc/mdoc.csproj b/mdoc/mdoc.csproj index a1b2ea59..bcf3a3a5 100644 --- a/mdoc/mdoc.csproj +++ b/mdoc/mdoc.csproj @@ -77,6 +77,12 @@ <Compile Include="Mono.Documentation\Updater\EcmaDocumentationEnumerator.cs" />
<Compile Include="Mono.Documentation\Updater\DocumentationEnumerator.cs" />
<Compile Include="Mono.Documentation\Updater\DocsNodeInfo.cs" />
+ <Compile Include="Mono.Documentation\Updater\Statistics\StatisticsCollector.cs" />
+ <Compile Include="Mono.Documentation\Updater\Statistics\StatisticsFormatter.cs" />
+ <Compile Include="Mono.Documentation\Updater\Statistics\StatisticsItem.cs" />
+ <Compile Include="Mono.Documentation\Updater\Statistics\StatisticsMetrics.cs" />
+ <Compile Include="Mono.Documentation\Updater\Statistics\StatisticsSaver.cs" />
+ <Compile Include="Mono.Documentation\Updater\Statistics\StatisticsStorage.cs" />
<Compile Include="Mono.Documentation\Util\ApiStyle.cs" />
<Compile Include="Mono.Documentation\Updater\DocUtils.cs" />
<Compile Include="Mono.Documentation\Util\CecilExtensions.cs" />
|