|
5 | 5 |
|
6 | 6 | import * as vscode from 'vscode'; |
7 | 7 |
|
8 | | -import { FormattingOptions, LanguageClient, TextDocumentIdentifier } from 'vscode-languageclient/node'; |
| 8 | +import { |
| 9 | + FormattingOptions, |
| 10 | + InsertTextFormat, |
| 11 | + LanguageClient, |
| 12 | + TextDocumentIdentifier, |
| 13 | +} from 'vscode-languageclient/node'; |
9 | 14 | import * as RoslynProtocol from '../server/roslynProtocol'; |
10 | 15 | import { RoslynLanguageServer } from '../server/roslynLanguageServer'; |
11 | 16 |
|
@@ -50,7 +55,21 @@ export function registerOnAutoInsert(languageServer: RoslynLanguageServer, langu |
50 | 55 | } |
51 | 56 |
|
52 | 57 | // Regular expression to match all whitespace characters except the newline character |
53 | | - const changeTrimmed = change.text.replace(/[^\S\n]+/g, ''); |
| 58 | + let changeTrimmed = change.text.replace(/[^\S\n]+/g, ''); |
| 59 | + |
| 60 | + // If the change is empty after removing whitespace, we don't need to process it. |
| 61 | + if (changeTrimmed.length === 0) { |
| 62 | + return; |
| 63 | + } |
| 64 | + |
| 65 | + // When hitting enter between braces, we can end up with two new lines added (one to move the cursor down to an empty line, |
| 66 | + // and another to move the close brace to a new line below that). We want to detect that edit as a single new line trigger. |
| 67 | + // |
| 68 | + // Since we already removed all whitespace except new lines above, we can just trim the string to remove new lines as well |
| 69 | + // and check if there is anything left. If not, we know the change is just whitespace and new lines and can set the trigger to the new line character. |
| 70 | + if (changeTrimmed.trim() === '') { |
| 71 | + changeTrimmed = '\n'; |
| 72 | + } |
54 | 73 |
|
55 | 74 | if (!vsTriggerCharacters.includes(changeTrimmed)) { |
56 | 75 | return; |
@@ -98,12 +117,20 @@ async function applyAutoInsertEdit( |
98 | 117 | const textEdit = response._vs_textEdit; |
99 | 118 | const startPosition = new vscode.Position(textEdit.range.start.line, textEdit.range.start.character); |
100 | 119 | const endPosition = new vscode.Position(textEdit.range.end.line, textEdit.range.end.character); |
101 | | - const docComment = new vscode.SnippetString(textEdit.newText); |
102 | | - const code: any = vscode; |
103 | | - const textEdits = [new code.SnippetTextEdit(new vscode.Range(startPosition, endPosition), docComment)]; |
| 120 | + |
| 121 | + let textEdits: (vscode.TextEdit | vscode.SnippetTextEdit)[] = []; |
| 122 | + if (response._vs_textEditFormat === InsertTextFormat.Snippet) { |
| 123 | + const docComment = new vscode.SnippetString(textEdit.newText); |
| 124 | + const edit = vscode.SnippetTextEdit.replace(new vscode.Range(startPosition, endPosition), docComment); |
| 125 | + // Roslyn already formats the snippet correctly - we don't want the client to try and change the whitespace. |
| 126 | + edit.keepWhitespace = true; |
| 127 | + textEdits = [edit]; |
| 128 | + } else { |
| 129 | + textEdits = [vscode.TextEdit.replace(new vscode.Range(startPosition, endPosition), textEdit.newText)]; |
| 130 | + } |
| 131 | + |
104 | 132 | const edit = new vscode.WorkspaceEdit(); |
105 | 133 | edit.set(uri, textEdits); |
106 | | - |
107 | 134 | const applied = vscode.workspace.applyEdit(edit); |
108 | 135 | if (!applied) { |
109 | 136 | throw new Error('Tried to apply an edit but an error occurred.'); |
|
0 commit comments