Esempio n. 1
0
        public static void ImportCloneDetectiveResults(string fileName)
        {
            string solutionPath = VSPackage.Instance.GetSolutionPath();

            if (solutionPath == null)
            {
                return;
            }

            string logPath         = PathHelper.GetLogPath(solutionPath);
            string cloneReportPath = PathHelper.GetCloneReportPath(solutionPath);

            using (StreamWriter logWriter = new StreamWriter(logPath))
            {
                try
                {
                    logWriter.WriteLine("Opening clone report from '{0}'...", fileName);
                    CloneReport cloneReport = CloneReport.FromFile(fileName);

                    string oldRootPath = GetCommonRoot(cloneReport);
                    string newRootPath = AskUserForNewRootPath(cloneReport, oldRootPath, Path.GetDirectoryName(solutionPath));
                    if (newRootPath == null)
                    {
                        logWriter.WriteLine("User aborted import.");
                        return;
                    }

                    logWriter.WriteLine("Remapping paths from '{0}' to '{1}'...", oldRootPath, newRootPath);
                    RemapPaths(cloneReport, oldRootPath, newRootPath);

                    logWriter.WriteLine("Saving clone report to '{0}'...", cloneReportPath);
                    CloneReport.ToFile(cloneReportPath, cloneReport);

                    logWriter.WriteLine("Import of '{0}' succeeded.", fileName);
                    LogHelper.WriteStatusInfo(logWriter, CloneDetectiveResultStatus.Succeeded, 0, TimeSpan.Zero);
                }
                catch (Exception ex)
                {
                    LogHelper.WriteError(logWriter, ex);
                    LogHelper.WriteStatusInfo(logWriter, CloneDetectiveResultStatus.Failed, 0, TimeSpan.Zero);
                }
            }

            CloneDetectiveResult = CloneDetectiveResult.FromSolutionPath(solutionPath);
        }
Esempio n. 2
0
        internal static void OnDocumentSaved(uint docCookie)
        {
            // The document identified by docCookie has been saved. Now we have to update
            // our internal data structures and persist them to file. This will ensure we
            // will display the same data again when the user closes and reopens the document.

            // If there is currently no clone report available there is nothing to do.
            if (!IsCloneReportAvailable)
            {
                return;
            }

            CloneDetectiveResult cloneDetectiveResult = CloneDetectiveResult;

            // Get the text buffer. We're done if this fails because that means it was not
            // a text document.
            IVsTextLines textLines = GetDocumentTextLines(docCookie);

            if (textLines == null)
            {
                return;
            }

            // Get the SourceFile of the document in our data structure. We're done if this
            // fails because that means the document was not included in clone detection.
            string     path       = GetDocumentPath(textLines);
            SourceNode sourceNode = cloneDetectiveResult.SourceTree.FindNode(path);

            if (sourceNode == null)
            {
                return;
            }
            SourceFile sourceFile = sourceNode.SourceFile;

            // And we need to be able to map existing clone markers to their corresponding
            // clone classes. If that fails we cannot update any clone information.
            DocumentInfo documentInfo;

            if (!_textLinesToDocInfos.TryGetValue(textLines, out documentInfo))
            {
                return;
            }

            // If the hash of the file didn't match when we opened it, we don't want to save
            // any changes.
            if (!documentInfo.HashMatched)
            {
                return;
            }

            // Store the new line count of the file. Be aware of the fact that the last line
            // is not taken into account if it is empty. Replace the fingerprint of the file
            // with the new one such that we get no problems when opening up the file the
            // next time.
            int lastLineIndex;
            int lastLineLength;

            if (ErrorHandler.Failed(textLines.GetLastLineIndex(out lastLineIndex, out lastLineLength)))
            {
                return;
            }
            sourceFile.Length      = lastLineIndex + ((lastLineLength > 0) ? 1 : 0);
            sourceFile.Fingerprint = GetHashFromFile(path);

            // We need to track which source file clone information was modified to be able
            // to update the rollups afterwards.
            HashSet <SourceFile> modifiedSourceFiles = new HashSet <SourceFile>();

            // Clear old clone information of the saved document as we're going to rebuild
            // it from scratch.
            foreach (Clone clone in sourceFile.Clones)
            {
                clone.CloneClass.Clones.Remove(clone);
            }
            sourceFile.Clones.Clear();
            modifiedSourceFiles.Add(sourceFile);

            // Store information about current position of each marker.
            foreach (KeyValuePair <IVsTextLineMarker, CloneClass> markerWithCloneClass in documentInfo.MarkersToCloneClasses)
            {
                // Retrieve the current text span of the marker we just enumerated.
                TextSpan[] span = new TextSpan[1];
                ErrorHandler.ThrowOnFailure(markerWithCloneClass.Key.GetCurrentSpan(span));

                // Create a new clone object and initialize it appropriately.
                Clone clone = new Clone();
                clone.CloneClass = markerWithCloneClass.Value;
                clone.SourceFile = sourceFile;
                clone.StartLine  = span[0].iStartLine;
                clone.LineCount  = span[0].iEndLine - span[0].iStartLine + 1;

                // Add the clone to the clone class as well as the source file.
                clone.CloneClass.Clones.Add(clone);
                clone.SourceFile.Clones.Add(clone);
            }

            // Remove clone classes with less than two clones.
            List <CloneClass> cloneClasses = cloneDetectiveResult.CloneReport.CloneClasses;

            for (int i = cloneClasses.Count - 1; i >= 0; i--)
            {
                List <Clone> clones = cloneClasses[i].Clones;
                if (clones.Count < 2)
                {
                    foreach (Clone clone in clones)
                    {
                        clone.SourceFile.Clones.Remove(clone);
                        modifiedSourceFiles.Add(clone.SourceFile);
                    }

                    cloneClasses.RemoveAt(i);
                }
            }

            // Save the new clone report to disk.
            string solutionPath    = VSPackage.Instance.GetSolutionPath();
            string cloneReportPath = PathHelper.GetCloneReportPath(solutionPath);

            CloneReport.ToFile(cloneReportPath, cloneDetectiveResult.CloneReport);

            // Rollup changes within the SourceTree.
            foreach (SourceFile modifiedSourceFile in modifiedSourceFiles)
            {
                SourceNode modifiedSourceNode = cloneDetectiveResult.SourceTree.FindNode(modifiedSourceFile.Path);
                SourceTree.RecalculateRollups(modifiedSourceNode);
            }

            // Send notification about changed result to listeners.
            OnCloneDetectiveResultChanged();
        }