Example #1
0
        /// <summary>
        /// Creates the tree structure for the given clone report.
        /// </summary>
        /// <param name="report">The clone report to create the tree structure for.</param>
        private void FillSourceElements(CloneReport report)
        {
            // First we construct the root.
            _root          = new SourceNode();
            _root.Name     = Path.GetFileNameWithoutExtension(_solutionPath);
            _root.FullPath = Path.GetDirectoryName(_solutionPath);

            // Enter the root. This is important in order to make sure that our
            // tree will only contain elements relative to the directory the solution
            // is contained in.
            _pathDictionary.Add(_root.FullPath, _root);

            // Add all files to the tree.
            foreach (SourceFile sourceFile in report.SourceFiles)
            {
                // Create the file node.
                SourceNode fileNode = new SourceNode();
                fileNode.Name       = Path.GetFileName(sourceFile.Path);
                fileNode.FullPath   = sourceFile.Path;
                fileNode.SourceFile = sourceFile;

                // Enter the file node to our dictionary. This is not required by
                // GetSourceElementParent() but for FindNode().
                _pathDictionary.Add(fileNode.FullPath, fileNode);

                // Get the node for the directory the file is contained in.
                string directory = Path.GetDirectoryName(sourceFile.Path);
                fileNode.Parent = GetSourceElementParent(_pathDictionary, directory);

                // Enter the file node to the children of the directory.
                fileNode.Parent.Children.Add(fileNode);
            }
        }
Example #2
0
        /// <summary>
        /// Writes a clone report to the given XML file.
        /// </summary>
        /// <param name="fileName">The fully qualified path to the ConQAT clone report file.</param>
        /// <param name="cloneReport">The clone report to be written.</param>
        public static void Write(string fileName, CloneReport cloneReport)
        {
            XmlDocument doc = new XmlDocument();

            Write(doc, cloneReport);

            // We want to write the clone report in the same encoding as ConQAT would.
            using (XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.GetEncoding("ISO-8859-1")))
            {
                // Since we want to be able to read the result we will
                // use formatted output.
                writer.Formatting = Formatting.Indented;
                doc.Save(writer);
            }
        }
        public static CloneDetectiveResult FromSolutionPath(string solutionPath)
        {
            // Get path to log file.
            string logPath         = PathHelper.GetLogPath(solutionPath);
            string cloneReportPath = PathHelper.GetCloneReportPath(solutionPath);

            // If the log file does not exist no clone detective result can be
            // constructed (if only the clone report is missing it can).
            if (!File.Exists(logPath))
            {
                return(null);
            }

            // Construct the clone detective result.
            CloneDetectiveResult result = new CloneDetectiveResult();

            if (File.Exists(cloneReportPath))
            {
                try
                {
                    // We have a clone report. Parse it and construct the source tree from it.
                    result.CloneReport = CloneReport.FromFile(cloneReportPath);
                    result.SourceTree  = SourceTree.FromCloneReport(result.CloneReport, solutionPath);
                }
                catch (Exception ex)
                {
                    // If we could not parse the clone report we write an error to the
                    // log file (which we will parse below).
                    result.CloneReport = null;
                    result.SourceTree  = null;
                    LogHelper.WriteError(logPath, ex);
                    LogHelper.WriteStatusInfo(logPath, CloneDetectiveResultStatus.Failed, 0, TimeSpan.Zero);
                }
            }

            // Parse the summary information out of the log file.
            CloneDetectiveResultStatus status;
            long     usedMemory;
            TimeSpan usedTime;

            LogHelper.ParseStatusInfo(logPath, out status, out usedMemory, out usedTime);

            result.Status     = status;
            result.UsedMemory = usedMemory;
            result.UsedTime   = usedTime;

            return(result);
        }
        /// <summary>
        /// Reads a clone report from the given XML file.
        /// </summary>
        /// <param name="fileName">The fully qualified path to the ConQAT clone report file.</param>
        public static CloneReport Read(string fileName)
        {
            XmlDocument doc = new XmlDocument();

            // First we try to load the document.
            try
            {
                doc.Load(fileName);
            }
            catch (Exception ex)
            {
                // NOTE: Here we intentionally catch all exceptions. XmlDocment.Load() lists ten possible exceptions.
                throw ExceptionBuilder.CannotLoadCloneReport(fileName, ex);
            }

            // Add schema so that we can validate the document is validated.
            using (StringReader stringReader = new StringReader(Resources.CloneReportSchema))
                using (XmlTextReader xmlTextReader = new XmlTextReader(stringReader))
                    doc.Schemas.Add(null, xmlTextReader);

            // Now we can validate document against the loaded schema.
            List <XmlSchemaException> validationErrors = new List <XmlSchemaException>();

            doc.Validate(delegate(object sender, ValidationEventArgs e)
            {
                validationErrors.Add(e.Exception);
            });

            if (validationErrors.Count > 0)
            {
                throw ExceptionBuilder.InvalidCloneReport(fileName, validationErrors);
            }

            CloneReport cloneReport = Read(doc);

            // Make sure the source files are sorted by their path.
            // This property is required by some algorithms later on.
            cloneReport.SourceFiles.Sort(delegate(SourceFile x, SourceFile y)
            {
                return(String.Compare(x.Path, y.Path, StringComparison.OrdinalIgnoreCase));
            });

            return(cloneReport);
        }
