/// <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); }
/// <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(); }
/// <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(); }
/// <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; }
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)); } } }
/// <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; } } }