コード例 #1
0
        public override MatchCollection GetMatches(string patchCode)
        {
            //var regs = Regex.Matches(patchCode, RegexFuncPattern);
            var regs = MethodExtractor.Matches(patchCode);

            return(regs);
        }
コード例 #2
0
        public void SimpleFileStatements()
        {
            var codeInfo = new MethodExtractor().Execute(new SourceCodeFile(@"..\..\..\..\assets\TestData\simpleFile.prg"));

            codeInfo.MethodList[0].StatementList.Should().HaveCount(11);
            codeInfo.MethodList[1].StatementList.Should().HaveCount(11);
        }
コード例 #3
0
    public async System.Threading.Tasks.Task<IEnumerable<CodeAction>> GetRefactoringsAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken)
    {
        if (textSpan.IsEmpty)
        {
            return null;
        }

        if (String.IsNullOrWhiteSpace(document.GetText().GetSubText(textSpan).ToString())) { return null; }

        var tree = (SyntaxTree)document.GetSyntaxTree(cancellationToken);
        var diagnostics = tree.GetDiagnostics(cancellationToken);
        if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error || d.IsWarningAsError)) return null;

        var linespan = tree.GetLocation(textSpan).GetLineSpan(false);
        if (linespan.EndLinePosition.Line <= linespan.StartLinePosition.Line) return null; // single line

        var semanticModel = (SemanticModel)document.GetSemanticModel(cancellationToken);
        var sdiag = semanticModel.GetDiagnostics(cancellationToken);
        if (sdiag == null) return null;
        if (sdiag.Any(d => d.Severity == DiagnosticSeverity.Error || d.IsWarningAsError)) return null;

        var methodExtractor = new MethodExtractor(semanticModel, document, textSpan, this.options);
        var newDocument = methodExtractor.GetRefactoredDocument(cancellationToken);
        if (newDocument == null) return null;
        var action = new ClousotExtractMethodAction(newDocument);
        return new List<CodeAction>{ action };
    }
コード例 #4
0
        public void SimpleFileMethodNames()
        {
            var codeInfo = new MethodExtractor().Execute(new SourceCodeFile(@"..\..\..\..\assets\TestData\simpleFile.prg"));

            codeInfo.MethodList.Should().HaveCount(2);
            codeInfo.MethodList[0].Name.Should().Be("Init");
            codeInfo.MethodList[1].Name.Should().Be("InitCopy");
        }
コード例 #5
0
        public void SimpleFileClassName()
        {
            var codeInfo = new MethodExtractor().Execute(new SourceCodeFile(@"..\..\..\..\assets\TestData\simpleFile.prg"));

            codeInfo.MethodList.Should().HaveCount(2);
            foreach (var method in codeInfo.MethodList)
            {
                method.ClassName.Should().Be("clsTestClass");
            }
        }
コード例 #6
0
    public CodeRefactoring GetRefactoring(Microsoft.CodeAnalysis.Document document, TextSpan textSpan, CancellationToken cancellationToken) {

      var tree = (SyntaxTree)document.GetSyntaxTree(cancellationToken);
      var semanticModel = (SemanticModel)document.GetSemanticModel(cancellationToken);

      var methodExtractor = new MethodExtractor(semanticModel, document, textSpan, this.options);
      var newDocument = methodExtractor.GetRefactoredDocument(cancellationToken);
      if (newDocument == null) return null;
      var action = new ClousotExtractMethodAction(newDocument);
      return new CodeRefactoring(new[] { action });
    }
コード例 #7
0
ファイル: EditFilter.cs プロジェクト: leeohalloran/PTVS
 private void QueryStatusExtractMethod(OLECMD[] prgCmds, int i) {
     switch (MethodExtractor.CanExtract(_textView)) {
         case true:
             prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
             break;
         case false:
             prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_SUPPORTED);
             break;
         case null:
             prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_INVISIBLE);
             break;
     }
 }
