private string GetSourceWithOffsetRegistrationStatements() { var parseData = CodeEditor.Document.ParseData as IDotNetParseData; var statementOffsets = new List <int>(); VisitNodesAndSelectStatementOffsets(parseData.Ast, statementOffsets); var inserts = statementOffsets.ToDictionary(o => o, o => String.Format("____TrackStatementOffset({0});", o)); var documentWithOffsets = new EditorDocument(); documentWithOffsets.SetText(parseData.Snapshot.Text); var options = new TextChangeOptions { OffsetDelta = TextChangeOffsetDelta.SequentialOnly }; var change = documentWithOffsets.CreateTextChange(TextChangeTypes.Custom, options); foreach (var insert in inserts) { change.InsertText(insert.Key, insert.Value); } change.Apply(); return(documentWithOffsets.Text); }
protected override void Invoke(ICodeAction action) { var snapshot = _document.CurrentSnapshot; var oldText = snapshot.ToSourceText(); var syntaxTree = action.GetEdit(); var newText = syntaxTree.Text; var changes = newText.GetChanges(oldText); var textChangeOptions = new TextChangeOptions(); textChangeOptions.RetainSelection = true; var textChange = _document.CreateTextChange(TextChangeTypes.Custom, textChangeOptions); var currentText = oldText; foreach (var change in changes) { var range = currentText.ToRange(change.Span); textChange.ReplaceText(range, change.NewText); currentText = currentText.WithChanges(change); } textChange.Apply(); }
///////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Applies text formatting to part or all of a snapshot. /// </summary> /// <param name="snapshot">The target <see cref="ITextSnapshot"/>.</param> /// <param name="selectionPositionRanges"> /// The <see cref="ITextPositionRangeCollection"/> indicating the selection position ranges. /// These are used to translate the current selection to the new snapshot that is created, even when formatting the entire snapshot. /// </param> /// <param name="mode">A <see cref="TextFormatMode"/> indicating whether to format part or all of the snapshot. The default value is <c>Ranges</c>.</param> /// <remarks> /// The containing <see cref="ITextDocument"/> is accessible via the <see cref="ITextSnapshot"/>. /// </remarks> public void Format(ITextSnapshot snapshot, ITextPositionRangeCollection selectionPositionRanges, TextFormatMode mode = TextFormatMode.Ranges) { if (snapshot == null) { throw new ArgumentNullException("snapshot"); } if ((selectionPositionRanges == null) || (selectionPositionRanges.Count == 0)) { throw new ArgumentNullException("selectionPositionRanges"); } // Changes must occur sequentially so that we can use unmodified offsets while looping over the document var options = new TextChangeOptions(); options.OffsetDelta = TextChangeOffsetDelta.SequentialOnly; options.RetainSelection = true; var change = snapshot.Document.CreateTextChange(TextChangeTypes.AutoFormat, options); // Get the snapshot ranges to format var snapshotRanges = (mode == TextFormatMode.All ? new TextSnapshotRange[] { snapshot.SnapshotRange } : selectionPositionRanges.Select(pr => new TextSnapshotRange(snapshot, snapshot.PositionRangeToTextRange(pr))).ToArray() ); // Loop through the snapshot ranges foreach (var snapshotRange in snapshotRanges) { this.FormatCore(change, snapshotRange); } // Apply the changes if (change.Operations.Count > 0) { change.Apply(); } }
private string GetSourceWithOffsetRegistrationStatements() { var parseData = CodeEditor.Document.ParseData as IDotNetParseData; var statementOffsets = new List<int>(); VisitNodesAndSelectStatementOffsets(parseData.Ast, statementOffsets); var inserts = statementOffsets.ToDictionary(o => o, o => String.Format("____TrackStatementOffset({0});", o)); var documentWithOffsets = new EditorDocument(); documentWithOffsets.SetText(parseData.Snapshot.Text); var options = new TextChangeOptions { OffsetDelta = TextChangeOffsetDelta.SequentialOnly }; var change = documentWithOffsets.CreateTextChange(TextChangeTypes.Custom, options); foreach (var insert in inserts) { change.InsertText(insert.Key, insert.Value); } change.Apply(); return documentWithOffsets.Text; }
/// <summary> /// Formats the specified snapshot range. /// </summary> /// <param name="snapshotRange"> The snapshot range. </param> public void Format(TextSnapshotRange snapshotRange) { // Get the snapshot var snapshot = snapshotRange.Snapshot; if (snapshot == null) { return; } // Get the snapshot reader var reader = snapshot.GetReader(snapshotRange.StartOffset); // Get the code document var document = snapshot.Document as ICodeDocument; if (document == null) { return; } // Get the tab size var tabSize = document.TabSize; // Create a text change object for the document var options = new TextChangeOptions(); // Changes must occur sequentially so that we can use unmodified offsets while looping over the document options.OffsetDelta = TextChangeOffsetDelta.SequentialOnly; options.RetainSelection = true; var change = document.CreateTextChange(TextChangeTypes.AutoFormat, options); // Keep track of the last non whitespace token Id var lastNonWhitespaceTokenId = -1; // Keep track of the indent level var indentLevel = 0; // Loop through the document while ((reader.Token != null) && (reader.Offset < snapshotRange.EndOffset)) { // If the token is whitespace, delete the text if (reader.Token.Id == JsonTokenId.Whitespace) { change.DeleteText(reader.Token.TextRange); } else { // The token is not whitespace // Create a variable that will contain the text to be inserted var insertText = ""; // Determine the insertText value based on the previous non-whitespace token and the current token switch (lastNonWhitespaceTokenId) { case JsonTokenId.OpenCurlyBrace: case JsonTokenId.OpenSquareBrace: { if (reader.Token.Id != JsonTokenId.CloseCurlyBrace && reader.Token.Id != JsonTokenId.CloseSquareBrace) { indentLevel++; } insertText = Environment.NewLine + StringHelper.GetIndentText(document.AutoConvertTabsToSpaces, tabSize, indentLevel * tabSize); break; } case JsonTokenId.Colon: { insertText = " "; break; } case JsonTokenId.Comma: { if (reader.Token.Id == JsonTokenId.CloseCurlyBrace || reader.Token.Id == JsonTokenId.CloseSquareBrace) { indentLevel = Math.Max(0, indentLevel - 1); } insertText = Environment.NewLine + StringHelper.GetIndentText(document.AutoConvertTabsToSpaces, tabSize, indentLevel * tabSize); break; } case JsonTokenId.CloseCurlyBrace: case JsonTokenId.CloseSquareBrace: case JsonTokenId.False: case JsonTokenId.True: case JsonTokenId.Number: case JsonTokenId.StringEndDelimiter: case JsonTokenId.Null: { if (reader.Token.Id == JsonTokenId.CloseCurlyBrace || reader.Token.Id == JsonTokenId.CloseSquareBrace) { indentLevel = Math.Max(0, indentLevel - 1); insertText = Environment.NewLine + StringHelper.GetIndentText(document.AutoConvertTabsToSpaces, tabSize, indentLevel * tabSize); } } break; } // Insert the replacement text change.InsertText(reader.Token.StartOffset, insertText); // Update the last non-whitespace token Id lastNonWhitespaceTokenId = reader.Token.Id; } // Go to the next token reader.GoToNextToken(); } // If the entire document was formatted, add a newline to the end if ((snapshot.SnapshotRange.StartOffset == snapshotRange.StartOffset) && (snapshot.SnapshotRange.EndOffset == snapshotRange.EndOffset)) { change.InsertText(snapshotRange.EndOffset, "\n"); } // Apply the changes change.Apply(); }
/// <summary> /// Formats the specified snapshot range. /// </summary> /// <param name="snapshotRange"> The snapshot range. </param> public void Format(TextSnapshotRange snapshotRange) { // Get the snapshot var snapshot = snapshotRange.Snapshot; if (snapshot == null) return; // Get the snapshot reader var reader = snapshot.GetReader(snapshotRange.StartOffset); // Get the code document var document = snapshot.Document as ICodeDocument; if (document == null) return; // Get the tab size var tabSize = document.TabSize; // Create a text change object for the document var options = new TextChangeOptions(); // Changes must occur sequentially so that we can use unmodified offsets while looping over the document options.OffsetDelta = TextChangeOffsetDelta.SequentialOnly; options.RetainSelection = true; var change = document.CreateTextChange(TextChangeTypes.AutoFormat, options); // Keep track of the last non whitespace token Id var lastNonWhitespaceTokenId = -1; // Keep track of the indent level var indentLevel = 0; // Loop through the document while ((reader.Token != null) && (reader.Offset < snapshotRange.EndOffset)) { // If the token is whitespace, delete the text if (reader.Token.Id == JsonTokenId.Whitespace) { change.DeleteText(reader.Token.TextRange); } else { // The token is not whitespace // Create a variable that will contain the text to be inserted var insertText = ""; // Determine the insertText value based on the previous non-whitespace token and the current token switch (lastNonWhitespaceTokenId) { case JsonTokenId.OpenCurlyBrace: case JsonTokenId.OpenSquareBrace: { if (reader.Token.Id != JsonTokenId.CloseCurlyBrace && reader.Token.Id != JsonTokenId.CloseSquareBrace) { indentLevel++; } insertText = Environment.NewLine + StringHelper.GetIndentText(document.AutoConvertTabsToSpaces, tabSize, indentLevel * tabSize); break; } case JsonTokenId.Colon : { insertText = " "; break; } case JsonTokenId.Comma : { if (reader.Token.Id == JsonTokenId.CloseCurlyBrace || reader.Token.Id == JsonTokenId.CloseSquareBrace) { indentLevel = Math.Max(0, indentLevel - 1); } insertText = Environment.NewLine + StringHelper.GetIndentText(document.AutoConvertTabsToSpaces, tabSize, indentLevel * tabSize); break; } case JsonTokenId.CloseCurlyBrace: case JsonTokenId.CloseSquareBrace: case JsonTokenId.False: case JsonTokenId.True: case JsonTokenId.Number: case JsonTokenId.StringEndDelimiter: case JsonTokenId.Null: { if (reader.Token.Id == JsonTokenId.CloseCurlyBrace || reader.Token.Id == JsonTokenId.CloseSquareBrace) { indentLevel = Math.Max(0, indentLevel - 1); insertText = Environment.NewLine + StringHelper.GetIndentText(document.AutoConvertTabsToSpaces, tabSize, indentLevel*tabSize); } } break; } // Insert the replacement text change.InsertText(reader.Token.StartOffset, insertText); // Update the last non-whitespace token Id lastNonWhitespaceTokenId = reader.Token.Id; } // Go to the next token reader.GoToNextToken(); } // If the entire document was formatted, add a newline to the end if ((snapshot.SnapshotRange.StartOffset == snapshotRange.StartOffset) && (snapshot.SnapshotRange.EndOffset == snapshotRange.EndOffset)) change.InsertText(snapshotRange.EndOffset, "\n"); // Apply the changes change.Apply(); }