void TestFoldings(string text) { var editor = TextEditorFactory.CreateNewEditor(); var sb = new StringBuilder(); var foldStack = new Stack <int> (); var expected = new List <ISegment> (); foreach (var ch in text) { if (ch == '+') { foldStack.Push(sb.Length); continue; } if (ch == '-') { expected.Add(TextSegment.FromBounds(foldStack.Pop(), sb.Length)); continue; } sb.Append(ch); } editor.Text = sb.ToString(); var ext = new TextMateFoldingTextEditorExtension(); var foldings = ext.GetFoldingsAsync(editor, default(CancellationToken)).Result.ToList(); Assert.AreEqual(expected.Count, foldings.Count); for (int i = 0; i < foldings.Count; i++) { Assert.AreEqual(expected [i].Offset, foldings [i].Offset); Assert.AreEqual(expected [i].Length, foldings [i].Length); } }
void SelectLine() { editor.Caret.Column = 1; var lineEnd = editor.Document.GetLine(editor.Caret.Line).EndOffset; editor.Selection = TextSegment.FromBounds(editor.Caret.Offset, lineEnd); }
MonoTextEditor CreateEditorWithLinks(string input, out List <TextLink> links) { links = new List <TextLink> (); var segments = new List <List <ISegment> > (); int caretOffset = 0; var text = new StringBuilder(); int curLink = -1, linkStart = 0; for (int i = 0; i < input.Length; i++) { char ch = input [i]; switch (ch) { case '[': i++; // skip number curLink = (int)(input[i] - '0'); if (segments.Count - 1 < curLink) // links need to be defined in order { segments.Add(new List <ISegment> ()); } linkStart = text.Length; break; case ']': if (curLink < 0) { goto default; } segments [curLink].Add(TextSegment.FromBounds(linkStart, text.Length)); curLink = -1; break; case '$': caretOffset = text.Length; break; default: text.Append(ch); break; } } for (int i = 0; i < segments.Count; i++) { links.Add(new TextLink(i.ToString()) { Links = segments [i] }); } var result = new MonoTextEditor(); result.Text = text.ToString(); result.Caret.Offset = caretOffset; return(result); }
public static void ExpandSelectionToLine(TextEditor textEditor) { // from MonoDevelop.Ide.Editor.SelectionActions.ExpandSelectionToLine using (var undoGroup = textEditor.OpenUndoGroup()) { var curLineSegment = textEditor.GetLine(textEditor.CaretLine).SegmentIncludingDelimiter; var range = textEditor.SelectionRange; var selection = TextSegment.FromBounds( System.Math.Min(range.Offset, curLineSegment.Offset), System.Math.Max(range.EndOffset, curLineSegment.EndOffset)); textEditor.CaretOffset = selection.EndOffset; textEditor.SelectionRange = selection; } }
ISegment CalcTypeBounds(BaseTypeDeclarationSyntax type) { int start = type.Span.Start; int end = type.Span.End; foreach (var trivia in type.GetLeadingTrivia()) { if (trivia.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia) { start = trivia.FullSpan.Start; } } return(TextSegment.FromBounds(start, end)); }
protected internal override void MousePressed(MarginMouseEventArgs args) { base.MousePressed(args); if (args.Button == Xwt.PointerButton.Left) { var basePoint = editor.Caret.Location = XYToLocation(args.X, args.Y); editor.Selection = new TextSegment(); int clickMode = args.MultipleClicks % 3; if (clickMode == 2) { // TODO: Select Word } else if (clickMode == 0) { SelectLine(); } editor.RegisterMouseMotionTracker(Xwt.PointerButton.Left, (x, y) => { var newPoint = XYToLocation(x, y); editor.Caret.Location = newPoint; editor.ResetCaretState(); var newOffset = editor.Document.GetOffset(newPoint); var oldOffset = editor.Document.GetOffset(basePoint); var startOffset = Math.Min(oldOffset, newOffset); var endOffset = Math.Max(oldOffset, newOffset); editor.Selection = TextSegment.FromBounds(startOffset, endOffset); if (clickMode == 0) { SelectLines(); } editor.QueueDraw(); }); editor.ResetCaretState(); } }
public int Insert(TextEditor editor, DocumentContext ctx, string text) { int offset = editor.LocationToOffset(Location); using (var undo = editor.OpenUndoGroup()) { var line = editor.GetLineByOffset(offset); int insertionOffset = line.Offset + Location.Column - 1; offset = insertionOffset; InsertNewLine(editor, LineBefore, ref offset); int result = offset - insertionOffset; editor.InsertText(offset, text); offset += text.Length; InsertNewLine(editor, LineAfter, ref offset); CodeFormatterService.Format(editor, ctx, TextSegment.FromBounds(insertionOffset - 1, offset)); return(result); } }
TextSegment?GetSegmentForLine(TextSegment segment, DocumentLine line) { var start = Math.Max(segment.Offset, line.Offset); if (!segment.Contains(start)) { return(null); } var end = Math.Min(segment.EndOffset, line.EndOffset); if (!segment.Contains(end - 1)) { return(null); } return(TextSegment.FromBounds(start, end)); }
void SelectLines() { // We have a selection which covers normal individual characters // We want to extend the selection to cover entire lines editor.Caret.Column = 1; var firstLine = editor.Document.GetLineByOffset(editor.Selection.Offset); int lastLineNumberInRange = editor.Document.GetLineByOffset(editor.Selection.EndOffset).LineNumber; bool inEndOfDocument = lastLineNumberInRange == editor.Document.LineCount; var lastLine = editor.Document.GetLine(inEndOfDocument ? lastLineNumberInRange : lastLineNumberInRange + 1); if (editor.Caret.Offset != firstLine.Offset) { editor.Caret.Line++; } editor.Selection = TextSegment.FromBounds(firstLine.Offset, inEndOfDocument ? lastLine.EndOffset : lastLine.Offset); }
void ShowReferences(IEnumerable <MemberReference> references) { RemoveMarkers(); var lineNumbers = new HashSet <int> (); usages = ImmutableArray <Usage> .Empty; var editor = Editor; if (editor != null /*&& editor.TextViewMargin != null*/) { if (references != null) { var builder = ImmutableArray <Usage> .Empty.ToBuilder(); foreach (var r in references) { if (r == null) { continue; } var start = r.Offset; var end = r.Offset + r.Length; if (end > editor.Length) { continue; } var usage = new Usage(TextSegment.FromBounds(start, end), r.ReferenceUsageType); builder.Add(usage); var marker = TextMarkerFactory.CreateUsageMarker(editor, usage); markers.Add(marker); lineNumbers.Add(editor.OffsetToLineNumber(start)); editor.AddMarker(marker); } usages = builder.ToImmutable(); } } OnUsagesUpdated(EventArgs.Empty); }
protected override void ApplyDocumentTextChanged(DocumentId id, SourceText text) { var document = GetDocument(id); if (document == null) { return; } bool isOpen; var filePath = document.FilePath; var data = TextFileProvider.Instance.GetTextEditorData(filePath, out isOpen); // Guard against already done changes in linked files. // This shouldn't happen but the roslyn merging seems not to be working correctly in all cases :/ if (document.GetLinkedDocumentIds().Length > 0 && isOpen && !(text.GetType().FullName == "Microsoft.CodeAnalysis.Text.ChangedText")) { return; } SourceText formerText; if (changedFiles.TryGetValue(filePath, out formerText)) { if (formerText.Length == text.Length && formerText.ToString() == text.ToString()) { return; } } changedFiles [filePath] = text; Projection projection = null; foreach (var entry in ProjectionList) { var p = entry.Projections.FirstOrDefault(proj => FilePath.PathComparer.Equals(proj.Document.FileName, filePath)); if (p != null) { filePath = entry.File.FilePath; projection = p; break; } } SourceText oldFile; if (!isOpen || !document.TryGetText(out oldFile)) { oldFile = new MonoDevelopSourceText(data); } var changes = text.GetTextChanges(oldFile).OrderByDescending(c => c.Span.Start).ToList(); int delta = 0; if (!isOpen) { delta = ApplyChanges(projection, data, changes); var formatter = CodeFormatterService.GetFormatter(data.MimeType); var mp = GetMonoProject(CurrentSolution.GetProject(id.ProjectId)); string currentText = data.Text; foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } string str; if (change.NewText.Length == 0) { str = formatter.FormatText(mp.Policies, currentText, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { str = formatter.FormatText(mp.Policies, currentText, new TextSegment(startOffset, change.NewText.Length)); } data.ReplaceText(startOffset, change.NewText.Length, str); } data.Save(); OnDocumentTextChanged(id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue); FileService.NotifyFileChanged(filePath); } else { var formatter = CodeFormatterService.GetFormatter(data.MimeType); var documentContext = IdeApp.Workbench.Documents.FirstOrDefault(d => FilePath.PathComparer.Compare(d.FileName, filePath) == 0); if (documentContext != null) { var editor = (TextEditor)data; using (var undo = editor.OpenUndoGroup()) { delta = ApplyChanges(projection, data, changes); foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } if (change.NewText.Length == 0) { formatter.OnTheFlyFormat(editor, documentContext, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { formatter.OnTheFlyFormat(editor, documentContext, new TextSegment(startOffset, change.NewText.Length)); } } } } OnDocumentTextChanged(id, new MonoDevelopSourceText(data.CreateDocumentSnapshot()), PreservationMode.PreserveValue); Runtime.RunInMainThread(() => { if (IdeApp.Workbench != null) { foreach (var w in IdeApp.Workbench.Documents) { w.StartReparseThread(); } } }); } }
protected override void ApplyDocumentTextChanged(DocumentId id, SourceText text) { var document = GetDocument(id); if (document == null) { return; } bool isOpen; var filePath = document.FilePath; Projection projection = null; foreach (var entry in ProjectionList) { var p = entry.Projections.FirstOrDefault(proj => FilePath.PathComparer.Equals(proj.Document.FileName, filePath)); if (p != null) { filePath = entry.File.FilePath; projection = p; break; } } var data = TextFileProvider.Instance.GetTextEditorData(filePath, out isOpen); var oldFile = isOpen ? document.GetTextAsync().Result : new MonoDevelopSourceText(data); var changes = text.GetTextChanges(oldFile).OrderByDescending(c => c.Span.Start).ToList(); int delta = 0; if (!isOpen) { delta = ApplyChanges(projection, data, changes); var formatter = CodeFormatterService.GetFormatter(data.MimeType); var mp = GetMonoProject(CurrentSolution.GetProject(id.ProjectId)); string currentText = data.Text; foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } string str; if (change.NewText.Length == 0) { str = formatter.FormatText(mp.Policies, currentText, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { str = formatter.FormatText(mp.Policies, currentText, new TextSegment(startOffset, change.NewText.Length)); } data.ReplaceText(startOffset, change.NewText.Length, str); } data.Save(); OnDocumentTextChanged(id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue); FileService.NotifyFileChanged(filePath); } else { var formatter = CodeFormatterService.GetFormatter(data.MimeType); var documentContext = IdeApp.Workbench.Documents.FirstOrDefault(d => FilePath.PathComparer.Compare(d.FileName, filePath) == 0); if (documentContext != null) { var editor = (TextEditor)data; using (var undo = editor.OpenUndoGroup()) { delta = ApplyChanges(projection, data, changes); foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } if (change.NewText.Length == 0) { formatter.OnTheFlyFormat(editor, documentContext, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { formatter.OnTheFlyFormat(editor, documentContext, new TextSegment(startOffset, change.NewText.Length)); } } } } OnDocumentTextChanged(id, new MonoDevelopSourceText(data.CreateDocumentSnapshot()), PreservationMode.PreserveValue); Runtime.RunInMainThread(() => { if (IdeApp.Workbench != null) { foreach (var w in IdeApp.Workbench.Documents) { w.StartReparseThread(); } } }); } }
//this runs as a glib idle handler so it can add/remove text editor markers //in order to to block the GUI thread, we batch them in UPDATE_COUNT bool IdleHandler() { if (cancellationToken.IsCancellationRequested) { return(false); } var editor = ext.Editor; if (editor == null) { return(false); } if (id == null) { foreach (var markerQueue in ext.markers) { while (markerQueue.Value.Count != 0) { editor.RemoveMarker(markerQueue.Value.Dequeue()); } } ext.markers.Clear(); return(false); } //clear the old results out at the same rate we add in the new ones for (int i = 0; oldMarkers > 0 && i < UPDATE_COUNT; i++) { if (cancellationToken.IsCancellationRequested) { return(false); } editor.RemoveMarker(ext.markers [id].Dequeue()); oldMarkers--; } //add in the new markers for (int i = 0; i < UPDATE_COUNT; i++) { if (!enumerator.MoveNext()) { ext.tasks [id] = builder.ToImmutable(); ext.OnTasksUpdated(EventArgs.Empty); return(false); } if (cancellationToken.IsCancellationRequested) { return(false); } var currentResult = (Result)enumerator.Current; if (currentResult.InspectionMark != IssueMarker.None) { int start = currentResult.Region.Start; int end = currentResult.Region.End; if (start >= end) { continue; } var marker = TextMarkerFactory.CreateGenericTextSegmentMarker(editor, GetSegmentMarkerEffect(currentResult.InspectionMark), TextSegment.FromBounds(start, end)); marker.Tag = currentResult; marker.IsVisible = currentResult.Underline; if (currentResult.InspectionMark != IssueMarker.GrayOut) { marker.Color = GetColor(editor, currentResult); marker.IsVisible &= currentResult.Level != DiagnosticSeverity.Hidden; } editor.AddMarker(marker); ext.markers [id].Enqueue(marker); } builder.Add(new QuickTask(currentResult.Message, currentResult.Region.Start, currentResult.Level)); } return(true); }
public void Select(int startPosition, int endPosition) { data.SelectionRange = TextSegment.FromBounds(startPosition, endPosition); }
protected override void DocumentParsed() { var parsedDocument = documentContext.ParsedDocument; if (parsedDocument == null) { return; } var resolver = parsedDocument.GetAst <SemanticModel> (); if (resolver == null) { return; } CancelHighlightingTask(); var token = src.Token; var theme = editor.Options.GetEditorTheme(); Task.Run(async delegate { try { var root = await resolver.SyntaxTree.GetRootAsync(token); var newTree = new HighlightingSegmentTree(); var visitor = new HighlightingVisitior(theme, resolver, newTree.Add, token, TextSegment.FromBounds(0, root.FullSpan.Length)); visitor.Visit(root); var doNotify = !AreEqual(highlightTree, newTree, token); if (!token.IsCancellationRequested) { Gtk.Application.Invoke(delegate { if (token.IsCancellationRequested) { return; } if (highlightTree != null) { highlightTree.RemoveListener(); } highlightTree = newTree; highlightTree.InstallListener(editor); if (doNotify) { NotifySemanticHighlightingUpdate(); } }); } } catch (OperationCanceledException) { } catch (AggregateException ae) { ae.Flatten().Handle(x => x is OperationCanceledException); } }, token); }
//this runs as a glib idle handler so it can add/remove text editor markers //in order to to block the GUI thread, we batch them in UPDATE_COUNT bool IdleHandler() { if (cancellationToken.IsCancellationRequested) { return(false); } var editor = ext.Editor; if (editor == null || editor.Document == null) { return(false); } //clear the old results out at the same rate we add in the new ones for (int i = 0; oldMarkers > 0 && i < UPDATE_COUNT; i++) { if (cancellationToken.IsCancellationRequested) { return(false); } editor.Document.RemoveMarker(ext.markers.Dequeue()); oldMarkers--; } //add in the new markers for (int i = 0; i < UPDATE_COUNT; i++) { if (!enumerator.MoveNext()) { ext.OnTasksUpdated(EventArgs.Empty); return(false); } if (cancellationToken.IsCancellationRequested) { return(false); } var currentResult = (Result)enumerator.Current; if (currentResult.InspectionMark != IssueMarker.None) { int start = editor.LocationToOffset(currentResult.Region.Begin); int end = editor.LocationToOffset(currentResult.Region.End); if (start >= end) { continue; } if (currentResult.InspectionMark == IssueMarker.GrayOut) { var marker = new GrayOutMarker(currentResult, TextSegment.FromBounds(start, end)); marker.IsVisible = currentResult.Underline; editor.Document.AddMarker(marker); ext.markers.Enqueue(marker); editor.Parent.TextViewMargin.RemoveCachedLine(editor.GetLineByOffset(start)); editor.Parent.QueueDraw(); } else { var marker = new ResultMarker(currentResult, TextSegment.FromBounds(start, end)); marker.IsVisible = currentResult.Underline; editor.Document.AddMarker(marker); ext.markers.Enqueue(marker); } } ext.tasks.Add(new QuickTask(currentResult.Message, currentResult.Region.Begin, currentResult.Level)); } return(true); }
//this runs as a glib idle handler so it can add/remove text editor markers //in order to to block the GUI thread, we batch them in UPDATE_COUNT bool IdleHandler() { if (cancellationToken.IsCancellationRequested) { return(false); } var editor = ext.Editor; if (editor == null) { return(false); } //clear the old results out at the same rate we add in the new ones for (int i = 0; oldMarkers > 0 && i < UPDATE_COUNT; i++) { if (cancellationToken.IsCancellationRequested) { return(false); } editor.RemoveMarker(ext.markers.Dequeue()); oldMarkers--; } //add in the new markers for (int i = 0; i < UPDATE_COUNT; i++) { if (!enumerator.MoveNext()) { ext.tasks = builder.ToImmutable(); ext.OnTasksUpdated(EventArgs.Empty); return(false); } if (cancellationToken.IsCancellationRequested) { return(false); } var currentResult = (Result)enumerator.Current; if (currentResult.InspectionMark != IssueMarker.None) { int start = currentResult.Region.Start; int end = currentResult.Region.End; if (start >= end) { continue; } if (currentResult.InspectionMark == IssueMarker.GrayOut) { var marker = TextMarkerFactory.CreateGenericTextSegmentMarker(editor, TextSegmentMarkerEffect.GrayOut, TextSegment.FromBounds(start, end)); marker.IsVisible = currentResult.Underline; marker.Tag = currentResult; editor.AddMarker(marker); ext.markers.Enqueue(marker); // editor.Parent.TextViewMargin.RemoveCachedLine (editor.GetLineByOffset (start)); // editor.Parent.QueueDraw (); } else { var effect = currentResult.InspectionMark == IssueMarker.DottedLine ? TextSegmentMarkerEffect.DottedLine : TextSegmentMarkerEffect.WavedLine; var marker = TextMarkerFactory.CreateGenericTextSegmentMarker(editor, effect, TextSegment.FromBounds(start, end)); marker.Color = GetColor(editor, currentResult); marker.IsVisible = currentResult.Underline; marker.Tag = currentResult; editor.AddMarker(marker); ext.markers.Enqueue(marker); } } builder.Add(new QuickTask(currentResult.Message, currentResult.Region.Start, currentResult.Level)); } return(true); }
//this runs as a glib idle handler so it can add/remove text editor markers //in order to to block the GUI thread, we batch them in UPDATE_COUNT bool IdleHandler() { var editor = ext.Editor; if (editor == null) { return(false); } if (id == null) { foreach (var markerQueue in ext.markers) { foreach (var marker in markerQueue.Value) { editor.RemoveMarker(marker); } PutBackCachedList(markerQueue.Value); } ext.markers.Clear(); lock (ext.tasks) ext.tasks.Clear(); ext.OnTasksUpdated(EventArgs.Empty); return(false); } if (cancellationToken.IsCancellationRequested) { FinishUpdateRun(); return(false); } //clear the old results out at the same rate we add in the new ones for (int i = 0; oldMarkerIndex < oldMarkers.Count && i < UPDATE_COUNT; i++) { var oldMarker = oldMarkers [oldMarkerIndex++]; var oldResult = (Result)oldMarker.Tag; if (curResult < results.Count) { Result currentResult = results [curResult]; if (currentResult.Equals(oldResult, oldMarker.Offset)) { oldMarker.Tag = currentResult; newMarkers.Add(oldMarker); if (oldResult.QuickTask != null) { currentResult.QuickTask = oldResult.QuickTask; builder.Add(currentResult.QuickTask); } curResult++; continue; } } editor.RemoveMarker(oldMarker); } //add in the new markers for (int i = 0; i < UPDATE_COUNT; i++) { if (curResult >= results.Count) { FinishUpdateRun(); return(false); } var currentResult = results [curResult++]; if (currentResult.InspectionMark != IssueMarker.None) { int start = currentResult.Region.Start; int end = currentResult.Region.End; if (start > end) { continue; } // In case a diagnostic has a 0 length span, force it to 1. if (start == end) { end = end + 1; } var marker = TextMarkerFactory.CreateGenericTextSegmentMarker(editor, GetSegmentMarkerEffect(currentResult.InspectionMark), TextSegment.FromBounds(start, end)); marker.Tag = currentResult; marker.IsVisible = currentResult.Underline; if (currentResult.InspectionMark != IssueMarker.GrayOut) { marker.Color = GetColor(editor, currentResult); marker.IsVisible &= currentResult.Level != DiagnosticSeverity.Hidden; } editor.AddMarker(marker); newMarkers.Add(marker); } builder.Add(currentResult.QuickTask = new QuickTask(currentResult.Message, currentResult.Region.Start, currentResult.Level)); } return(true); }
/// <summary> /// Don't use this unless you're implementing ICodeTemplateWidget. Use Insert instead. /// </summary> public TemplateResult InsertTemplateContents(TextEditor editor, DocumentContext context) { var data = editor; int offset = data.CaretOffset; // string leadingWhiteSpace = GetLeadingWhiteSpace (editor, editor.CursorLine); var templateCtx = new TemplateContext { Template = this, DocumentContext = context, Editor = editor, //ParsedDocument = context.ParsedDocument != null ? context.ParsedDocument.ParsedFile : null, InsertPosition = data.CaretLocation, LineIndent = data.GetLineIndent(data.CaretLocation.Line), TemplateCode = Code }; if (data.IsSomethingSelected) { int start = data.SelectionRange.Offset; while (Char.IsWhiteSpace(data.GetCharAt(start))) { start++; } int end = data.SelectionRange.EndOffset; while (Char.IsWhiteSpace(data.GetCharAt(end - 1))) { end--; } templateCtx.LineIndent = data.GetLineIndent(data.OffsetToLineNumber(start)); templateCtx.SelectedText = RemoveIndent(data.GetTextBetween(start, end), templateCtx.LineIndent); data.RemoveText(start, end - start); offset = start; } else { string word = GetTemplateShortcutBeforeCaret(data).Trim(); if (word.Length > 0) { offset = DeleteTemplateShortcutBeforeCaret(data); } } TemplateResult template = FillVariables(templateCtx); template.InsertPosition = offset; editor.InsertText(offset, template.Code); int newoffset; if (template.CaretEndOffset >= 0) { newoffset = offset + template.CaretEndOffset; } else { newoffset = offset + template.Code.Length; } editor.CaretLocation = editor.OffsetToLocation(newoffset); var prettyPrinter = CodeFormatterService.GetFormatter(data.MimeType); if (prettyPrinter != null && prettyPrinter.SupportsOnTheFlyFormatting) { int endOffset = template.InsertPosition + template.Code.Length; var oldVersion = data.Version; prettyPrinter.OnTheFlyFormat(editor, context, TextSegment.FromBounds(template.InsertPosition, editor.CaretOffset)); if (editor.CaretOffset < endOffset) { prettyPrinter.OnTheFlyFormat(editor, context, TextSegment.FromBounds(editor.CaretOffset, endOffset)); } foreach (var textLink in template.TextLinks) { for (int i = 0; i < textLink.Links.Count; i++) { var segment = textLink.Links [i]; var translatedOffset = oldVersion.MoveOffsetTo(data.Version, template.InsertPosition + segment.Offset) - template.InsertPosition; textLink.Links [i] = new TextSegment(translatedOffset, segment.Length); } } } return(template); }
//this runs as a glib idle handler so it can add/remove text editor markers //in order to to block the GUI thread, we batch them in UPDATE_COUNT bool IdleHandler() { try { var editor = ext.Editor; if (editor == null) { return(false); } if (id == null) { ext.RemoveMarkersAndTasks(); return(false); } //clear the old results out at the same rate we add in the new ones if (oldMarkers != null) { for (int i = 0; oldMarkerIndex < oldMarkers.Count && i < UPDATE_COUNT; i++) { var oldMarker = oldMarkers [oldMarkerIndex++]; var oldResult = (Result)oldMarker.Tag; if (oldResult != null && curResult < results.Count) { Result currentResult = results [curResult]; if (currentResult.Equals(oldResult, oldMarker.Offset)) { oldMarker.Tag = currentResult; newMarkers.Add(oldMarker); if (oldResult.QuickTask != null) { currentResult.QuickTask = oldResult.QuickTask; builder.Add(currentResult.QuickTask); } curResult++; continue; } } editor.RemoveMarker(oldMarker); } } //add in the new markers for (int i = 0; i < UPDATE_COUNT; i++) { if (curResult >= results.Count) { FinishUpdateRun(); return(false); } var currentResult = results [curResult++]; if (currentResult.InspectionMark != IssueMarker.None) { int start = currentResult.Region.Start; int end = currentResult.Region.End; if (start > end) { continue; } // In case a diagnostic has a 0 length span, force it to 1. if (start == end) { end = end + 1; } var marker = TextMarkerFactory.CreateGenericTextSegmentMarker(editor, GetSegmentMarkerEffect(currentResult.InspectionMark), TextSegment.FromBounds(start, end)); marker.Tag = currentResult; marker.IsVisible = currentResult.Underline; if (currentResult.InspectionMark != IssueMarker.GrayOut) { marker.Color = GetColor(editor, currentResult); marker.IsVisible &= currentResult.Level != DiagnosticSeverity.Hidden; } editor.AddMarker(marker); newMarkers.Add(marker); } builder.Add(currentResult.QuickTask = new QuickTask(currentResult.Message, currentResult.Region.Start, currentResult.Level)); } return(true); } catch (Exception ex) { LoggingService.LogInternalError("Error while ResutsUpdater.IdleHandler", ex); return(false); } }