コード例 #8
0
        public void TestMethodExtractorSingleFile()
        {
            var baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            var filepath = Path.Combine(baseDir, @"..\..\..\", "testdata", "Sample Methods", "sampleMethods.cpp");

            Console.WriteLine(filepath);

            var methodList = MethodExtractor.ExtractAllMethodsFromFile(filepath).ToList();

            Assert.IsNotEmpty(methodList);
            Console.WriteLine(methodList.ToString());
        }
コード例 #9
0
        void TestMemberCall()
        {
            Expression <Action <MyClass> > lamda = m => m.MyAction(0);
            var method1 = new MethodExtractor().GetMethodInfo <MyClass> (m => m.MyAction(1));
            var newType = typeof(int);

            var method2 = new MethodExtractor().GetMethodInfo <MyClass <string> > (m => m.MyAction(null));
            var method3 = typeof(MyClass <>).MakeGenericType(newType)
                          .GetMethod(method2.Name, method2.GetParameters().Select(p => newType).ToArray());

            var method4  = new MethodExtractor().GetMethodInfo <MyClass> (m => m.MyGenFunction <string> (""));
            var method5  = method4.GetGenericMethodDefinition().MakeGenericMethod(newType);
            var myObject = new MyClass();
            var result5  = method5.Invoke(myObject, new object[] { Activator.CreateInstance(newType) });
        }
コード例 #10
0
        public void AllCodeBlocksFile()
        {
            var codeInfo = new MethodExtractor().Execute(new SourceCodeFile(@"..\..\..\..\assets\TestData\allCodeBlocks.prg"));

            codeInfo.MethodList.Should().HaveCount(10);

            codeInfo.MethodList.Select(q => q.Name).ToList().Should().BeEquivalentTo(
                "AsProperty[Get]",
                "AsProperty[Set]",
                "Operator",
                "AsAccess",
                "AsAssign",
                "AsMethod",
                "Constructor",
                "Destructor",
                "AsFunction",
                "AsProcedure");

            codeInfo.MethodList.Select(q => q.Type).ToList().Should().BeEquivalentTo(
                MethodInfoType.PropertyGet,
                MethodInfoType.PropertySet,
                MethodInfoType.Operator,
                MethodInfoType.Method,
                MethodInfoType.Method,
                MethodInfoType.Method,
                MethodInfoType.Constructor,
                MethodInfoType.Destructor,
                MethodInfoType.FuncProc,
                MethodInfoType.FuncProc);

            codeInfo.MethodList.Select(q => q.ClassName).ToList().Should().BeEquivalentTo(
                "DummyClass",
                "DummyClass",
                "DummyClass",
                "DummyClass",
                "DummyClass",
                "DummyClass",
                "DummyClass",
                "DummyClass",
                "",
                "");

            foreach (var method in codeInfo.MethodList)
            {
                method.StatementList.Should().HaveCount(3);
            }
        }
コード例 #11
0
ファイル: TestPipeline.cs プロジェクト: neostoic/Swummary
        public void TestPipelineWithSourceFile()
        {
            // TODO: rewrite unit test to handle all the methods in a file
            // For now, just pull the first method from the file and proceed as TestPipelineXMLSnipper().
            var srcmlMethod = MethodExtractor.ExtractAllMethodsFromFile("../Sample Methods/sample methods.cpp").First().Item3;

            // Verify the method definition
            Assert.IsInstanceOf <MethodDefinition>(srcmlMethod, "MethodDefinition found.");
            Console.WriteLine(srcmlMethod.ToString());

            // Extract SUnit Statements from MethodDefinition
            var statements = SUnitExtractor.ExtractAll(srcmlMethod).ToList();

            // verify the statements selected
            Assert.IsNotEmpty(statements, "statements selected from method definition");
            Console.WriteLine(statements.ToString());

            // Translate Statements into SUnits
            List <SUnit> sunits = statements.ConvertAll(
                new Converter <Statement, SUnit>(SUnitTranslator.Translate));

            // verify sunits have been translated
            Assert.That(sunits.TrueForAll(s => s.action != null), "All SUnits initialized.");
            Console.WriteLine(sunits.ToString());


            // Generate text from SUnits
            List <string> sentences = sunits.ConvertAll(
                new Converter <SUnit, string>(TextGenerator.GenerateText));

            // verify string generated
            Assert.That(sentences.TrueForAll(s => s.Length > 0));
            Console.WriteLine(sentences);

            // Collect text and summarize
            var methodDocument = String.Join <string>(" ", sentences);
            var summary        = Summarizer.Summarize(methodDocument);


            // verify summary
            Assert.That(!summary.Equals(""));
            Console.WriteLine(summary);
        }
コード例 #12
0
        public void TestMethodExtractorDirectory(string directoryName)
        {
            var baseDir   = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            var targetDir = Path.GetFullPath(Path.Combine(baseDir, @"..\..\..\testdata\", directoryName));

            var methodList = MethodExtractor.ExtractAllMethodsFromDirectory(targetDir).ToList();

            Assert.That(methodList is List <MethodDefinition>);
            Assert.IsNotEmpty(methodList);

            // Generate report on methods extracted
            foreach (var m in methodList)
            {
                var methodName  = m.GetFullName();
                var methodDef   = m.ToString();
                var parentClass = m.GetAncestors <TypeDefinition>();

                Console.WriteLine(String.Format("{0}\t{1}\t{2}", parentClass, methodName, methodDef));
            }
        }
コード例 #13
0
        public List <Duplicate> Execute()
        {
            ProcessUpdate?.Invoke($"Updating Cache ({Configuration.CacheFileName})");

            using (var cacheDB = new CacheDB(Configuration.CacheFileName))
            {
                var methodExtractor = new MethodExtractor();
                var finder          = new DuplicateFinder(Configuration);

                var files = Directory.EnumerateFiles(Configuration.SourceDirectory, "*.prg", SearchOption.AllDirectories).ToList();
                ProcessUpdate?.Invoke($"Found {files.Count} source files");

                var index = 1;
                foreach (var fileName in files)
                {
                    var sourceCodeFile = new SourceCodeFile(fileName);

                    ProcessUpdate?.Invoke($"[{index++} of {files.Count}] {sourceCodeFile.RelativeFileName(Configuration.SourceDirectory)}");

                    try
                    {
                        if (!cacheDB.TryGetValue(sourceCodeFile, out var codeInfo))
                        {
                            codeInfo = methodExtractor.Execute(sourceCodeFile);
                            cacheDB.Add(codeInfo);
                        }
                        finder.AddSourceCodeFile(sourceCodeFile, codeInfo);
                    }
                    catch
                    {
                        ProcessUpdate?.Invoke("File could not be parsed and will be skipped");
                    }
                }

                ProcessUpdate?.Invoke("Identifying duplicates");
                var result = finder.Execute();
                ProcessUpdate?.Invoke($"{(result.Count > 0 ? result.Count.ToString() : "No")} duplicates found");

                return(result);
            }
        }
コード例 #14
0
ファイル: SourceReplacer.cs プロジェクト: dkgv/probe
        public void Replace(RawCode code)
        {
            var notImplementedEmitStrategy = new NotImplementedEmitStrategy();

            var processed = new HashSet <string>();

            MethodDefinition FindUnprocessed()
            {
                // We need to continuously extract methods if a modification changes indexing
                var definitions = MethodExtractor.ExtractMethods(code);

                return(definitions.FirstOrDefault(definition => !processed.Contains(definition.Signature)));
            }

            MethodDefinition next;

            while ((next = FindUnprocessed()) != default)
            {
                var bodyLineStart = next.MethodBody.LineStartIndex;
                var bodyLineEnd   = next.MethodBody.LineEndIndex;

                switch (next.Declaration.Variant)
                {
                case MethodVariant.FullMethod:
                    if (next.MethodBody.NumLines == 0)
                    {
                        continue;
                    }

                    var lines = new List <string>(next.MethodBody.NumLines);
                    for (var i = 0; i < next.MethodBody.NumLines; i++)
                    {
                        lines.Add(EmitStrategy.Emit);
                    }

                    lines[^ 1] = notImplementedEmitStrategy.Emit;
コード例 #15
0
ファイル: Summary.cs プロジェクト: bjzz/moma
        static void Main0(string[] args)
        {
            string output_path = Path.GetDirectoryName(Application.ExecutablePath);

            // Get the assemblies we want to examine
            List <string> mono_assemblies = AssemblyManager.GetAssemblies(true, use_20, use_30, use_35, use_design, mwf_only);
            List <string> ms_assemblies   = AssemblyManager.GetAssemblies(false, use_20, use_30, use_35, use_design, mwf_only);

            StreamWriter sw = new StreamWriter(Path.Combine(output_path, "summary.txt"));

            foreach (string assembly in ms_assemblies)
            {
                SortedList <string, Method> ms_all  = new SortedList <string, Method> ();
                SortedList <string, Method> missing = new SortedList <string, Method> ();

                // Get all methods in MS assembly
                MethodExtractor.ExtractFromAssembly(assembly, ms_all, null, null);
                string file = Path.GetFileName(assembly);

                // We only want MS method counts
                if (count_only)
                {
                    sw.WriteLine("{0}: {1}", file, ms_all.Count);
                    continue;
                }

                // Find the matching Mono assembly
                string mono_file = string.Empty;

                foreach (string s in mono_assemblies)
                {
                    if (s.ToLower().Contains(file.ToLower()))
                    {
                        mono_file = s;
                    }
                }

                if (string.IsNullOrEmpty(mono_file))
                {
                    sw.WriteLine("No Mono assembly found for " + file);
                    continue;
                }

                // Do the MoMA extracts/compares, and output the results
                SortedList <string, Method> all  = new SortedList <string, Method> ();
                SortedList <string, Method> todo = new SortedList <string, Method> ();
                SortedList <string, Method> nie  = new SortedList <string, Method> ();

                MethodExtractor.ExtractFromAssembly(mono_file, all, nie, todo);

                SortedList <string, Method> final_todo = new SortedList <string, Method> ();

                foreach (string s in todo.Keys)
                {
                    if (ms_all.ContainsKey(s))
                    {
                        final_todo[s] = todo[s];
                    }
                }

                sw.WriteLine(file);
                sw.WriteLine(string.Format("TODO: {0}", final_todo.Count));

                SortedList <string, Method> final_nie = new SortedList <string, Method> ();

                foreach (string s in nie.Keys)
                {
                    if (ms_all.ContainsKey(s))
                    {
                        final_nie[s] = nie[s];
                    }
                }

                sw.WriteLine(string.Format("NIEX: {0}", final_nie.Count));

                MethodExtractor.ComputeMethodDifference(ms_all, all, missing, true);
                sw.WriteLine(string.Format("MISS: {0}", missing.Count));
            }

            sw.Close();
            sw.Dispose();

            Console.WriteLine("done");
            Console.ReadLine();
        }
コード例 #16
0
ファイル: Program.cs プロジェクト: yumatchlab/moma
        private static bool mwf_only   = false;         // Only do System.Windows.Forms (overrides others)

        static void Main(string[] args)
        {
            string output_path = Path.GetDirectoryName(Application.ExecutablePath);

            // Get the assemblies we want to examine
            List <string> mono_assemblies = AssemblyManager.GetAssemblies(true, use_20, use_30, use_35, use_40, use_mobile, use_design, mwf_only);
            List <string> ms_assemblies   = AssemblyManager.GetAssemblies(false, use_20, use_30, use_35, use_40, use_mobile, use_design, mwf_only);

            // Extract all methods from the MS assemblies
            SortedList <string, Method> ms_all = new SortedList <string, Method> ();

            foreach (string assembly in ms_assemblies)
            {
                MethodExtractor.ExtractFromAssembly(assembly, ms_all, null, null);
            }

            // Extract all, NIEX, and TODO methods from Mono assemblies
            SortedList <string, Method> missing = new SortedList <string, Method> ();
            SortedList <string, Method> all     = new SortedList <string, Method> ();
            SortedList <string, Method> todo    = new SortedList <string, Method> ();
            SortedList <string, Method> nie     = new SortedList <string, Method> ();

            foreach (string assembly in mono_assemblies)
            {
                MethodExtractor.ExtractFromAssembly(assembly, all, nie, todo);
            }

            // Only report the TODO's that are also in MS's assemblies
            SortedList <string, Method> final_todo = new SortedList <string, Method> ();

            foreach (string s in todo.Keys)
            {
                if (ms_all.ContainsKey(s))
                {
                    final_todo[s] = todo[s];
                }
            }

            WriteListToFile(final_todo, Path.Combine(output_path, "monotodo.txt"), true);

            // Only report the NIEX's that are also in MS's assemblies
            SortedList <string, Method> final_nie = new SortedList <string, Method> ();

            foreach (string s in nie.Keys)
            {
                if (ms_all.ContainsKey(s))
                {
                    final_nie[s] = nie[s];
                }
            }

            WriteListToFile(final_nie, Path.Combine(output_path, "exception.txt"), false);

            // Write methods that are both TODO and NIEX
            SortedList <string, Method> todo_niex = new SortedList <string, Method> ();

            foreach (string s in nie.Keys)
            {
                if (todo.ContainsKey(s))
                {
                    todo_niex.Add(s, todo[s]);
                }
            }

            WriteListToFile(todo_niex, Path.Combine(output_path, "dupe.txt"), true);

            // Find methods that exist in MS but not in Mono (Missing methods)
            MethodExtractor.ComputeMethodDifference(ms_all, all, missing, use_design);

            WriteListToFile(missing, Path.Combine(output_path, "missing.txt"), false);

            Console.WriteLine("done");
            Console.ReadLine();
        }
コード例 #17
0
ファイル: TestPipeline.cs プロジェクト: neostoic/Swummary
        public void TestPipelineWithSourceDirectory(string directoryName)
        {
            var currentDirectory = Path.GetFullPath(Assembly.GetExecutingAssembly().Location);
            var sourceDirectory  = Path.GetFullPath(Path.Combine(currentDirectory,
                                                                 @"..\..\..\..\testData\", directoryName));

            var srcmlMethods = MethodExtractor.ExtractAllMethodsFromDirectory(sourceDirectory);

            foreach (var methodDef in srcmlMethods)
            {
                // Print Class and Method Name
                Console.WriteLine("*************************\n\n{0}\n*************************",
                                  methodDef.GetFullName());

                // Extract SUnit Statements from MethodDefinition
                var statements = SUnitExtractor.ExtractAll(methodDef).ToList();

                // verify the statements selected
                //Assert.IsNotEmpty(statements, "statements selected from method definition");

                /*
                 * foreach (var s in statements)
                 * {
                 *  Console.WriteLine(statements.ToString());
                 * }
                 */

                // Translate Statements into SUnits
                List <SUnit> sunits = statements.ConvertAll(
                    new Converter <Statement, SUnit>(SUnitTranslator.Translate));

                // verify sunits have been translated
                Assert.That(sunits.TrueForAll(s => s.action != null), "All SUnits initialized.");

                /*
                 * foreach (var s in sunits)
                 * {
                 *  Console.WriteLine(s);
                 * }
                 */


                // Generate text from SUnits
                List <string> sentences = sunits.ConvertAll(
                    new Converter <SUnit, string>(TextGenerator.GenerateText));

                // verify string generated

                /*
                 * Assert.That(sentences.TrueForAll(s => s.Length > 0));
                 * foreach (var s in sentences)
                 * {
                 *  Console.WriteLine(s);
                 * }
                 */


                // Collect text and summarize
                var methodDocument = String.Join <string>("\n", sentences);

                // Actually, lets skip the summary for now
                Console.WriteLine(methodDocument);

                /*
                 * var summary = Summarizer.Summarize(methodDocument);
                 *
                 * // verify summary
                 * Assert.That(!summary.Equals(""));
                 * Console.WriteLine(summary);
                 */
            }
        }
コード例 #18
0
        public static void Analyze(Versions version, bool count_only)
        {
            // Parameters to fiddle with
            bool use_20     = version == Versions.v20;         // Include the 2.0 framework
            bool use_30     = version == Versions.v30;         // Include the 3.0 framework
            bool use_35     = version == Versions.v35;         // Include the 3.5 framework
            bool use_40     = version == Versions.v40;         // Include the 4.0 framework
            bool use_45     = version == Versions.v45;         // Include the 4.0 framework
            bool use_451    = version == Versions.v451;        // Include the 4.0 framework
            bool use_452    = version == Versions.v452;        // Include the 4.0 framework
            bool use_46     = version == Versions.v46;         // Include the 4.0 framework
            bool use_461    = version == Versions.v461;        // Include the 4.0 framework
            bool use_462    = version == Versions.v462;        // Include the 4.0 framework
            bool use_47     = version == Versions.v47;         // Include the 4.0 framework
            bool use_mobile = version == Versions.Mobile;

            bool use_design = true;                         // Include *Design namespaces
            bool mwf_only   = version == Versions.WinForms; // Only do System.Windows.Forms (overrides others)

            string output_path = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Definitions");

            Console.Clear();

            // Get the assemblies we want to examine
            List <string> mono_assemblies = AssemblyManager.GetAssemblies(true, use_20, use_30, use_35, use_40, use_45, use_451, use_452, use_46, use_461, use_462, use_47, use_mobile, use_design, mwf_only);
            List <string> ms_assemblies   = AssemblyManager.GetAssemblies(false, use_20, use_30, use_35, use_40, use_45, use_451, use_452, use_46, use_461, use_462, use_47, use_mobile, use_design, mwf_only);

            string displayVersion;

            switch (version)
            {
            case Versions.v20: displayVersion = "2.0"; break;

            case Versions.v30: displayVersion = "3.0"; break;

            case Versions.v35: displayVersion = "3.5"; break;

            case Versions.v40: displayVersion = "4.0"; break;

            case Versions.v45: displayVersion = "4.5"; break;

            case Versions.v451: displayVersion = "4.5.1"; break;

            case Versions.v452: displayVersion = "4.5.2"; break;

            case Versions.v46: displayVersion = "4.6"; break;

            case Versions.v461: displayVersion = "4.6.1"; break;

            case Versions.v462: displayVersion = "4.6.2"; break;

            case Versions.v47: displayVersion = "4.7"; break;

            case Versions.Mobile: displayVersion = "Mobile"; break;

            default: displayVersion = version.ToString(); break;
            }

            var procInfo = new ProcessStartInfo(MonoBin, "-V")
            {
                RedirectStandardOutput = true,
                CreateNoWindow         = true,
                UseShellExecute        = false
            };
            var monoproc    = Process.Start(procInfo);
            var res         = monoproc.StandardOutput.ReadToEnd();
            var monoVersion = Regex.Match(res, "[0-9.]+").Value;
            var monoName    = $"{monoVersion}-{displayVersion}-defs";

            Console.CursorTop = 0;
            Console.WriteLine();
            Console.WriteLine($"Analyzing for .Mono {monoVersion} ({displayVersion} Profile)...");

            output_path = Path.Combine(output_path, monoName);

            if (!Directory.Exists(output_path))
            {
                Directory.CreateDirectory(output_path);
            }

            // Extract all methods from the MS assemblies
            SortedList <string, Method> ms_all = new SortedList <string, Method> ();

            Console.CursorTop = 3;
            Console.WriteLine(".NET Assemblies:                                  ");
            foreach (string assembly in ms_assemblies)
            {
                Console.CursorTop = 5;
                MethodExtractor.ExtractFromAssembly(assembly, ms_all, null, null);
            }

            // Extract all, NIEX, and TODO methods from Mono assemblies
            SortedList <string, Method> missing = new SortedList <string, Method> ();
            SortedList <string, Method> all     = new SortedList <string, Method> ();
            SortedList <string, Method> todo    = new SortedList <string, Method> ();
            SortedList <string, Method> nie     = new SortedList <string, Method> ();

            Console.CursorTop = 3;
            Console.WriteLine("Mono Assemblies:                              ");
            foreach (string assembly in mono_assemblies)
            {
                Console.CursorTop = 5;
                MethodExtractor.ExtractFromAssembly(assembly, all, nie, todo);
            }

            // Only report the TODO's that are also in MS's assemblies
            SortedList <string, Method> final_todo = new SortedList <string, Method> ();

            foreach (string s in todo.Keys)
            {
                if (ms_all.ContainsKey(s))
                {
                    final_todo[s] = todo[s];
                }
            }

            var monotodoTxt = Path.Combine(output_path, "monotodo.txt");

            WriteListToFile(final_todo, monotodoTxt, true);

            // Only report the NIEX's that are also in MS's assemblies
            SortedList <string, Method> final_nie = new SortedList <string, Method> ();

            foreach (string s in nie.Keys)
            {
                if (ms_all.ContainsKey(s))
                {
                    final_nie[s] = nie[s];
                }
            }

            var exceptionTxt = Path.Combine(output_path, "exception.txt");

            WriteListToFile(final_nie, exceptionTxt, false);

            // Write methods that are both TODO and NIEX
            SortedList <string, Method> todo_niex = new SortedList <string, Method> ();

            foreach (string s in nie.Keys)
            {
                if (todo.ContainsKey(s))
                {
                    todo_niex.Add(s, todo[s]);
                }
            }

            var dupeTxt = Path.Combine(output_path, "dupe.txt");

            WriteListToFile(todo_niex, dupeTxt, true);

            // Find methods that exist in MS but not in Mono (Missing methods)
            MethodExtractor.ComputeMethodDifference(ms_all, all, missing, use_design);

            var missingTxt = Path.Combine(output_path, "missing.txt");

            WriteListToFile(missing, missingTxt, false);

            // summary

            Console.CursorTop = 3;
            Console.WriteLine("Summary...                                      ");
            var          summaryTxt = Path.Combine(output_path, "summary.txt");
            StreamWriter sw         = new StreamWriter(summaryTxt);

            foreach (string assembly in ms_assemblies)
            {
                ms_all.Clear();
                missing.Clear();

                // Get all methods in MS assembly
                Console.CursorTop = 5;
                MethodExtractor.ExtractFromAssembly(assembly, ms_all, null, null);
                string file = Path.GetFileName(assembly);

                // We only want MS method counts
                if (count_only)
                {
                    sw.WriteLine("{0}: {1}", file, ms_all.Count);
                    continue;
                }

                // Find the matching Mono assembly
                string mono_file = string.Empty;

                foreach (string s in mono_assemblies)
                {
                    if (s.ToLower().Contains(file.ToLower()))
                    {
                        mono_file = s;
                    }
                }

                if (string.IsNullOrEmpty(mono_file))
                {
                    sw.WriteLine("No Mono assembly found for " + file);
                    continue;
                }

                // Do the MoMA extracts/compares, and output the results
                all.Clear();
                todo.Clear();
                nie.Clear();

                Console.CursorTop = 5;
                MethodExtractor.ExtractFromAssembly(mono_file, all, nie, todo);

                final_todo.Clear();

                foreach (string s in todo.Keys)
                {
                    if (ms_all.ContainsKey(s))
                    {
                        final_todo[s] = todo[s];
                    }
                }

                sw.WriteLine(file);
                sw.WriteLine(string.Format("TODO: {0}", final_todo.Count));

                final_nie.Clear();

                foreach (string s in nie.Keys)
                {
                    if (ms_all.ContainsKey(s))
                    {
                        final_nie[s] = nie[s];
                    }
                }

                sw.WriteLine(string.Format("NIEX: {0}", final_nie.Count));

                MethodExtractor.ComputeMethodDifference(ms_all, all, missing, true);
                sw.WriteLine(string.Format("MISS: {0}", missing.Count));
            }

            sw.Close();
            sw.Dispose();

            var versionTxt = Path.Combine(output_path, "version.txt");

            File.WriteAllText(versionTxt, $@"Mono {monoVersion} ({displayVersion} Profile)
{DateTime.Now.ToString("MM/dd/yyyy")}");

            var zipName = Path.Combine(Path.GetDirectoryName(output_path), $"{monoName}.zip");

            if (File.Exists(zipName))
            {
                File.Delete(zipName);
            }
            using (var zip = new ZipFile(zipName)) {
                zip.AddFiles(new string[] { monotodoTxt, exceptionTxt, dupeTxt, missingTxt, summaryTxt, versionTxt }, false, "/");
                zip.Save();
            }

            Directory.Delete(output_path, true);
        }