private async Task <AddMessageResult> AddMessageCoreAsync(TargetGeneratedError error) { // We only want to pass compiler, analyzers, etc to the language // service, so we skip tasks that do not have a code if (!TryExtractErrorListDetails(error.BuildEventArgs, out ErrorListDetails details) || string.IsNullOrEmpty(details.Code)) { return(await NotHandled.ConfigureAwait(false)); } InitializeBuildErrorReporter(); bool handled = false; if (_languageServiceBuildErrorReporter != null) { try { _languageServiceBuildErrorReporter.ReportError2(details.Message, details.Code, details.Priority, details.LineNumberForErrorList, details.ColumnNumberForErrorList, details.EndLineNumberForErrorList, details.EndColumnNumberForErrorList, details.GetFileFullPath(_host)); handled = true; } catch (NotImplementedException) { // Language Service doesn't handle it, typically because file // isn't in the project or because it doesn't have line/column } } return(handled ? await HandledAndStopProcessing.ConfigureAwait(false) : await NotHandled.ConfigureAwait(false)); }
/// <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); } }); }