public void FormatSpan(SnapshotSpan span) { // At this point, the $selection$ token has been replaced with the selected text and // declarations have been replaced with their default text. We need to format the // inserted snippet text while carefully handling $end$ position (where the caret goes // after Return is pressed). The IExpansionSession keeps a tracking point for this // position but we do the tracking ourselves to properly deal with virtual space. To // ensure the end location is correct, we take three extra steps: // 1. Insert an empty comment ("/**/" or "'") at the current $end$ position (prior // to formatting), and keep a tracking span for the comment. // 2. After formatting the new snippet text, find and delete the empty multiline // comment (via the tracking span) and notify the IExpansionSession of the new // $end$ location. If the line then contains only whitespace (due to the formatter // putting the empty comment on its own line), then delete the white space and // remember the indentation depth for that line. // 3. When the snippet is finally completed (via Return), and PositionCaretForEditing() // is called, check to see if the end location was on a line containing only white // space in the previous step. If so, and if that line is still empty, then position // the caret in virtual space. // This technique ensures that a snippet like "if($condition$) { $end$ }" will end up // as: // if ($condition$) // { // $end$ // } if (!TryGetSubjectBufferSpan(span, out var snippetSpan)) { return; } Contract.ThrowIfNull(ExpansionSession); // Insert empty comment and track end position var snippetTrackingSpan = snippetSpan.CreateTrackingSpan(SpanTrackingMode.EdgeInclusive); var fullSnippetSpan = ExpansionSession.GetSnippetSpan(); var isFullSnippetFormat = fullSnippetSpan == span; var endPositionTrackingSpan = isFullSnippetFormat ? InsertEmptyCommentAndGetEndPositionTrackingSpan() : null; var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(SubjectBuffer.CurrentSnapshot, snippetTrackingSpan.GetSpan(SubjectBuffer.CurrentSnapshot)); SubjectBuffer.FormatAndApplyToBuffer(formattingSpan, EditorOptionsService, CancellationToken.None); if (isFullSnippetFormat) { CleanUpEndLocation(endPositionTrackingSpan); SetNewEndPosition(endPositionTrackingSpan); } }