예제 #1
0
            /// <summary>
            /// Gets the analysis status for the given source code document.
            /// </summary>
            /// <param name="sourceCode">The source code to retrieve status for.</param>
            /// <returns>Returns the analysis status for the source code.</returns>
            public DocumentAnalysisStatus GetDocumentStatus(SourceCode sourceCode)
            {
                Param.AssertNotNull(sourceCode, "sourceCode");

                DocumentAnalysisStatus status;

                if (!this.sourceCodeInstanceStatus.TryGetValue(sourceCode, out status))
                {
                    // Create a new status object and add add it to the dictionary.
                    status = new DocumentAnalysisStatus();
                    this.sourceCodeInstanceStatus.Add(sourceCode, status);
                }

                return(status);
            }
예제 #2
0
        /// <summary>
        /// Parses and analyzes the given document.
        /// </summary>
        /// <param name="sourceCode">
        /// The document to parse and analyze.
        /// </param>
        /// <param name="documentStatus">
        /// The current status of the documents.
        /// </param>
        private void ParseAndAnalyzeDocument(SourceCode sourceCode, DocumentAnalysisStatus documentStatus)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(documentStatus, "documentStatus");
            StyleCopTrace.In(sourceCode, documentStatus);

            // Signal the output for this document.
            this.data.Core.SignalOutput(
                MessageImportance.Low, string.Format(CultureInfo.CurrentCulture, "Pass {0}:   {1}", this.data.PassNumber + 1, GetSignalOutputGetText(sourceCode)));

            // Extract the document to parse.
            CodeDocument parsedDocument = documentStatus.Document;

            // Get or load the analyzer list.
            IEnumerable <SourceAnalyzer> analyzers = sourceCode.Settings.EnabledAnalyzers;

            // Parse the document.
            bool parsingCompleted;

            try
            {
                parsingCompleted = !sourceCode.Parser.ParseFile(sourceCode, this.data.PassNumber, ref parsedDocument);
            }
            catch (Exception)
            {
                string details = string.Format(
                    CultureInfo.CurrentCulture,
                    "Exception thrown by parser '{0}' while processing '{1}'.",
                    sourceCode.Parser.Name,
                    sourceCode.Path);
                this.data.Core.SignalOutput(MessageImportance.High, details);
                throw;
            }

            if (parsingCompleted)
            {
                if (parsedDocument == null)
                {
                    string format = string.Format(CultureInfo.CurrentCulture, "Skipping: {0} - {1}", sourceCode.Project.Location.SubstringAfterLast('\\'), GetRelativeFileName(sourceCode));
                    this.data.Core.SignalOutput(MessageImportance.Normal, format);

                    documentStatus.Complete = true;
                }
                else if (this.TestAndRunAnalyzers(parsedDocument, sourceCode.Parser, analyzers, this.data.PassNumber))
                {
                    // Analysis of this document is completed.
                    documentStatus.Complete = true;

                    // Save the cache for this document and dispose it.
                    if (this.data.ResultsCache != null && sourceCode.Project.WriteCache)
                    {
                        this.data.ResultsCache.SaveDocumentResults(parsedDocument, sourceCode.Parser, sourceCode.Settings.WriteTime);
                    }

                    parsedDocument.Dispose();
                    parsedDocument = null;
                }
            }

            if (!documentStatus.Complete)
            {
                // Analysis of this document is not complete, so we will need to
                // perform another round of analysis after this one is finished.
                this.complete = false;

                // Cache the document if there is one.
                if (parsedDocument != null)
                {
                    documentStatus.Document = parsedDocument;
                }
            }

            StyleCopTrace.Out();
        }
