public void AnalyzeFile_ExistingFileWithTrackedMethods_AnalysisIsReturned()
        {
            var sut = new CodeFile("C:\\temp\\Program.cs", new int[] { -2, -1, 0, 1 });
            var testMethod = new TestMethod("TestFull", "Test");
            sut.AddCoverageByTestMethod(testMethod, new int[] { -2, 1, -1, 0 });

            var fileAnalysis = sut.AnalyzeFile();

            Assert.AreEqual(1, fileAnalysis.Lines.First().LineCoverageByTestMethod[testMethod].LineVisits);
            Assert.AreEqual(LineVisitStatus.Covered, fileAnalysis.Lines.First().LineCoverageByTestMethod[testMethod].LineVisitStatus);
        }
        public void Merge_MergeCodeFileWithEqualLengthCoverageArray_CoverageInformationIsUpdated()
        {
            var sut = new CodeFile("C:\\temp\\Program.cs", new int[] { -1, -1, -1, 0, 0, 0, 1, 1, 1 });
            var codeFileToMerge = new CodeFile("C:\\temp\\Program.cs", new int[] { -1, 0, 1, -1, 0, 1, -1, 0, 1 });
            var testMethod = new TestMethod("TestFull", "Test");
            codeFileToMerge.AddCoverageByTestMethod(testMethod, new int[] { -1, -1, -1, 0, 0, 0, 1, 1, 1 });

            sut.Merge(codeFileToMerge);

            Assert.AreEqual(8, sut.CoverableLines, "Not equal");
            Assert.AreEqual(5, sut.CoveredLines, "Not equal");

            Assert.IsNull(sut.CoveredBranches, "Not null");
            Assert.IsNull(sut.TotalBranches, "Not null");

            Assert.IsTrue(sut.TestMethods.Contains(testMethod));
        }
        /// <summary>
        /// Processes the file.
        /// </summary>
        /// <param name="fileIds">The file ids of the class.</param>
        /// <param name="class">The class.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>The <see cref="CodeFile"/>.</returns>
        private CodeFile ProcessFile(HashSet<string> fileIds, Class @class, string filePath)
        {
            var methods = this.modules
                .Where(m => m.Element("ModuleName").Value.Equals(@class.Assembly.Name))
                .Elements("Classes")
                .Elements("Class")
                .Where(c => c.Element("FullName").Value.Equals(@class.Name)
                            || c.Element("FullName").Value.StartsWith(@class.Name + "/", StringComparison.Ordinal))
                .Elements("Methods")
                .Elements("Method")
                .ToArray();

            var methodsOfFile = methods
                .Where(m => m.Element("FileRef") != null && fileIds.Contains(m.Element("FileRef").Attribute("uid").Value))
                .ToArray();

            SetMethodMetrics(methodsOfFile, @class);

            var seqpntsOfFile = methods
                .Elements("SequencePoints")
                .Elements("SequencePoint")
                .Where(seqpnt => (seqpnt.Attribute("fileid") != null
                                    && fileIds.Contains(seqpnt.Attribute("fileid").Value))
                    || (seqpnt.Attribute("fileid") == null && seqpnt.Parent.Parent.Element("FileRef") != null
                        && fileIds.Contains(seqpnt.Parent.Parent.Element("FileRef").Attribute("uid").Value)))
                .Select(seqpnt => new
                {
                    LineNumberStart = int.Parse(seqpnt.Attribute("sl").Value, CultureInfo.InvariantCulture),
                    LineNumberEnd = seqpnt.Attribute("el") != null ? int.Parse(seqpnt.Attribute("el").Value, CultureInfo.InvariantCulture) : int.Parse(seqpnt.Attribute("sl").Value, CultureInfo.InvariantCulture),
                    Visits = int.Parse(seqpnt.Attribute("vc").Value, CultureInfo.InvariantCulture),
                    TrackedMethodRefs = seqpnt.Elements("TrackedMethodRefs")
                        .Elements("TrackedMethodRef")
                        .Select(t => new
                        {
                            Visits = int.Parse(t.Attribute("vc").Value, CultureInfo.InvariantCulture),
                            TrackedMethodId = t.Attribute("uid").Value
                        })
                })
                .OrderBy(seqpnt => seqpnt.LineNumberEnd)
                .ToArray();

            int[] coverage = new int[] { };
            var branches = GetBranches(methods, fileIds);

            var trackedMethodsCoverage = seqpntsOfFile
                .SelectMany(s => s.TrackedMethodRefs)
                .Select(t => t.TrackedMethodId)
                .Distinct()
                .ToDictionary(id => id, id => new int[] { });

            if (seqpntsOfFile.Length > 0)
            {
                coverage = new int[seqpntsOfFile[seqpntsOfFile.LongLength - 1].LineNumberEnd + 1];

                for (int i = 0; i < coverage.Length; i++)
                {
                    coverage[i] = -1;
                }

                foreach (var name in trackedMethodsCoverage.Keys.ToArray())
                {
                    trackedMethodsCoverage[name] = (int[])coverage.Clone();
                }

                foreach (var seqpnt in seqpntsOfFile)
                {
                    for (int lineNumber = seqpnt.LineNumberStart; lineNumber <= seqpnt.LineNumberEnd; lineNumber++)
                    {
                        int visits = coverage[lineNumber] == -1 ? seqpnt.Visits : coverage[lineNumber] + seqpnt.Visits;
                        coverage[lineNumber] = visits;

                        if (visits > -1)
                        {
                            foreach (var trackedMethodCoverage in trackedMethodsCoverage)
                            {
                                if (trackedMethodCoverage.Value[lineNumber] == -1)
                                {
                                    trackedMethodCoverage.Value[lineNumber] = 0;
                                }
                            }
                        }

                        foreach (var trackedMethod in seqpnt.TrackedMethodRefs)
                        {
                            var trackedMethodCoverage = trackedMethodsCoverage[trackedMethod.TrackedMethodId];
                            trackedMethodCoverage[lineNumber] = trackedMethodCoverage[lineNumber] == -1 ? trackedMethod.Visits : trackedMethodCoverage[lineNumber] + trackedMethod.Visits;
                        }
                    }
                }
            }

            var codeFile = new CodeFile(filePath, coverage, branches);

            foreach (var trackedMethodCoverage in trackedMethodsCoverage)
            {
                string name = null;

                // Sometimes no corresponding MethodRef element exists
                if (this.trackedMethods.TryGetValue(trackedMethodCoverage.Key, out name))
                {
                    string shortName = name.Substring(name.Substring(0, name.IndexOf(':') + 1).LastIndexOf('.') + 1);
                    TestMethod testMethod = new TestMethod(name, shortName);
                    codeFile.AddCoverageByTestMethod(testMethod, trackedMethodCoverage.Value);
                }
            }

            return codeFile;
        }
        /// <summary>
        /// Adds the coverage by test method.
        /// </summary>
        /// <param name="testMethod">The test method.</param>
        /// <param name="coverage">The coverage.</param>
        internal void AddCoverageByTestMethod(TestMethod testMethod, int[] coverage)
        {
            if (testMethod == null)
            {
                throw new ArgumentNullException(nameof(testMethod));
            }

            if (coverage == null)
            {
                throw new ArgumentNullException(nameof(coverage));
            }

            this.lineCoveragesByTestMethod.Add(testMethod, coverage);
        }
        /// <summary>
        /// Adds the coverage by test method.
        /// </summary>
        /// <param name="testMethod">The test method.</param>
        /// <param name="coverage">The coverage.</param>
        public void AddCoverageByTestMethod(TestMethod testMethod, int[] coverage)
        {
            if (testMethod == null)
            {
                throw new ArgumentNullException("testMethod");
            }

            if (coverage == null)
            {
                throw new ArgumentNullException("coverage");
            }

            this.lineCoveragesByTestMethod.Add(testMethod, coverage);
        }
        private void ProcessTestMethods(CodeFile codeFile, IEnumerable<CoverageLine> lines)
        {
            var methods = lines.GroupBy (x => x.MethodName);
          
                
            foreach (var method in methods)
            {
               
                
                string shortName = method.Key.Substring(method.Key.Substring(0, method.Key.IndexOf('/') + 1).LastIndexOf('.') + 1);
                TestMethod testMethod = new TestMethod (method.Key, shortName);

                var maxLine = method.Max (x => x.LineNumStart);


                if (maxLine == -1)
                    continue;

                int [] coverage = new int [maxLine+1];
                for (int i = 0; i < coverage.Length; i++)
                    coverage [i] = -1;
                
                foreach (var sourceLine in method)
                {
                    if (sourceLine.LineNumStart != -1)
                        for (int i = sourceLine.LineNumStart; i <= sourceLine.LineNumEnd; i++)
                            coverage [i] = sourceLine.Missed ? 0 : 1;
                }
                codeFile.AddCoverageByTestMethod (testMethod, coverage);
            }
        }