Exemplo n.º 1
0
        public static bool RunCloneDetective(EventHandler <CloneDetectiveCompletedEventArgs> completedHandler)
        {
            string solutionPath = VSPackage.Instance.GetSolutionPath();

            // Save all modified documents before we start the build. Pay attention
            // to the fact that the user can cancel this operation.
            IVsSolutionBuildManager2 solutionBuildManager = (IVsSolutionBuildManager2)VSPackage.Instance.GetService(typeof(SVsSolutionBuildManager));
            int hr = solutionBuildManager.SaveDocumentsBeforeBuild(null, 0, 0);

            if (hr == VSConstants.E_ABORT)
            {
                return(false);
            }

            VSPackage.Instance.ClearOutput();

            _cloneDetectiveRunner            = new CloneDetectiveRunner(solutionPath);
            _cloneDetectiveRunner.Started   += (sender, e) => WriteStartedMessage(e);
            _cloneDetectiveRunner.Message   += (sender, e) => WriteOutputMessage(e);
            _cloneDetectiveRunner.Completed += (sender, e) =>
            {
                WriteCompletedMessage(e);

                _cloneDetectiveRunner = null;

                if (e.Result != null)
                {
                    CloneDetectiveResult = e.Result;
                }

                completedHandler(sender, e);
            };

            // Validate path to ConQAT.bat
            if (!File.Exists(GlobalSettings.GetConqatBatFileName()))
            {
                VSPackage.Instance.ShowError(Res.InvalidConqatBatPath);
                return(false);
            }

            // Validate Java Home.
            if (!File.Exists(Path.Combine(Path.Combine(GlobalSettings.GetJavaHome(), "bin"), "Java.exe")))
            {
                VSPackage.Instance.ShowError(Res.InvalidJavaExePath);
                return(false);
            }

            // Now run the clone detective.
            _cloneDetectiveRunner.RunAsync();

            return(true);
        }
Exemplo n.º 2
0
        internal static void OnSolutionOpened()
        {
            // Try to open an existing clone report.
            string solutionPath = VSPackage.Instance.GetSolutionPath();

            CloneDetectiveResult = CloneDetectiveResult.FromSolutionPath(solutionPath);

            // We do NOT have to do anything else as Visual Studio closes all document
            // windows when a solution is closed. Similarly all document windows are
            // restored when a solution is opened. However this will happen after this
            // event is fired, so our TextManagerEventSink will get all the notifications
            // for the restored windows and insert all text markers as usual.
        }
Exemplo n.º 3
0
        internal static void OnSolutionClosed()
        {
            if (_cloneDetectiveRunner != null)
            {
                // Terminate clone detective if it is still running. We need to disable
                // the events upfront to prevent any unwanted UI changes after we close
                // the result.
                _cloneDetectiveRunner.DisableEvents();
                _cloneDetectiveRunner.Abort();
            }

            // Since the clone report is solution specific now it's the right time to
            // close it.
            CloneDetectiveResult = null;
        }
Exemplo n.º 4
0
        public static void CloseCloneDetectiveResults()
        {
            string solutionPath = VSPackage.Instance.GetSolutionPath();

            if (solutionPath == null)
            {
                return;
            }

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

            File.Delete(logPath);
            File.Delete(cloneReportPath);

            CloneDetectiveResult = CloneDetectiveResult.FromSolutionPath(solutionPath);
        }
Exemplo n.º 5
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);
        }
        private static void UpdateTreeView(TreeView treeView, CloneDetectiveResult result)
        {
            treeView.BeginUpdate();
            try
            {
                bool wasEmpty = (treeView.Nodes.Count == 0);

                if (result == null || result.Status != CloneDetectiveResultStatus.Succeeded)
                {
                    treeView.Nodes.Clear();
                }
                else
                {
                    List <SourceNode> nodesToAdd = new List <SourceNode>();
                    nodesToAdd.Add(result.SourceTree.Root);

                    HashSet <string> fileSet = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                    while (nodesToAdd.Count > 0)
                    {
                        SourceNode nodeToAdd = nodesToAdd[0];
                        nodesToAdd.RemoveAt(0);
                        fileSet.Add(nodeToAdd.FullPath);
                        nodesToAdd.AddRange(nodeToAdd.Children);
                    }

                    UpdateTreeView(treeView.Nodes, new SourceNode[] { result.SourceTree.Root }, fileSet);
                }

                if (wasEmpty && treeView.Nodes.Count > 0)
                {
                    treeView.Nodes[0].Expand();
                }
            }
            finally
            {
                treeView.EndUpdate();
            }
        }