예제 #3
0
        /// <summary>
        /// Parses and analyzes the given document.
        /// </summary>
        /// <param name="sourceCode">
        /// The document to parse and analyze.
        /// </param>
        /// <param name="documentStatus">
        /// The current status of the documents.
        /// </param>
        private void ParseAndAnalyzeDocument(SourceCode sourceCode, DocumentAnalysisStatus documentStatus)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(documentStatus, "documentStatus");
            StyleCopTrace.In(sourceCode, documentStatus);

            // Signal the output for this document.
            this.data.Core.SignalOutput(
                MessageImportance.Low, string.Format(CultureInfo.CurrentCulture, "Pass {0}:   {1}", this.data.PassNumber + 1, GetSignalOutputGetText(sourceCode)));

            // Extract the document to parse.
            CodeDocument parsedDocument = documentStatus.Document;

            // Get or load the analyzer list.
            IEnumerable<SourceAnalyzer> analyzers = sourceCode.Settings.EnabledAnalyzers;

            // Parse the document.
            bool parsingCompleted;
            try
            {
                parsingCompleted = !sourceCode.Parser.ParseFile(sourceCode, this.data.PassNumber, ref parsedDocument);
            }
            catch (Exception)
            {
                string details = string.Format(
                    CultureInfo.CurrentCulture,
                    "Exception thrown by parser '{0}' while processing '{1}'.",
                    sourceCode.Parser.Name,
                    sourceCode.Path);
                this.data.Core.SignalOutput(MessageImportance.High, details);
                throw;
            }

            if (parsingCompleted)
            {
                if (parsedDocument == null)
                {
                    string format = string.Format(CultureInfo.CurrentCulture, "Skipping: {0} - {1}", sourceCode.Project.Location.SubstringAfterLast('\\'), GetRelativeFileName(sourceCode));
                    this.data.Core.SignalOutput(MessageImportance.Normal, format);

                    documentStatus.Complete = true;
                }
                else if (this.TestAndRunAnalyzers(parsedDocument, sourceCode.Parser, analyzers, this.data.PassNumber))
                {
                    // Analysis of this document is completed.
                    documentStatus.Complete = true;

                    // Save the cache for this document and dispose it.
                    if (this.data.ResultsCache != null && sourceCode.Project.WriteCache)
                    {
                        this.data.ResultsCache.SaveDocumentResults(parsedDocument, sourceCode.Parser, sourceCode.Settings.WriteTime);
                    }

                    parsedDocument.Dispose();
                    parsedDocument = null;
                }
            }

            if (!documentStatus.Complete)
            {
                // Analysis of this document is not complete, so we will need to 
                // perform another round of analysis after this one is finished.
                this.complete = false;

                // Cache the document if there is one.
                if (parsedDocument != null)
                {
                    documentStatus.Document = parsedDocument;
                }
            }

            StyleCopTrace.Out();
        }
예제 #4
0
            /// <summary>
            /// Gets the analysis status for the given source code document.
            /// </summary>
            /// <param name="sourceCode">The source code to retrieve status for.</param>
            /// <returns>Returns the analysis status for the source code.</returns>
            public DocumentAnalysisStatus GetDocumentStatus(SourceCode sourceCode)
            {
                Param.AssertNotNull(sourceCode, "sourceCode");

                DocumentAnalysisStatus status;
                if (!this.sourceCodeInstanceStatus.TryGetValue(sourceCode, out status))
                {
                    // Create a new status object and add add it to the dictionary.
                    status = new DocumentAnalysisStatus();
                    this.sourceCodeInstanceStatus.Add(sourceCode, status);
                }

                return status;
            }
