/// <summary> /// Format error messages for the task list /// </summary> /// <param name="e"></param> /// <returns></returns> private string GetFormattedErrorMessage(DefaultCompilerError e) { if (e == null) { return(String.Empty); } string errCode = (e.IsWarning) ? this.warningString : this.errorString; StringBuilder fileRef = new StringBuilder(); // JAF: // Even if fsc.exe returns a canonical message with no file at all, MSBuild will set the file to the name // of the task (FSC). In principle, e.FileName will not be null or empty but handle this case anyway. bool thereIsAFile = !string.IsNullOrEmpty(e.FileName); bool thereIsASpan = e.Line != 0 || e.Column != 0 || e.EndLine != 0 || e.EndColumn != 0; if (thereIsAFile) { fileRef.AppendFormat(CultureInfo.CurrentUICulture, "{0}", e.FileName); if (thereIsASpan) { fileRef.AppendFormat(CultureInfo.CurrentUICulture, "({0},{1})", e.Line, e.Column); } fileRef.AppendFormat(CultureInfo.CurrentUICulture, ":"); } fileRef.AppendFormat(CultureInfo.CurrentUICulture, " {0} {1}: {2}", errCode, e.ErrorNumber, e.ErrorText); return(fileRef.ToString()); }
/// <summary> /// Add the error/warning to the error list and potentially to the output window. /// </summary> private void AddToErrorList( BuildEventArgs errorEvent, string subcategory, string errorCode, string file, int startLine, int startColumn, int endLine, int endColumn) { if (file == null) { file = String.Empty; } bool isWarning = errorEvent is BuildWarningEventArgs; Shell.TaskPriority priority = isWarning ? Shell.TaskPriority.Normal : Shell.TaskPriority.High; TextSpan span; span.iStartLine = startLine; span.iStartIndex = startColumn; span.iEndLine = endLine < startLine ? span.iStartLine : endLine; span.iEndIndex = (endColumn < startColumn) && (span.iStartLine == span.iEndLine) ? span.iStartIndex : endColumn; if (OutputWindowPane != null && (this.Verbosity != LoggerVerbosity.Quiet || errorEvent is BuildErrorEventArgs)) { // Format error and output it to the output window string message = this.FormatMessage(errorEvent.Message); DefaultCompilerError e = new DefaultCompilerError(file, span.iStartLine, span.iStartIndex, span.iEndLine, span.iEndIndex, errorCode, message); e.IsWarning = isWarning; Output(GetFormattedErrorMessage(e)); } UIThread.Run(delegate() { IVsUIShellOpenDocument openDoc = serviceProvider.GetService(typeof(IVsUIShellOpenDocument)) as IVsUIShellOpenDocument; if (openDoc == null) { return; } IVsWindowFrame frame; IOleServiceProvider sp; IVsUIHierarchy hier; uint itemid; Guid logicalView = VSConstants.LOGVIEWID_Code; IVsTextLines buffer = null; // JAF // Notes about acquiring the buffer: // If the file physically exists then this will open the document in the current project. It doesn't matter if the file is a member of the project. // Also, it doesn't matter if this is an F# file. For example, an error in Microsoft.Common.targets will cause a file to be opened here. // However, opening the document does not mean it will be shown in VS. if (!Microsoft.VisualStudio.ErrorHandler.Failed(openDoc.OpenDocumentViaProject(file, ref logicalView, out sp, out hier, out itemid, out frame)) && frame != null) { object docData; frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out docData); // Get the text lines buffer = docData as IVsTextLines; if (buffer == null) { IVsTextBufferProvider bufferProvider = docData as IVsTextBufferProvider; if (bufferProvider != null) { bufferProvider.GetTextBuffer(out buffer); } } } // Need to adjust line and column indexing for the task window, which assumes zero-based values if (span.iStartLine > 0 && span.iStartIndex > 0) { span.iStartLine -= 1; span.iEndLine -= 1; span.iStartIndex -= 1; span.iEndIndex -= 1; } // Add error to task list var taskText = global::FSharp.Compiler.ErrorLogger.NewlineifyErrorString(errorEvent.Message); if (errorReporter != null) { errorReporter.ReportError2(taskText, errorCode, (VSTASKPRIORITY)priority, span.iStartLine, span.iStartIndex, span.iEndLine, span.iEndIndex, file); } }); }
/// <summary> /// Format error messages for the task list /// </summary> /// <param name="e"></param> /// <returns></returns> private string GetFormattedErrorMessage(DefaultCompilerError e) { if (e == null) return String.Empty; string errCode = (e.IsWarning) ? this.warningString : this.errorString; StringBuilder fileRef = new StringBuilder(); // JAF: // Even if Fsc.exe returns a canonical message with no file at all, MSBuild will set the file to the name // of the task (FSC). In principle, e.FileName will not be null or empty but handle this case anyway. bool thereIsAFile = !string.IsNullOrEmpty(e.FileName); bool thereIsASpan = e.Line!=0 || e.Column!=0 || e.EndLine!=0 || e.EndColumn!=0; if (thereIsAFile) { fileRef.AppendFormat(CultureInfo.CurrentUICulture, "{0}", e.FileName); if (thereIsASpan) { fileRef.AppendFormat(CultureInfo.CurrentUICulture, "({0},{1})", e.Line, e.Column); } fileRef.AppendFormat(CultureInfo.CurrentUICulture, ":"); } fileRef.AppendFormat(CultureInfo.CurrentUICulture, " {0} {1}: {2}", errCode, e.ErrorNumber, e.ErrorText); return fileRef.ToString(); }
/// <summary> /// Add the error/warning to the error list and potentially to the output window. /// </summary> private void AddToErrorList( BuildEventArgs errorEvent, string subcategory, string errorCode, string file, int startLine, int startColumn, int endLine, int endColumn) { if (file == null) { file = String.Empty; } bool isWarning = errorEvent is BuildWarningEventArgs; TaskPriority priority = isWarning ? TaskPriority.Normal : TaskPriority.High; TextSpan span; span.iStartLine = startLine; span.iStartIndex = startColumn; span.iEndLine = endLine < startLine ? span.iStartLine : endLine; span.iEndIndex = (endColumn < startColumn) && (span.iStartLine == span.iEndLine) ? span.iStartIndex : endColumn; if (OutputWindowPane != null && (this.Verbosity != LoggerVerbosity.Quiet || errorEvent is BuildErrorEventArgs)) { // Format error and output it to the output window string message = this.FormatMessage(errorEvent.Message); DefaultCompilerError e = new DefaultCompilerError(file, span.iStartLine, span.iStartIndex, span.iEndLine, span.iEndIndex, errorCode, message); e.IsWarning = isWarning; Output(GetFormattedErrorMessage(e)); } UIThread.Run(delegate() { IVsUIShellOpenDocument openDoc = serviceProvider.GetService(typeof(IVsUIShellOpenDocument)) as IVsUIShellOpenDocument; if (openDoc == null) { return; } IVsWindowFrame frame; IOleServiceProvider sp; IVsUIHierarchy hier; uint itemid; Guid logicalView = VSConstants.LOGVIEWID_Code; IVsTextLines buffer = null; // JAF // Notes about acquiring the buffer: // If the file physically exists then this will open the document in the current project. It doesn't matter if the file is a member of the project. // Also, it doesn't matter if this is an F# file. For example, an error in Microsoft.Common.targets will cause a file to be opened here. // However, opening the document does not mean it will be shown in VS. if (!Microsoft.VisualStudio.ErrorHandler.Failed(openDoc.OpenDocumentViaProject(file, ref logicalView, out sp, out hier, out itemid, out frame)) && frame != null) { object docData; frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out docData); // Get the text lines buffer = docData as IVsTextLines; if (buffer == null) { IVsTextBufferProvider bufferProvider = docData as IVsTextBufferProvider; if (bufferProvider != null) { bufferProvider.GetTextBuffer(out buffer); } } } // Need to adjust line and column indexing for the task window, which assumes zero-based values if (span.iStartLine > 0 && span.iStartIndex > 0) { span.iStartLine -= 1; span.iEndLine -= 1; span.iStartIndex -= 1; span.iEndIndex -= 1; } // Add new document task to task list DocumentTask task = new DocumentTask(serviceProvider, buffer, // May be null // This seems weird. Why would warning status make this a 'compile error'? // The “code sense” errors produce red squiggles, whereas the “compile” errors produce blue squiggles. (This is in line with C#’s pre-VS2008-SP1 behavior.) Swapping these two gives us a look consistent with that of the language service. isWarning ? MARKERTYPE.MARKER_COMPILE_ERROR : MARKERTYPE.MARKER_CODESENSE_ERROR, span, file, subcategory); // Add error to task list task.Text = Microsoft.FSharp.Compiler.ErrorLogger.NewlineifyErrorString(errorEvent.Message); task.Priority = priority; task.ErrorCategory = isWarning ? TaskErrorCategory.Warning : TaskErrorCategory.Error; task.Category = TaskCategory.BuildCompile; task.HierarchyItem = hierarchy; task.Navigate += new EventHandler(NavigateTo); if (null != this.TaskReporter) { this.taskReporter.AddTask(task); } else { this.taskProvider.Tasks.Add(task); } }); }
/// <summary> /// Add the error/warning to the error list and potentially to the output window. /// </summary> private void AddToErrorList( BuildEventArgs errorEvent, string subcategory, string errorCode, string file, int startLine, int startColumn, int endLine, int endColumn) { if (file == null) file = String.Empty; bool isWarning = errorEvent is BuildWarningEventArgs; TaskPriority priority = isWarning ? TaskPriority.Normal : TaskPriority.High; TextSpan span; span.iStartLine = startLine; span.iStartIndex = startColumn; span.iEndLine = endLine < startLine ? span.iStartLine : endLine; span.iEndIndex = (endColumn < startColumn) && (span.iStartLine == span.iEndLine) ? span.iStartIndex : endColumn; if (OutputWindowPane != null && (this.Verbosity != LoggerVerbosity.Quiet || errorEvent is BuildErrorEventArgs)) { // Format error and output it to the output window string message = this.FormatMessage(errorEvent.Message); DefaultCompilerError e = new DefaultCompilerError(file, span.iStartLine, span.iStartIndex, span.iEndLine, span.iEndIndex, errorCode, message); e.IsWarning = isWarning; Output(GetFormattedErrorMessage(e)); } UIThread.Run(delegate() { IVsUIShellOpenDocument openDoc = serviceProvider.GetService(typeof(IVsUIShellOpenDocument)) as IVsUIShellOpenDocument; if (openDoc == null) return; IVsWindowFrame frame; IOleServiceProvider sp; IVsUIHierarchy hier; uint itemid; Guid logicalView = VSConstants.LOGVIEWID_Code; IVsTextLines buffer = null; // JAF // Notes about acquiring the buffer: // If the file physically exists then this will open the document in the current project. It doesn't matter if the file is a member of the project. // Also, it doesn't matter if this is an F# file. For example, an error in Microsoft.Common.targets will cause a file to be opened here. // However, opening the document does not mean it will be shown in VS. if (!Microsoft.VisualStudio.ErrorHandler.Failed(openDoc.OpenDocumentViaProject(file, ref logicalView, out sp, out hier, out itemid, out frame)) && frame != null) { object docData; frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out docData); // Get the text lines buffer = docData as IVsTextLines; if (buffer == null) { IVsTextBufferProvider bufferProvider = docData as IVsTextBufferProvider; if (bufferProvider != null) { bufferProvider.GetTextBuffer(out buffer); } } } // Need to adjust line and column indexing for the task window, which assumes zero-based values if (span.iStartLine > 0 && span.iStartIndex > 0) { span.iStartLine -= 1; span.iEndLine -= 1; span.iStartIndex -= 1; span.iEndIndex -= 1; } // Add new document task to task list DocumentTask task = new DocumentTask(serviceProvider, buffer, // May be null // This seems weird. Why would warning status make this a 'compile error'? // The “code sense” errors produce red squiggles, whereas the “compile” errors produce blue squiggles. (This is in line with C#’s pre-VS2008-SP1 behavior.) Swapping these two gives us a look consistent with that of the language service. isWarning ? MARKERTYPE.MARKER_COMPILE_ERROR : MARKERTYPE.MARKER_CODESENSE_ERROR, span, file, subcategory); // Add error to task list task.Text = Microsoft.FSharp.Compiler.ErrorLogger.NewlineifyErrorString(errorEvent.Message); task.Priority = priority; task.ErrorCategory = isWarning ? TaskErrorCategory.Warning : TaskErrorCategory.Error; task.Category = TaskCategory.BuildCompile; task.HierarchyItem = hierarchy; task.Navigate += new EventHandler(NavigateTo); if (null != this.TaskReporter) { this.taskReporter.AddTask(task); } else { this.taskProvider.Tasks.Add(task); } }); }