Exemplo n.º 7
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();
        }
        private void UpdateTreeView()
        {
            CloneDetectiveResult result = CloneDetectiveManager.CloneDetectiveResult;

            UpdateTreeView(treeView, result);
        }
        private void UpdateUI()
        {
            CloneDetectiveResult result = CloneDetectiveManager.CloneDetectiveResult;

            switch (CurrentUIState)
            {
            case UIState.NoSolution:
                runToolStripButton.Enabled          = false;
                stopToolStripButton.Enabled         = false;
                settingsToolStripButton.Enabled     = false;
                importToolStripButton.Enabled       = false;
                exportToolStripButton.Enabled       = false;
                closeToolStripButton.Enabled        = false;
                rollupTypeToolStripComboBox.Enabled = false;
                resultTableLayoutPanel.Visible      = false;
                pictureBox.Image     = null;
                runningLabel.Visible = false;
                progressBar.Visible  = false;
                break;

            case UIState.SolutionAndRunning:
                runToolStripButton.Enabled          = false;
                stopToolStripButton.Enabled         = true;
                settingsToolStripButton.Enabled     = false;
                importToolStripButton.Enabled       = false;
                exportToolStripButton.Enabled       = false;
                closeToolStripButton.Enabled        = false;
                rollupTypeToolStripComboBox.Enabled = false;
                resultTableLayoutPanel.Visible      = false;
                pictureBox.Image     = Res.Running;
                runningLabel.Visible = true;
                progressBar.Visible  = true;
                break;

            case UIState.Solution:
                runToolStripButton.Enabled          = true;
                stopToolStripButton.Enabled         = false;
                settingsToolStripButton.Enabled     = true;
                importToolStripButton.Enabled       = true;
                rollupTypeToolStripComboBox.Enabled = true;
                runningLabel.Visible = false;
                progressBar.Visible  = false;
                if (result == null)
                {
                    exportToolStripButton.Enabled       = false;
                    closeToolStripButton.Enabled        = false;
                    rollupTypeToolStripComboBox.Enabled = false;
                    resultTableLayoutPanel.Visible      = false;
                    pictureBox.Image = null;
                }
                else
                {
                    closeToolStripButton.Enabled   = true;
                    resultTableLayoutPanel.Visible = true;
                    switch (result.Status)
                    {
                    case CloneDetectiveResultStatus.Succeeded:
                        exportToolStripButton.Enabled       = true;
                        rollupTypeToolStripComboBox.Enabled = true;
                        pictureBox.Image     = Res.Succeeded;
                        resultLinkLabel.Text = Res.CloneExplorerSucceeded;
                        timeLabel.Text       = String.Format(CultureInfo.CurrentCulture, Res.CloneExplorerTimeStatistic, FormattingHelper.FormatTime(result.UsedTime));
                        memoryLabel.Text     = String.Format(CultureInfo.CurrentCulture, Res.CloneExplorerMemoryStatistic, FormattingHelper.FormatMemory(result.UsedMemory));
                        timeLabel.Visible    = true;
                        memoryLabel.Visible  = true;
                        break;

                    case CloneDetectiveResultStatus.Failed:
                        exportToolStripButton.Enabled       = false;
                        rollupTypeToolStripComboBox.Enabled = false;
                        pictureBox.Image     = Res.Error;
                        resultLinkLabel.Text = Res.CloneExplorerFailed;
                        timeLabel.Visible    = false;
                        memoryLabel.Visible  = false;
                        break;

                    case CloneDetectiveResultStatus.Stopped:
                        exportToolStripButton.Enabled       = false;
                        rollupTypeToolStripComboBox.Enabled = false;
                        pictureBox.Image     = Res.Stopped;
                        resultLinkLabel.Text = Res.CloneExplorerStopped;
                        timeLabel.Visible    = false;
                        memoryLabel.Visible  = false;
                        break;

                    default:
                        throw ExceptionBuilder.UnhandledCaseLabel(result.Status);
                    }
                }
                break;

            default:
                throw ExceptionBuilder.UnhandledCaseLabel(CurrentUIState);
            }

            UpdateTreeView();
        }