public void FixUpFirstPartOfDelimiter() { document.Text = "a\n\nb"; document.Replace(1, 1, "\r"); Assert.AreEqual("a\r\nb", document.Text); CheckDocumentLines("a", "b"); }
/// <summary> /// Replaces the text in a line. /// If only whitespace at the beginning and end of the line was changed, this method /// only adjusts the whitespace and doesn't replace the other text. /// </summary> public static void SmartReplaceLine(this TextDocument document, DocumentLine line, string newLineText) { if (document == null) { throw new ArgumentNullException("document"); } if (line == null) { throw new ArgumentNullException("line"); } if (newLineText == null) { throw new ArgumentNullException("newLineText"); } string newLineTextTrim = newLineText.Trim(whitespaceChars); string oldLineText = document.GetText(line); if (oldLineText == newLineText) { return; } int pos = oldLineText.IndexOf(newLineTextTrim, StringComparison.Ordinal); if (newLineTextTrim.Length > 0 && pos >= 0) { using (document.RunUpdate()) { // find whitespace at beginning int startWhitespaceLength = 0; while (startWhitespaceLength < newLineText.Length) { char c = newLineText[startWhitespaceLength]; if (c != ' ' && c != '\t') { break; } startWhitespaceLength++; } // find whitespace at end int endWhitespaceLength = newLineText.Length - newLineTextTrim.Length - startWhitespaceLength; // replace whitespace sections int lineOffset = line.Offset; document.Replace(lineOffset + pos + newLineTextTrim.Length, line.Length - pos - newLineTextTrim.Length, newLineText.Substring(newLineText.Length - endWhitespaceLength)); document.Replace(lineOffset, pos, newLineText.Substring(0, startWhitespaceLength)); } } else { document.Replace(line.Offset, line.Length, newLineText); } }
public void IndentLine(TextDocument document, DocumentLine line) { if (document == null || line == null) { return; } DocumentLine previousLine = line.PreviousLine; if (previousLine != null) { ISegment indentationSegment = TextUtilities.GetWhitespaceAfter(document, previousLine.Offset); string indentation = document.GetText(indentationSegment); if (Program.OptionsObject.Editor_AgressiveIndentation) { string currentLineTextTrimmed = (document.GetText(line)).Trim(); string lastLineTextTrimmed = (document.GetText(previousLine)).Trim(); char currentLineFirstNonWhitespaceChar = ' '; if (currentLineTextTrimmed.Length > 0) { currentLineFirstNonWhitespaceChar = currentLineTextTrimmed[0]; } char lastLineLastNonWhitespaceChar = ' '; if (lastLineTextTrimmed.Length > 0) { lastLineLastNonWhitespaceChar = lastLineTextTrimmed[lastLineTextTrimmed.Length - 1]; } if (lastLineLastNonWhitespaceChar == '{' && currentLineFirstNonWhitespaceChar != '}') { indentation += "\t"; } else if (currentLineFirstNonWhitespaceChar == '}') { if (indentation.Length > 0) { indentation = indentation.Substring(0, indentation.Length - 1); } else { indentation = string.Empty; } } /*if (lastLineTextTrimmed == "{" && currentLineTextTrimmed != "}") { indentation += "\t"; } else if (currentLineTextTrimmed == "}") { if (indentation.Length > 0) { indentation = indentation.Substring(0, indentation.Length - 1); } else { indentation = string.Empty; } }*/ } indentationSegment = TextUtilities.GetWhitespaceAfter(document, line.Offset); document.Replace(indentationSegment, indentation); } }
public void ShortReplacements() { char[] chars = { 'a', 'b', '\r', '\n' }; char[] buffer = new char[20]; for (int i = 0; i < 2500; i++) { int offset = rnd.Next(0, document.TextLength); int length = rnd.Next(0, document.TextLength - offset); int newTextLength = rnd.Next(0, 20); for (int j = 0; j < newTextLength; j++) { buffer[j] = chars[rnd.Next(0, chars.Length)]; } document.Replace(offset, length, new string(buffer, 0, newTextLength)); CheckLines(); } }
public void MoveAnchorsDuringReplace() { document.Text = "abcd"; TextAnchor start = document.CreateAnchor(1); TextAnchor middleDeletable = document.CreateAnchor(2); TextAnchor middleSurvivorLeft = document.CreateAnchor(2); middleSurvivorLeft.SurviveDeletion = true; middleSurvivorLeft.MovementType = AnchorMovementType.BeforeInsertion; TextAnchor middleSurvivorRight = document.CreateAnchor(2); middleSurvivorRight.SurviveDeletion = true; middleSurvivorRight.MovementType = AnchorMovementType.AfterInsertion; TextAnchor end = document.CreateAnchor(3); document.Replace(1, 2, "BxC"); Assert.AreEqual(1, start.Offset); Assert.IsTrue(middleDeletable.IsDeleted); Assert.AreEqual(1, middleSurvivorLeft.Offset); Assert.AreEqual(4, middleSurvivorRight.Offset); Assert.AreEqual(4, end.Offset); }
/// <inheritdoc/> public virtual void IndentLine(TextDocument document, DocumentLine line) { if (document == null) throw new ArgumentNullException("document"); if (line == null) throw new ArgumentNullException("line"); DocumentLine previousLine = line.PreviousLine; if (previousLine != null) { ISegment indentationSegment = TextUtilities.GetWhitespaceAfter(document, previousLine.Offset); string indentation = document.GetText(indentationSegment); // copy indentation to line indentationSegment = TextUtilities.GetWhitespaceAfter(document, line.Offset); document.Replace(indentationSegment, indentation); } }
/// <summary> /// Sets the indentation for the specified line. /// Usually this is constructed from the indentation of the previous line. /// </summary> /// <param name="document"></param> /// <param name="line"></param> public void IndentLine(TextDocument document, DocumentLine line) { var pLine = line.PreviousLine; if (pLine != null) { var segment = TextUtilities.GetWhitespaceAfter(document, pLine.Offset); var indentation = document.GetText(segment); var amount = HtmlParser.CountUnclosedTags(document.GetText(pLine)); if (amount > 0) indentation += new string('\t', amount); document.Replace(TextUtilities.GetWhitespaceAfter(document, line.Offset), indentation); } }
public void BackwardChanges() { TextDocument document = new TextDocument("initial text"); ITextSource snapshot1 = document.CreateSnapshot(); document.Replace(0, 7, "nw"); document.Insert(1, "e"); ITextSource snapshot2 = document.CreateSnapshot(); Assert.AreEqual(1, snapshot2.Version.CompareAge(snapshot1.Version)); TextChangeEventArgs[] arr = snapshot2.Version.GetChangesTo(snapshot1.Version).ToArray(); Assert.AreEqual(2, arr.Length); Assert.AreEqual("", arr[0].InsertedText.Text); Assert.AreEqual("initial", arr[1].InsertedText.Text); Assert.AreEqual("initial text", snapshot1.Text); Assert.AreEqual("new text", snapshot2.Text); }
/// <inheritdoc/> public virtual void IndentLine(TextDocument document, DocumentLine line) { if (document == null) throw new ArgumentNullException(nameof(document)); if (line == null) throw new ArgumentNullException(nameof(line)); if (line.PreviousLine != null) { var indentationSegment = TextUtilities.GetWhitespaceAfter(document, line.PreviousLine.Offset); var indentation = document.GetText(indentationSegment); // copy indentation to line indentationSegment = TextUtilities.GetWhitespaceAfter(document, line.Offset); document.Replace(indentationSegment, indentation); } }
/// <inheritdoc/> public virtual void IndentLine(TextDocument document, DocumentLine line) { if (document == null) throw new ArgumentNullException("document"); if (line == null) throw new ArgumentNullException("line"); DocumentLine previousLine = line.PreviousLine; if (previousLine != null) { ISegment indentationSegment = TextUtilities.GetWhitespaceAfter(document, previousLine.Offset); string indentation = document.GetText(indentationSegment); // copy indentation to line indentationSegment = TextUtilities.GetWhitespaceAfter(document, line.Offset); document.Replace(indentationSegment.Offset, indentationSegment.Length, indentation, OffsetChangeMappingType.RemoveAndInsert); // OffsetChangeMappingType.RemoveAndInsert guarantees the caret moves behind the new indentation. } }
public void BackwardChanges() { TextDocument document = new TextDocument("initial text"); ChangeTrackingCheckpoint checkpoint1, checkpoint2; ITextSource snapshot1 = document.CreateSnapshot(out checkpoint1); document.Replace(0, 7, "nw"); document.Insert(1, "e"); ITextSource snapshot2 = document.CreateSnapshot(out checkpoint2); Assert.AreEqual(1, checkpoint2.CompareAge(checkpoint1)); DocumentChangeEventArgs[] arr = checkpoint2.GetChangesTo(checkpoint1).ToArray(); Assert.AreEqual(2, arr.Length); Assert.AreEqual("", arr[0].InsertedText); Assert.AreEqual("initial", arr[1].InsertedText); Assert.AreEqual("initial text", snapshot1.Text); Assert.AreEqual("new text", snapshot2.Text); }
public void Undo() { OffsetChangeMap map = change.OffsetChangeMapOrNull; document.Replace(change.Offset, change.InsertionLength, change.RemovedText, map != null ? map.Invert() : null); }
void RenameReferencesInFile(SymbolRenameArgs args, IList<IFindReferenceSearchScope> searchScopeList, FileName fileName, Action<PatchedFile> callback, Action<Error> errorCallback, bool isNameValid, CancellationToken cancellationToken) { ITextSource textSource = args.ParseableFileContentFinder.Create(fileName); if (textSource == null) return; if (searchScopeList != null) { if (!searchScopeList.DistinctBy(scope => scope.SearchTerm ?? String.Empty).Any( scope => (scope.SearchTerm == null) || (textSource.IndexOf(scope.SearchTerm, 0, textSource.TextLength, StringComparison.Ordinal) >= 0))) return; } var parseInfo = SD.ParserService.Parse(fileName, textSource) as CSharpFullParseInformation; if (parseInfo == null) return; ReadOnlyDocument document = null; IHighlighter highlighter = null; List<RenameResultMatch> results = new List<RenameResultMatch>(); // Grab the unresolved file matching the compilation version // (this may differ from the version created by re-parsing the project) CSharpUnresolvedFile unresolvedFile = null; IProjectContent pc = compilation.MainAssembly.UnresolvedAssembly as IProjectContent; if (pc != null) { unresolvedFile = pc.GetFile(fileName) as CSharpUnresolvedFile; } CSharpAstResolver resolver = new CSharpAstResolver(compilation, parseInfo.SyntaxTree, unresolvedFile); fr.RenameReferencesInFile( searchScopeList, args.NewName, resolver, delegate (RenameCallbackArguments callbackArgs) { var node = callbackArgs.NodeToReplace; string newCode = callbackArgs.NewNode.ToString(); if (document == null) { document = new ReadOnlyDocument(textSource, fileName); if (args.ProvideHighlightedLine) { highlighter = SD.EditorControlService.CreateHighlighter(document); highlighter.BeginHighlighting(); } } var startLocation = node.StartLocation; var endLocation = node.EndLocation; int offset = document.GetOffset(startLocation); int length = document.GetOffset(endLocation) - offset; if (args.ProvideHighlightedLine) { var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter); var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null; results.Add(new RenameResultMatch(fileName, startLocation, endLocation, offset, length, newCode, builder, defaultTextColor)); } else { results.Add(new RenameResultMatch(fileName, startLocation, endLocation, offset, length, newCode)); } }, errorCallback, cancellationToken); if (highlighter != null) { highlighter.Dispose(); } if (results.Count > 0) { if (!isNameValid) { errorCallback(new Error(ErrorType.Error, string.Format("The name '{0}' is not valid in the current context!", args.NewName), new DomRegion(fileName, results[0].StartLocation))); return; } IDocument changedDocument = new TextDocument(document); var oldVersion = changedDocument.Version; List<SearchResultMatch> fixedResults = new List<SearchResultMatch>(); int lastStartOffset = changedDocument.TextLength + 1; foreach (var result in results.OrderByDescending(m => m.StartOffset)) { if (result.EndOffset <= lastStartOffset) { changedDocument.Replace(result.StartOffset, result.Length, result.NewCode); fixedResults.Add(result); lastStartOffset = result.StartOffset; } } callback(new PatchedFile(fileName, fixedResults, oldVersion, changedDocument.Version)); } }
public void InsertBold(int start, int length, TextDocument document) { var chs = document.GetCharAt(start); var che = document.GetCharAt(start + length - 1); document.Insert(start + length - 1, che.ToString()); document.Replace(start + length, 1, "]"); //trick to keep anchors document.Insert(start + 1, chs.ToString()); document.Replace(start, 1, "["); //trick to keep anchors Blocks.Add(new TextBlockBold() { OriginallyLength = length + 2, OriginallyOffset = start, MyAnchor = new AnchorSegment(document, start, length + 2) }); }
void RenameReferencesInFile(SymbolRenameArgs args, FileName fileName, Action<PatchedFile> callback, Action<Error> errorCallback, bool isNameValid, CancellationToken cancellationToken) { ITextSource textSource = args.ParseableFileContentFinder.Create(fileName); if (textSource == null) return; int offset = textSource.IndexOf(entity.Name, 0, textSource.TextLength, StringComparison.Ordinal); if (offset < 0) return; var parseInfo = SD.ParserService.Parse(fileName, textSource) as XamlFullParseInformation; if (parseInfo == null) return; ReadOnlyDocument document = null; IHighlighter highlighter = null; List<RenameResultMatch> results = new List<RenameResultMatch>(); XamlAstResolver resolver = new XamlAstResolver(compilation, parseInfo); string newCode = args.NewName; do { if (document == null) { document = new ReadOnlyDocument(textSource, fileName); highlighter = SD.EditorControlService.CreateHighlighter(document); highlighter.BeginHighlighting(); } var result = resolver.ResolveAtLocation(document.GetLocation(offset + entity.Name.Length / 2 + 1), cancellationToken); int length = entity.Name.Length; if ((result is TypeResolveResult && ((TypeResolveResult)result).Type.Equals(entity)) || (result is MemberResolveResult && ((MemberResolveResult)result).Member.Equals(entity))) { var region = new DomRegion(fileName, document.GetLocation(offset), document.GetLocation(offset + length)); var builder = SearchResultsPad.CreateInlineBuilder(region.Begin, region.End, document, highlighter); results.Add(new RenameResultMatch(fileName, document.GetLocation(offset), document.GetLocation(offset + length), offset, length, newCode, builder, highlighter.DefaultTextColor)); } offset = textSource.IndexOf(entity.Name, offset + length, textSource.TextLength - offset - length, StringComparison.OrdinalIgnoreCase); } while (offset > 0); if (highlighter != null) { highlighter.Dispose(); } if (results.Count > 0) { if (!isNameValid) { errorCallback(new Error(ErrorType.Error, string.Format("The name '{0}' is not valid in the current context!", args.NewName), new DomRegion(fileName, results[0].StartLocation))); return; } IDocument changedDocument = new TextDocument(document); var oldVersion = changedDocument.Version; foreach (var result in results.OrderByDescending(m => m.StartOffset)) { changedDocument.Replace(result.StartOffset, result.Length, result.NewCode); } callback(new PatchedFile(fileName, results, oldVersion, changedDocument.Version)); } }
void ReloadDocument(TextDocument document, string newContent) { var diff = new MyersDiffAlgorithm(new StringSequence(document.Text), new StringSequence(newContent)); document.Replace(0, document.TextLength, newContent, diff.GetEdits().ToOffsetChangeMap()); document.UndoStack.ClearAll(); }
void ReloadDocument(TextDocument document, string newContent) { var diff = new MyersDiffAlgorithm(new StringSequence(document.Text), new StringSequence(newContent)); document.Replace(0, document.TextLength, newContent, diff.GetEdits().ToOffsetChangeMap()); if (this.ClearUndoStackOnSwitch || documentFirstLoad) document.UndoStack.ClearAll(); if (documentFirstLoad) documentFirstLoad = false; }
public void Undo() { document.Replace(offset, insertedText.Length, removedText); }