예제 #5
0
        public void DoWork(object sender, DoWorkEventArgs e)
        {
            Param.Ignore(sender, e);

            // This flag will indicated whether any source code documents need to passed through
            // another round of analysis after this one is completed.
            this.complete = true;

            SourceCode sourceCode = null;

            try
            {
                // Keep looping until all the source code documents have been processed.
                while (!this.data.Core.Cancel)
                {
                    DocumentAnalysisStatus documentStatus = null;

                    lock (this.data)
                    {
                        // Get the next document to analyze.
                        sourceCode = this.data.GetNextSourceCodeDocument();
                        if (sourceCode == null)
                        {
                            // There are no more documents. Break out of the loop.
                            break;
                        }

                        // Get the status object for this document.
                        documentStatus = this.data.GetDocumentStatus(sourceCode);
                        Debug.Assert(documentStatus != null, "There is no DocumentStatus for the given SourceCode.");
                    }

                    // If this is the first time we have seen this document, prepare it for analysis.
                    if (!documentStatus.Initialized)
                    {
                        // If the document does not exist, or if the document's analysis data can
                        // be loaded from the results cache, mark the document as completed.
                        if (!sourceCode.Exists || this.LoadSourceCodeFromResultsCache(sourceCode))
                        {
                            documentStatus.Complete = true;
                        }

                        // Note that the document status has been initialized now.
                        documentStatus.Initialized = true;
                    }

                    // Check whether this document needs further parsing.
                    if (!documentStatus.Complete)
                    {
                        this.ParseAndAnalyzeDocument(sourceCode, documentStatus);
                    }
                }
            }
            catch (OutOfMemoryException)
            {
                // Do not catch out of memory exceptions.
                throw;
            }
            catch (ThreadAbortException)
            {
                // The thread is being aborted. Stop this thread from doing any additional analysis.
            }
            catch (Exception ex)
            {
                // Catch exceptions from the parser and analyzer modules.
                System.Diagnostics.Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Exception occurred: {0}, {1}", ex.GetType(), ex.Message));
                this.data.Core.CoreViolations.AddViolation(sourceCode, 1, Rules.ExceptionOccurred, ex.GetType(), FormatExceptionMessage(ex));

                // Do not re-throw the exception as this can crash Visual Studio or the build system that StyleCop is running under.
            }
            finally
            {
                // Send out the data object as the result of this worker thread so that the
                // finalization event can get access to it.
                e.Result = this.data;

                // Fire the completion event if necessary. When running under Visual Studio using MSBuild, the standard
                // completion event from the BackgroundWorker class does not get fired. The reason is unknown. We fire
                // our own event instead to get around this problem.
                if (this.ThreadCompleted != null)
                {
                    this.ThreadCompleted(this, new StyleCopThreadCompletedEventArgs(this.data));
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Parses and analyzes the given document.
        /// </summary>
        /// <param name="sourceCode">The document to parse and analyze.</param>
        /// <param name="documentStatus">The current status of the documents.</param>
        private void ParseAndAnalyzeDocument(SourceCode sourceCode, DocumentAnalysisStatus documentStatus)
        {
            Param.AssertNotNull(sourceCode, "sourceCode");
            Param.AssertNotNull(documentStatus, "documentStatus");

            // Signal the output for this document.
            this.data.Core.SignalOutput(
                MessageImportance.Low,
                string.Format(CultureInfo.CurrentCulture, "Pass {0}: {1}...\n", this.data.PassNumber + 1, sourceCode.Name));

            // Extract the document to parse.
            ICodeDocument parsedDocument = documentStatus.Document;

            // Get or load the analyzer list.
            IEnumerable <SourceAnalyzer> analyzers = sourceCode.Settings.EnabledAnalyzers;

            // Parse the document.
            bool parsingCompleted;

            try
            {
                parsingCompleted = !sourceCode.Parser.ParseFile(sourceCode, this.data.PassNumber, ref parsedDocument);
            }
            catch (System.Exception)
            {
                string details = string.Format(
                    CultureInfo.CurrentCulture,
                    "Exception thrown by parser '{0}' while processing '{1}'.",
                    sourceCode.Parser.Name,
                    sourceCode.Path);

                this.data.Core.SignalOutput(MessageImportance.High, details);
                throw;
            }

            if (parsingCompleted)
            {
                if (parsedDocument == null)
                {
                    documentStatus.Complete = true;
                }
                else
                {
                    if (this.data.RunContext.AutoFix)
                    {
                        parsedDocument.ReadOnly = false;
                    }

                    if (this.TestAndRunAnalyzers(parsedDocument, sourceCode.Parser, analyzers, this.data.PassNumber))
                    {
                        // Analysis of this document is completed.
                        documentStatus.Complete = true;

                        // Save the cache for this document and dispose it.
                        if (parsedDocument != null)
                        {
                            if (this.data.ResultsCache != null && sourceCode.Project.WriteCache)
                            {
                                this.data.ResultsCache.SaveDocumentResults(parsedDocument, sourceCode.Parser, sourceCode.Settings.WriteTime);
                            }

                            // If auto-save is true, then save the doc.
                            if (this.data.RunContext.AutoFix && this.data.AutoSaveMode && parsedDocument.Dirty)
                            {
                                this.SaveDocumentToSource(sourceCode, parsedDocument);
                            }

                            parsedDocument.Dispose();
                            parsedDocument = null;
                        }
                    }
                }
            }

            if (!documentStatus.Complete)
            {
                // Analysis of this document is not complete, so we will need to
                // perform another round of analysis after this one is finished.
                this.complete = false;

                // Cache the document if there is one.
                if (parsedDocument != null)
                {
                    documentStatus.Document = parsedDocument;
                }
            }
        }