/// <summary> /// Check that current <paramref name="marker"/> point to correct line position /// and attach it to <paramref name="docCookie"/> for track changes. /// </summary> private void AttachToDocumentWorker(IVsWindowFrame frame, long docCookie, ResultTextMarker marker) { ThreadHelper.ThrowIfNotOnUIThread(); var sourceLocation = marker.GetSourceLocation(); int line = sourceLocation.StartLine; // Coerce the line numbers so we don't go out of bound. However, if we have to // coerce the line numbers, then we won't perform highlighting because most likely // we will highlight the wrong line. The idea here is to just go to the top or bottom // of the file as our "best effort" to be closest where it thinks it should be if (line <= 0) { line = 1; } IVsTextView textView = GetTextViewFromFrame(frame); if (textView != null) { // Locate the specific line/column position in the text view and go there IVsTextLines textLines; textView.GetBuffer(out textLines); if (textLines != null) { int lastLine; int length; int hr = textLines.GetLastLineIndex(out lastLine, out length); if (hr != 0) { return; } // our source code lines are 1-based, and the VS API source code lines are 0-based lastLine = lastLine + 1; // Same thing here, coerce the line number if it's going out of bound if (line > lastLine) { line = lastLine; } } // Call a bunch of functions to get the WPF text view so we can perform the highlighting only // if we haven't yet IWpfTextView wpfTextView = GetWpfTextView(textView); if (wpfTextView != null) { AttachMarkerToTextView(wpfTextView, docCookie, marker, line, sourceLocation.StartColumn, line + (sourceLocation.EndLine - sourceLocation.StartLine), sourceLocation.EndColumn); } } }
/// <summary> /// Highlight the source code on a particular line /// </summary> private static void AttachMarkerToTextView(IWpfTextView textView, long docCookie, ResultTextMarker marker, int line, int column, int endLine, int endColumn) { // If for some reason the start line is not correct, just skip the highlighting ITextSnapshot textSnapshot = textView.TextSnapshot; if (line > textSnapshot.LineCount) { return; } Span spanToColor; int markerStart, markerEnd = 0; try { // Fix up the end line number if it's inconsistent if (endLine <= 0 || endLine < line) { endLine = line; } bool coerced = false; // Calculate the start and end marker bound. Adjust for the column values if // the values don't make sense. Make sure we handle the case of empty file correctly ITextSnapshotLine startTextLine = textSnapshot.GetLineFromLineNumber(Math.Max(line - 1, 0)); ITextSnapshotLine endTextLine = textSnapshot.GetLineFromLineNumber(Math.Max(endLine - 1, 0)); if (column <= 0 || column >= startTextLine.Length) { column = 1; coerced = true; } // Calculate the end marker bound. Perform coersion on the values if they aren't consistent if (endColumn <= 0 && endColumn >= endTextLine.Length) { endColumn = endTextLine.Length; coerced = true; } // If we are highlighting just one line and the column values don't make // sense or we corrected one or more of them, then simply mark the // entire line if (endLine == line && (coerced || column >= endColumn)) { column = 1; endColumn = endTextLine.Length; } // Create a span with the calculated markers markerStart = startTextLine.Start.Position + column - 1; markerEnd = endTextLine.Start.Position + endColumn; spanToColor = Span.FromBounds(markerStart, markerEnd); marker.AddTracking(textView, textSnapshot, docCookie, spanToColor); } catch (Exception e) { // Log the exception and move ahead. We don't want to bubble this or fail. // We just don't color the problem line. Debug.Print(e.Message); } }
/// <summary> /// Check that current <paramref name="marker"/> point to correct line position /// and attach it to <paramref name="docCookie"/> for track changes. /// </summary> private void AttachToDocumentWorker(IVsWindowFrame frame, long docCookie, ResultTextMarker marker) { var sourceLocation = marker.GetSourceLocation(); int line = sourceLocation.StartLine; // Coerce the line numbers so we don't go out of bound. However, if we have to // coerce the line numbers, then we won't perform highlighting because most likely // we will highlight the wrong line. The idea here is to just go to the top or bottom // of the file as our "best effort" to be closest where it thinks it should be if (line <= 0) { line = 1; } IVsTextView textView = GetTextViewFromFrame(frame); if (textView != null) { // Locate the specific line/column position in the text view and go there IVsTextLines textLines; textView.GetBuffer(out textLines); if (textLines != null) { int lastLine; int length; int hr = textLines.GetLastLineIndex(out lastLine, out length); if (hr != 0) { return; } // our source code lines are 1-based, and the VS API source code lines are 0-based lastLine = lastLine + 1; // Same thing here, coerce the line number if it's going out of bound if (line > lastLine) { line = lastLine; } } // Call a bunch of functions to get the WPF text view so we can perform the highlighting only // if we haven't yet IWpfTextView wpfTextView = GetWpfTextView(textView); if (wpfTextView != null) { AttachMarkerToTextView(wpfTextView, docCookie, marker, line, sourceLocation.StartColumn, line + (sourceLocation.EndLine - sourceLocation.StartLine), sourceLocation.EndColumn); } } }
internal bool TryNavigateTo(SarifError sarifError, string fileName, string mimeType, Region region, ResultTextMarker marker, out IVsWindowFrame result) { result = null; if (string.IsNullOrEmpty(fileName)) { return(false); } string remappedName = fileName; if (!File.Exists(fileName)) { remappedName = RebaselineFileName(fileName); if (!File.Exists(remappedName)) { return(false); } } CodeAnalysisResultManager.Instance.RemapFileNames(fileName, remappedName); fileName = remappedName; NewLineIndex newLineIndex = null; if (!sarifError.RegionPopulated && mimeType != MimeType.Binary) { if (!_fileToNewLineIndexMap.TryGetValue(fileName, out newLineIndex)) { _fileToNewLineIndexMap[fileName] = newLineIndex = new NewLineIndex(File.ReadAllText(fileName)); } region.Populate(newLineIndex); sarifError.RegionPopulated = true; } marker.FullFilePath = remappedName; result = marker.NavigateTo(false, null, false); return(result != null); }