static void InsertDocumentationComments(ITextEditor editor, int lineNr, int cursorOffset) { string terminator = DocumentUtilitites.GetLineTerminator(editor.Document, lineNr); IDocumentLine currentLine = editor.Document.GetLine(lineNr); IDocumentLine previousLine = (lineNr > 1) ? editor.Document.GetLine(lineNr - 1) : null; string curLineText = currentLine.Text; string lineAboveText = previousLine == null ? null : previousLine.Text; if (curLineText != null && curLineText.EndsWith("'''", StringComparison.OrdinalIgnoreCase) && (lineAboveText == null || !lineAboveText.Trim().StartsWith("'''", StringComparison.OrdinalIgnoreCase))) { string indentation = DocumentUtilitites.GetWhitespaceAfter(editor.Document, currentLine.Offset); object member = GetMemberAfter(editor, lineNr); if (member != null) { StringBuilder sb = new StringBuilder(); sb.Append(" <summary>"); sb.Append(terminator); sb.Append(indentation); sb.Append("''' "); sb.Append(terminator); sb.Append(indentation); sb.Append("''' </summary>"); if (member is IMethod) { IMethod method = (IMethod)member; if (method.Parameters != null && method.Parameters.Count > 0) { for (int i = 0; i < method.Parameters.Count; ++i) { sb.Append(terminator); sb.Append(indentation); sb.Append("''' <param name=\""); sb.Append(method.Parameters[i].Name); sb.Append("\"></param>"); } } if (method.ReturnType != null && !method.IsConstructor && method.ReturnType.FullyQualifiedName != "System.Void") { sb.Append(terminator); sb.Append(indentation); sb.Append("''' <returns></returns>"); } } editor.Document.Insert(cursorOffset, sb.ToString()); editor.Caret.Position = editor.Document.OffsetToPosition(cursorOffset + indentation.Length + "/// ".Length + " <summary>".Length + terminator.Length); } } }
protected override void Run(ITextEditor editor, string clipboardText) { string indentation = GetIndentation(editor.Document, editor.Caret.Line); IAmbience ambience = AmbienceService.GetCurrentAmbience(); int maxLineLength = editor.Options.VerticalRulerColumn - VisualIndentationLength(editor, indentation); StringWriter insertedText = new StringWriter(); insertedText.NewLine = DocumentUtilitites.GetLineTerminator(editor.Document, editor.Caret.Line); using (StringReader reader = new StringReader(clipboardText)) { string line; while ((line = reader.ReadLine()) != null) { AppendTextLine(indentation, ambience, maxLineLength, insertedText, line); } } IDocument document = editor.Document; int insertionPos = document.GetLine(editor.Caret.Line).Offset + indentation.Length; document.Insert(insertionPos, insertedText.ToString()); }
/// <summary> /// C# only. /// </summary> public static void AddCodeToMethodStart(IMember m, ITextEditor textArea, string newCode) { int methodStart = FindMethodStartOffset(textArea.Document, m.BodyRegion); if (methodStart < 0) { return; } textArea.Select(methodStart, 0); using (textArea.Document.OpenUndoGroup()) { int startLine = textArea.Caret.Line; foreach (string newCodeLine in newCode.Split('\n')) { textArea.Document.Insert(textArea.Caret.Offset, DocumentUtilitites.GetLineTerminator(textArea.Document, textArea.Caret.Line) + newCodeLine); } int endLine = textArea.Caret.Line; textArea.Language.FormattingStrategy.IndentLines(textArea, startLine, endLine); } }
public string GetOldVersionFromLine(int lineNumber, out int newStartLine, out bool added) { LineChangeInfo info = changeList[lineNumber]; added = info.Change == ChangeType.Added; if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) { newStartLine = CalculateNewStartLineNumber(lineNumber); if (info.Change == ChangeType.Added) { return(""); } var startDocumentLine = baseDocument.GetLine(info.OldStartLineNumber + 1); var endLine = baseDocument.GetLine(info.OldEndLineNumber); return(TextUtilities.NormalizeNewLines(baseDocument.GetText(startDocumentLine.Offset, endLine.EndOffset - startDocumentLine.Offset), DocumentUtilitites.GetLineTerminator(document, newStartLine == 0 ? 1 : newStartLine))); } newStartLine = 0; return(null); }
void FormatLineInternal(ITextEditor editor, int lineNr, int cursorOffset, char ch) { string terminator = DocumentUtilitites.GetLineTerminator(editor.Document, lineNr); doCasing = PropertyService.Get("VBBinding.TextEditor.EnableCasing", true); doInsertion = PropertyService.Get("VBBinding.TextEditor.EnableEndConstructs", true); IDocumentLine currentLine = editor.Document.GetLine(lineNr); IDocumentLine lineAbove = lineNr > 1 ? editor.Document.GetLine(lineNr - 1) : null; string curLineText = currentLine == null ? "" : currentLine.Text; string lineAboveText = lineAbove == null ? "" : lineAbove.Text; if (ch == '\'') { InsertDocumentationComments(editor, lineNr, cursorOffset); } if (ch == '\n' && lineAboveText != null) { if (LanguageUtils.IsInsideDocumentationComment(editor, lineAbove, lineAbove.EndOffset)) { editor.Document.Insert(cursorOffset, "''' "); return; } string textToReplace = lineAboveText.TrimLine(); if (doCasing) { DoCasingOnLine(lineAbove, textToReplace, editor); } if (doInsertion) { DoInsertionOnLine(terminator, currentLine, lineAbove, textToReplace, editor, lineNr); } if (IsInString(lineAboveText)) { if (IsFinishedString(curLineText)) { editor.Document.Insert(lineAbove.EndOffset, "\" & _"); editor.Document.Insert(currentLine.Offset, "\""); } else { editor.Document.Insert(lineAbove.EndOffset, "\""); } } else { string indent = DocumentUtilitites.GetWhitespaceAfter(editor.Document, lineAbove.Offset); if (indent.Length > 0) { string newLineText = indent + currentLine.Text.Trim(); editor.Document.Replace(currentLine.Offset, currentLine.Length, newLineText); } editor.Caret.Column = indent.Length + 1; } IndentLines(editor, lineNr - 1, lineNr); } else if (ch == '>') { if (LanguageUtils.IsInsideDocumentationComment(editor, currentLine, cursorOffset)) { int column = editor.Caret.Offset - currentLine.Offset; int index = Math.Min(column - 1, curLineText.Length - 1); while (index > 0 && curLineText[index] != '<') { --index; if (curLineText[index] == '/') { return; // the tag was an end tag or already } } if (index > 0) { StringBuilder commentBuilder = new StringBuilder(""); for (int i = index; i < curLineText.Length && i < column && !Char.IsWhiteSpace(curLineText[i]); ++i) { commentBuilder.Append(curLineText[i]); } string tag = commentBuilder.ToString().Trim(); if (!tag.EndsWith(">", StringComparison.OrdinalIgnoreCase)) { tag += ">"; } if (!tag.StartsWith("/", StringComparison.OrdinalIgnoreCase)) { string endTag = "</" + tag.Substring(1); editor.Document.Insert(editor.Caret.Offset, endTag); editor.Caret.Offset -= endTag.Length; } } } } }
void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char ch) { IDocumentLine curLine = textArea.Document.GetLine(lineNr); IDocumentLine lineAbove = lineNr > 1 ? textArea.Document.GetLine(lineNr - 1) : null; string terminator = DocumentUtilitites.GetLineTerminator(textArea.Document, lineNr); string curLineText; //// local string for curLine segment if (ch == '/') { curLineText = curLine.Text; string lineAboveText = lineAbove == null ? "" : lineAbove.Text; if (curLineText != null && curLineText.EndsWith("///") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///"))) { string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); object member = GetMemberAfter(textArea, lineNr); if (member != null) { StringBuilder sb = new StringBuilder(); sb.Append(" <summary>"); sb.Append(terminator); sb.Append(indentation); sb.Append("/// "); sb.Append(terminator); sb.Append(indentation); sb.Append("/// </summary>"); if (member is IMethod) { IMethod method = (IMethod)member; if (method.Parameters != null && method.Parameters.Count > 0) { for (int i = 0; i < method.Parameters.Count; ++i) { sb.Append(terminator); sb.Append(indentation); sb.Append("/// <param name=\""); sb.Append(method.Parameters[i].Name); sb.Append("\"></param>"); } } if (method.ReturnType != null && !method.IsConstructor && method.ReturnType.FullyQualifiedName != "System.Void") { sb.Append(terminator); sb.Append(indentation); sb.Append("/// <returns></returns>"); } } textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Caret.Offset = cursorOffset + indentation.Length + "/// ".Length + " <summary>".Length + terminator.Length; } } return; } if (ch != '\n' && ch != '>') { if (IsInsideStringOrComment(textArea, curLine, cursorOffset)) { return; } } switch (ch) { case '>': if (IsInsideDocumentationComment(textArea, curLine, cursorOffset)) { curLineText = curLine.Text; int column = cursorOffset - curLine.Offset; int index = Math.Min(column - 1, curLineText.Length - 1); while (index >= 0 && curLineText[index] != '<') { --index; if (curLineText[index] == '/') { return; // the tag was an end tag or already } } if (index > 0) { StringBuilder commentBuilder = new StringBuilder(""); for (int i = index; i < curLineText.Length && i < column && !Char.IsWhiteSpace(curLineText[i]); ++i) { commentBuilder.Append(curLineText[i]); } string tag = commentBuilder.ToString().Trim(); if (!tag.EndsWith(">")) { tag += ">"; } if (!tag.StartsWith("/")) { textArea.Document.Insert(cursorOffset, "</" + tag.Substring(1), AnchorMovementType.BeforeInsertion); } } } break; case ':': case ')': case ']': case '}': case '{': //if (textArea.Document.TextEditorProperties.IndentStyle == IndentStyle.Smart) { IndentLine(textArea, curLine); //} break; case '\n': string lineAboveText = lineAbove == null ? "" : lineAbove.Text; //// curLine might have some text which should be added to indentation curLineText = curLine.Text; if (lineAbove != null && lineAbove.Text.Trim().StartsWith("#region") && NeedEndregion(textArea.Document)) { textArea.Document.Insert(cursorOffset, "#endregion"); return; } ISyntaxHighlighter highlighter = textArea.GetService(typeof(ISyntaxHighlighter)) as ISyntaxHighlighter; bool isInMultilineComment = false; bool isInMultilineString = false; if (highlighter != null && lineAbove != null) { var spanStack = highlighter.GetSpanColorNamesFromLineStart(lineNr); isInMultilineComment = spanStack.Contains(SyntaxHighligherKnownSpanNames.Comment); isInMultilineString = spanStack.Contains(SyntaxHighligherKnownSpanNames.String); } bool isInNormalCode = !(isInMultilineComment || isInMultilineString); if (lineAbove != null && isInMultilineComment) { string lineAboveTextTrimmed = lineAboveText.TrimStart(); if (lineAboveTextTrimmed.StartsWith("/*", StringComparison.Ordinal)) { textArea.Document.Insert(cursorOffset, " * "); return; } if (lineAboveTextTrimmed.StartsWith("*", StringComparison.Ordinal)) { textArea.Document.Insert(cursorOffset, "* "); return; } } if (lineAbove != null && isInNormalCode) { IDocumentLine nextLine = lineNr + 1 <= textArea.Document.TotalNumberOfLines ? textArea.Document.GetLine(lineNr + 1) : null; string nextLineText = (nextLine != null) ? nextLine.Text : ""; int indexAbove = lineAboveText.IndexOf("///"); int indexNext = nextLineText.IndexOf("///"); if (indexAbove > 0 && (indexNext != -1 || indexAbove + 4 < lineAbove.Length)) { textArea.Document.Insert(cursorOffset, "/// "); return; } if (IsInNonVerbatimString(lineAboveText, curLineText)) { textArea.Document.Insert(cursorOffset, "\""); textArea.Document.Insert(lineAbove.Offset + lineAbove.Length, "\" +"); } } if (textArea.Options.AutoInsertBlockEnd && lineAbove != null && isInNormalCode) { string oldLineText = lineAbove.Text; if (oldLineText.EndsWith("{")) { if (NeedCurlyBracket(textArea.Document.Text)) { int insertionPoint = curLine.Offset + curLine.Length; textArea.Document.Insert(insertionPoint, terminator + "}"); IndentLine(textArea, textArea.Document.GetLine(lineNr + 1)); textArea.Caret.Offset = insertionPoint; } } } return; } }
void DisplayTooltip(MouseEventArgs e) { int line = GetLineFromMousePosition(e); if (line == 0) { return; } int startLine; bool added; string oldText = changeWatcher.GetOldVersionFromLine(line, out startLine, out added); TextEditor editor = this.TextView.Services.GetService(typeof(TextEditor)) as TextEditor; markerService = this.TextView.Services.GetService(typeof(ITextMarkerService)) as ITextMarkerService; LineChangeInfo zeroLineInfo = changeWatcher.GetChange(0); int offset, length; bool hasNewVersion = changeWatcher.GetNewVersionFromLine(line, out offset, out length); if (line == 1 && zeroLineInfo.Change == ChangeType.Deleted) { int zeroStartLine; bool zeroAdded; startLine = 1; string deletedText = changeWatcher.GetOldVersionFromLine(0, out zeroStartLine, out zeroAdded); var docLine = editor.Document.GetLineByNumber(line); string newLine = DocumentUtilitites.GetLineTerminator(changeWatcher.CurrentDocument, 1); deletedText += newLine; deletedText += editor.Document.GetText(docLine.Offset, docLine.Length); if (oldText != null) { oldText = deletedText + newLine + oldText; } else { oldText = deletedText; } if (!hasNewVersion) { offset = 0; length = docLine.Length; hasNewVersion = true; } } if (hasNewVersion) { if (marker != null) { markerService.Remove(marker); } if (length <= 0) { marker = null; length = 0; } else { marker = markerService.Create(offset, length); marker.BackgroundColor = Colors.LightGreen; } } if (oldText != null) { LineChangeInfo currLineInfo = changeWatcher.GetChange(startLine); if (currLineInfo.Change == ChangeType.Deleted && !(line == 1 && zeroLineInfo.Change == ChangeType.Deleted)) { var docLine = editor.Document.GetLineByNumber(startLine); if (docLine.DelimiterLength == 0) { oldText = DocumentUtilitites.GetLineTerminator(changeWatcher.CurrentDocument, startLine) + oldText; } oldText = editor.Document.GetText(docLine.Offset, docLine.TotalLength) + oldText; } DiffControl differ = new DiffControl(); differ.editor.SyntaxHighlighting = editor.SyntaxHighlighting; differ.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; differ.editor.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden; differ.editor.Document.Text = oldText; differ.Background = Brushes.White; if (oldText == string.Empty) { differ.editor.Visibility = Visibility.Collapsed; differ.copyButton.Visibility = Visibility.Collapsed; } else { var baseDocument = new TextDocument(DocumentUtilitites.GetTextSource(changeWatcher.BaseDocument)); if (differ.editor.SyntaxHighlighting != null) { var mainHighlighter = new DocumentHighlighter(baseDocument, differ.editor.SyntaxHighlighting.MainRuleSet); var popupHighlighter = differ.editor.TextArea.GetService(typeof(IHighlighter)) as DocumentHighlighter; popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(currLineInfo.OldStartLineNumber); } } differ.revertButton.Click += delegate { if (hasNewVersion) { Document.Replace(offset, length, oldText); tooltip.IsOpen = false; } }; tooltip.Child = new Border() { Child = differ, BorderBrush = Brushes.Black, BorderThickness = new Thickness(1) }; if (tooltip.IsOpen) { tooltip.IsOpen = false; } tooltip.IsOpen = true; tooltip.Closed += delegate { if (marker != null) { markerService.Remove(marker); } }; tooltip.HorizontalOffset = -10; tooltip.VerticalOffset = TextView.GetVisualTopByDocumentLine(startLine) - TextView.ScrollOffset.Y; tooltip.Placement = PlacementMode.Top; tooltip.PlacementTarget = this.TextView; } }
void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char ch) { IDocumentLine curLine = textArea.Document.GetLine(lineNr); IDocumentLine lineAbove = lineNr > 1 ? textArea.Document.GetLine(lineNr - 1) : null; string terminator = DocumentUtilitites.GetLineTerminator(textArea.Document, lineNr); string curLineText; //// local string for curLine segment if (ch == '-') { curLineText = curLine.Text; string lineAboveText = lineAbove == null ? "" : lineAbove.Text; if (curLineText != null && curLineText.EndsWith("---") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("---"))) { string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); StringBuilder sb = new StringBuilder(); sb.Append(" <summary>"); sb.Append(terminator); sb.Append(indentation); sb.Append("--- "); sb.Append(terminator); sb.Append(indentation); sb.Append("--- </summary>"); //sb.Append(terminator); //sb.Append(indentation); //sb.Append("--- <returns></returns>"); textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Caret.Offset = cursorOffset + indentation.Length + "--- ".Length + " <summary>".Length + terminator.Length; } else if (curLineText != null && curLineText.Trim() == "-" && (lineAboveText != null && lineAboveText.Trim().StartsWith("---"))) { StringBuilder sb = new StringBuilder(); sb.Append("-- "); //sb.Append(terminator); //sb.Append(indentation); //sb.Append("--- <returns></returns>"); textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Caret.Offset = cursorOffset + "-- ".Length; } return; } if (ch != '\n' && ch != '>') { if (IsInsideStringOrComment(textArea, curLine, cursorOffset)) { return; } } if (IsInsideStringOrComment(textArea, curLine, cursorOffset) == false && textArea.Caret.Offset == curLine.EndOffset && // end of line, not editing something inside the line (curLine.Text.TrimEnd().EndsWith("then") || curLine.Text.TrimEnd().EndsWith("do"))) { string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); StringBuilder sb = new StringBuilder(); sb.Append(terminator); sb.Append(indentation + textArea.Options.IndentationString); sb.Append(terminator); sb.Append(indentation); sb.Append("end"); textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Caret.Offset = cursorOffset + terminator.Length // end of line + indentation.Length // indentation + textArea.Options.IndentationString.Length ; } if (IsInsideStringOrComment(textArea, curLine, cursorOffset) == false && textArea.Caret.Offset == curLine.EndOffset && // end of line, not editing something inside the line curLine.Text.TrimStart().StartsWith("repeat")) { string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); StringBuilder sb = new StringBuilder(); sb.Append(terminator); sb.Append(indentation + textArea.Options.IndentationString); sb.Append(terminator); sb.Append(indentation); sb.Append("until "); textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Caret.Offset = cursorOffset + indentation.Length + terminator.Length // line 1 + indentation.Length + textArea.Options.IndentationString.Length + terminator.Length // line 2 + "until ".Length ; } switch (ch) { case '>': if (IsInsideDocumentationComment(textArea, curLine, cursorOffset)) { curLineText = curLine.Text; int column = cursorOffset - curLine.Offset; int index = Math.Min(column - 1, curLineText.Length - 1); while (index >= 0 && curLineText[index] != '<') { --index; if (curLineText[index] == '/') { return; // the tag was an end tag or already } } if (index > 0) { StringBuilder commentBuilder = new StringBuilder(""); for (int i = index; i < curLineText.Length && i < column && !Char.IsWhiteSpace(curLineText[i]); ++i) { commentBuilder.Append(curLineText[i]); } string tag = commentBuilder.ToString().Trim(); if (!tag.EndsWith(">")) { tag += ">"; } if (!tag.StartsWith("/")) { textArea.Document.Insert(cursorOffset, "</" + tag.Substring(1), AnchorMovementType.BeforeInsertion); } } } break; case ')': if (curLine.Text.TrimStart().StartsWith("function")) { string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); StringBuilder sb = new StringBuilder(); sb.Append(terminator); sb.Append(indentation + textArea.Options.IndentationString); sb.Append(terminator); sb.Append(indentation); sb.Append("end"); textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Caret.Offset = cursorOffset + terminator.Length // end of line + indentation.Length // indentation + textArea.Options.IndentationString.Length ; } else { IndentLine(textArea, curLine); } break; case ':': case ']': case '}': case '{': IndentLine(textArea, curLine); break; case '\n': string lineAboveText = lineAbove == null ? "" : lineAbove.Text; //// curLine might have some text which should be added to indentation curLineText = curLine.Text; ISyntaxHighlighter highlighter = textArea.GetService(typeof(ISyntaxHighlighter)) as ISyntaxHighlighter; bool isInMultilineComment = false; bool isInMultilineString = false; if (highlighter != null && lineAbove != null) { var spanStack = highlighter.GetSpanColorNamesFromLineStart(lineNr); isInMultilineComment = spanStack.Contains(SyntaxHighligherKnownSpanNames.Comment); isInMultilineString = spanStack.Contains(SyntaxHighligherKnownSpanNames.String); } bool isInNormalCode = !(isInMultilineComment || isInMultilineString); if (lineAbove != null && isInMultilineComment) { string lineAboveTextTrimmed = lineAboveText.TrimStart(); if (lineAboveTextTrimmed.StartsWith("--[[", StringComparison.Ordinal)) { textArea.Document.Insert(cursorOffset, " - "); return; } if (lineAboveTextTrimmed.StartsWith("-", StringComparison.Ordinal)) { textArea.Document.Insert(cursorOffset, "- "); return; } } if (lineAbove != null && isInNormalCode) { IDocumentLine nextLine = lineNr + 1 <= textArea.Document.TotalNumberOfLines ? textArea.Document.GetLine(lineNr + 1) : null; string nextLineText = (nextLine != null) ? nextLine.Text : ""; int indexAbove = lineAboveText.IndexOf("---"); int indexNext = nextLineText.IndexOf("---"); if (indexAbove > 0 && (indexNext != -1 || indexAbove + 4 < lineAbove.Length)) { textArea.Document.Insert(cursorOffset, "--- "); return; } if (IsInNonVerbatimString(lineAboveText, curLineText)) { textArea.Document.Insert(cursorOffset, "\""); textArea.Document.Insert(lineAbove.Offset + lineAbove.Length, "\" +"); } } return; } }
void DisplayTooltip(MouseEventArgs e) { int line = GetLineFromMousePosition(e); if (line == 0) { return; } int startLine; bool added; string oldText = changeWatcher.GetOldVersionFromLine(line, out startLine, out added); TextEditor editor = this.TextView.Services.GetService(typeof(TextEditor)) as TextEditor; markerService = this.TextView.Services.GetService(typeof(ITextMarkerService)) as ITextMarkerService; int offset, length; bool hasNewVersion = changeWatcher.GetNewVersionFromLine(line, out offset, out length); if (hasNewVersion) { if (marker != null) { markerService.Remove(marker); } if (length <= 0) { marker = null; length = 0; } else { marker = markerService.Create(offset, length); marker.BackgroundColor = Colors.LightGreen; } } if (oldText != null) { DiffControl differ = new DiffControl(); differ.editor.SyntaxHighlighting = editor.SyntaxHighlighting; differ.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; differ.editor.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden; differ.editor.Document.Text = oldText; differ.Background = Brushes.White; // TODO : deletions on line 0 cannot be displayed. LineChangeInfo prevLineInfo = changeWatcher.GetChange(startLine - 1); LineChangeInfo lineInfo = changeWatcher.GetChange(startLine); if (prevLineInfo.Change == ChangeType.Deleted) { var docLine = editor.Document.GetLineByNumber(startLine - 1); differ.editor.Document.Insert(0, editor.Document.GetText(docLine.Offset, docLine.TotalLength)); } if (oldText == string.Empty) { differ.editor.Visibility = Visibility.Collapsed; differ.copyButton.Visibility = Visibility.Collapsed; } else { var baseDocument = new TextDocument(changeWatcher.BaseDocument.Text); if (differ.editor.SyntaxHighlighting != null) { var mainHighlighter = new DocumentHighlighter(baseDocument, differ.editor.SyntaxHighlighting.MainRuleSet); var popupHighlighter = differ.editor.TextArea.GetService(typeof(IHighlighter)) as DocumentHighlighter; if (prevLineInfo.Change == ChangeType.Deleted) { popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(prevLineInfo.OldStartLineNumber); } else { popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(lineInfo.OldStartLineNumber); } } } differ.revertButton.Click += delegate { if (hasNewVersion) { int delimiter = 0; DocumentLine l = Document.GetLineByOffset(offset + length); if (added) { delimiter = l.DelimiterLength; } if (length == 0) { oldText += DocumentUtilitites.GetLineTerminator(new AvalonEditDocumentAdapter(Document, null), l.LineNumber); } Document.Replace(offset, length + delimiter, oldText); tooltip.IsOpen = false; } }; tooltip.Child = new Border() { Child = differ, BorderBrush = Brushes.Black, BorderThickness = new Thickness(1) }; if (tooltip.IsOpen) { tooltip.IsOpen = false; } tooltip.IsOpen = true; tooltip.Closed += delegate { if (marker != null) { markerService.Remove(marker); } }; tooltip.HorizontalOffset = -10; tooltip.VerticalOffset = TextView.GetVisualTopByDocumentLine(startLine) - TextView.ScrollOffset.Y; tooltip.Placement = PlacementMode.Top; tooltip.PlacementTarget = this.TextView; } }