Example #5
0
        /// <summary>
        /// Creates a <see cref="SourceTree"/> from the given <paramref name="cloneReport"/> and solution path.
        /// </summary>
        /// <param name="cloneReport">The clone report to create a source tree from.</param>
        /// <param name="solutionPath">The path to the solution of the clone report.</param>
        /// <returns>A hierarchical representation of the clone report.</returns>
        public static SourceTree FromCloneReport(CloneReport cloneReport, string solutionPath)
        {
            // Create the source and initialize path to solution.
            SourceTree sourceTree = new SourceTree();

            sourceTree.SolutionPath = solutionPath;

            // Create the tree structure.
            sourceTree.FillSourceElements(cloneReport);

            // Traverse tree and calculate statistics.
            PropagateDetails(sourceTree.Root);

            // Sort tree elements so that directories come before files and both
            // are sorted by name.
            SortSourceElements(sourceTree.Root);

            return(sourceTree);
        }
Example #6
0
 /// <summary>
 /// Writes the clone report to the given ConQAT clone report file.
 /// </summary>
 /// <param name="fileName">The fully qualified path of the clone report file.</param>
 /// <param name="cloneReport">The clone report to be written.</param>
 public static void ToFile(string fileName, CloneReport cloneReport)
 {
     CloneReportWriter.Write(fileName, cloneReport);
 }
        /// <summary>
        /// Reads a clone report from the given XML document.
        /// </summary>
        /// <param name="doc">The XML document to read the clone report from.</param>
        private static CloneReport Read(XmlDocument doc)
        {
            XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);

            manager.AddNamespace("cr", Resources.CloneReportSchemaNamespace);

            CloneReport cloneReport = new CloneReport();

            cloneReport.SystemDate = GetOptionalAttributeString(doc, "/cr:cloneReport/@systemdate", manager);

            // In order to associate source files and clones we need to map
            // source file ids to source file objects.
            Dictionary <int, SourceFile> sourceFileDictionary = new Dictionary <int, SourceFile>();

            // Read all source files.
            XmlNodeList sourceFiles = doc.SelectNodes("/cr:cloneReport/cr:sourceFile", manager);

            foreach (XmlNode sourceFileNode in sourceFiles)
            {
                // Create source file object and parse attributes.
                SourceFile sourceFile = new SourceFile();
                sourceFile.Id          = XmlConvert.ToInt32(sourceFileNode.Attributes["id"].Value);
                sourceFile.Path        = sourceFileNode.Attributes["path"].Value;
                sourceFile.Length      = XmlConvert.ToInt32(sourceFileNode.Attributes["length"].Value);
                sourceFile.Fingerprint = sourceFileNode.Attributes["fingerprint"].Value;

                // Add source file object to list of all source files.
                cloneReport.SourceFiles.Add(sourceFile);

                // Add mapping sourceFile.Id -> sourceFile for later use.
                sourceFileDictionary.Add(sourceFile.Id, sourceFile);
            }

            // Read all clone classes.
            XmlNodeList cloneClasses = doc.SelectNodes("/cr:cloneReport/cr:cloneClass", manager);

            foreach (XmlNode cloneClassNode in cloneClasses)
            {
                // Create clone class and parse attributes.
                CloneClass cloneClass = new CloneClass();
                cloneClass.Id               = XmlConvert.ToInt32(cloneClassNode.Attributes["id"].Value);
                cloneClass.UniqueId         = GetOptionalAttributeString(cloneClassNode, "@uniqueId", manager);
                cloneClass.NormalizedLength = XmlConvert.ToInt32(cloneClassNode.Attributes["normalizedLength"].Value);
                cloneClass.Fingerprint      = cloneClassNode.Attributes["fingerprint"].Value;

                // Add clone class to list of all clone classes.
                cloneReport.CloneClasses.Add(cloneClass);

                // Read all key-value pairs associated with this clone class.
                XmlNodeList cloneClassValues = cloneClassNode.SelectNodes("cr:values/cr:value", manager);
                ReadValues(cloneClassValues, cloneClass.Values);

                // Read all clones.
                XmlNodeList clones = cloneClassNode.SelectNodes("cr:clone", manager);
                foreach (XmlNode cloneNode in clones)
                {
                    // Parse source file id and get associated source file object.
                    int        sourceFileId = XmlConvert.ToInt32(cloneNode.Attributes["sourceFileId"].Value);
                    SourceFile sourceFile   = sourceFileDictionary[sourceFileId];

                    // Create clone and parse attributes.
                    Clone clone = new Clone();
                    clone.Id                   = GetOptionalAttributeInt32(cloneNode, "@id", manager);
                    clone.UniqueId             = GetOptionalAttributeString(cloneNode, "@uniqueId", manager);
                    clone.SourceFile           = sourceFile;
                    clone.StartLine            = XmlConvert.ToInt32(cloneNode.Attributes["startLine"].Value);
                    clone.LineCount            = XmlConvert.ToInt32(cloneNode.Attributes["lineCount"].Value);
                    clone.StartUnitIndexInFile = XmlConvert.ToInt32(cloneNode.Attributes["startUnitIndexInFile"].Value);
                    clone.LengthInUnits        = XmlConvert.ToInt32(cloneNode.Attributes["lengthInUnits"].Value);
                    clone.DeltaInUnits         = XmlConvert.ToInt32(cloneNode.Attributes["deltaInUnits"].Value);
                    clone.Gaps                 = cloneNode.Attributes["gaps"].Value;
                    clone.Fingerprint          = cloneNode.Attributes["fingerprint"].Value;

                    // Read all key-value pairs associated with this clone.
                    XmlNodeList cloneValues = cloneNode.SelectNodes("cr:values/cr:value", manager);
                    ReadValues(cloneValues, clone.Values);

                    clone.CloneClass = cloneClass;

                    // Add clone to the clone class' list of clones.
                    cloneClass.Clones.Add(clone);

                    // Add clone to the source file's list of clones.
                    clone.SourceFile.Clones.Add(clone);
                }
            }

            return(cloneReport);
        }
Example #8
0
        /// <summary>
        /// Writes a clone report to the given XML document.
        /// </summary>
        /// <param name="doc">The XML document to write to.</param>
        /// <param name="cloneReport">The clone report to be written.</param>
        private static void Write(XmlDocument doc, CloneReport cloneReport)
        {
            // Create root node.
            XmlNode reportNode = doc.AppendChild(doc.CreateElement("cloneReport", Resources.CloneReportSchemaNamespace));

            if (cloneReport.SystemDate != null)
            {
                reportNode.Attributes.Append(doc.CreateAttribute("systemdate")).Value = cloneReport.SystemDate;
            }

            // Write all source files.
            foreach (SourceFile sourceFile in cloneReport.SourceFiles)
            {
                // Create source file node and write attributes.
                XmlNode sourceFileNode = reportNode.AppendChild(doc.CreateElement("sourceFile", Resources.CloneReportSchemaNamespace));
                sourceFileNode.Attributes.Append(doc.CreateAttribute("id")).Value          = XmlConvert.ToString(sourceFile.Id);
                sourceFileNode.Attributes.Append(doc.CreateAttribute("path")).Value        = sourceFile.Path;
                sourceFileNode.Attributes.Append(doc.CreateAttribute("length")).Value      = XmlConvert.ToString(sourceFile.Length);
                sourceFileNode.Attributes.Append(doc.CreateAttribute("fingerprint")).Value = sourceFile.Fingerprint;
            }

            // Write all clone classes.
            foreach (CloneClass cloneClass in cloneReport.CloneClasses)
            {
                // Create clone class node and write attributes.
                XmlNode cloneClassNode = reportNode.AppendChild(doc.CreateElement("cloneClass", Resources.CloneReportSchemaNamespace));
                cloneClassNode.Attributes.Append(doc.CreateAttribute("id")).Value = XmlConvert.ToString(cloneClass.Id);
                if (cloneClass.UniqueId != null)
                {
                    cloneClassNode.Attributes.Append(doc.CreateAttribute("uniqueId")).Value = cloneClass.UniqueId;
                }
                cloneClassNode.Attributes.Append(doc.CreateAttribute("normalizedLength")).Value = XmlConvert.ToString(cloneClass.NormalizedLength);
                cloneClassNode.Attributes.Append(doc.CreateAttribute("fingerprint")).Value      = cloneClass.Fingerprint;

                // Write all key-value pairs of the current clone class.
                if (cloneClass.Values.Count > 0)
                {
                    XmlNode valuesNode = cloneClassNode.AppendChild(doc.CreateElement("values", Resources.CloneReportSchemaNamespace));
                    WriteValues(valuesNode, cloneClass.Values);
                }

                // Write all clones of the current clone class.
                foreach (Clone clone in cloneClass.Clones)
                {
                    XmlNode cloneNode = cloneClassNode.AppendChild(doc.CreateElement("clone", Resources.CloneReportSchemaNamespace));
                    if (clone.Id != null)
                    {
                        cloneNode.Attributes.Append(doc.CreateAttribute("id")).Value = XmlConvert.ToString(clone.Id.Value);
                    }
                    if (clone.UniqueId != null)
                    {
                        cloneNode.Attributes.Append(doc.CreateAttribute("uniqueId")).Value = clone.UniqueId;
                    }
                    cloneNode.Attributes.Append(doc.CreateAttribute("sourceFileId")).Value         = XmlConvert.ToString(clone.SourceFile.Id);
                    cloneNode.Attributes.Append(doc.CreateAttribute("startLine")).Value            = XmlConvert.ToString(clone.StartLine);
                    cloneNode.Attributes.Append(doc.CreateAttribute("lineCount")).Value            = XmlConvert.ToString(clone.LineCount);
                    cloneNode.Attributes.Append(doc.CreateAttribute("startUnitIndexInFile")).Value = XmlConvert.ToString(clone.LineCount);
                    cloneNode.Attributes.Append(doc.CreateAttribute("lengthInUnits")).Value        = XmlConvert.ToString(clone.LengthInUnits);
                    cloneNode.Attributes.Append(doc.CreateAttribute("deltaInUnits")).Value         = XmlConvert.ToString(clone.DeltaInUnits);
                    cloneNode.Attributes.Append(doc.CreateAttribute("gaps")).Value        = clone.Gaps;
                    cloneNode.Attributes.Append(doc.CreateAttribute("fingerprint")).Value = clone.Fingerprint;

                    // Write all key-value pairs of the current clone.
                    if (clone.Values.Count > 0)
                    {
                        XmlNode valuesNode = cloneNode.AppendChild(doc.CreateElement("values", Resources.CloneReportSchemaNamespace));
                        WriteValues(valuesNode, clone.Values);
                    }
                }
            }
        }