Skip to content

Commit 08f435e

Browse files
committed
Improve completionComplexEdit command
1 parent d07dd86 commit 08f435e

File tree

1 file changed

+55
-58
lines changed

1 file changed

+55
-58
lines changed

src/lsptoolshost/commands.ts

Lines changed: 55 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -103,73 +103,70 @@ async function completionComplexEdit(
103103
newOffset: number,
104104
outputChannel: vscode.OutputChannel
105105
): Promise<void> {
106-
let success = false;
107-
const uri = UriConverter.deserialize(uriStr);
108-
const editor = vscode.window.visibleTextEditors.find(
109-
(editor) => editor.document.uri.path === uri.path || editor.document.uri.fsPath === uri.fsPath
110-
);
111-
112-
if (editor !== undefined) {
113-
const newRange = editor.document.validateRange(
114-
new vscode.Range(
115-
textEdit.range.start.line,
116-
textEdit.range.start.character,
117-
textEdit.range.end.line,
118-
textEdit.range.end.character
119-
)
120-
);
106+
const componentName = '[roslyn.client.completionComplexEdit]';
121107

122-
// HACK:
123-
// ApplyEdit would fail the first time it's called when an item was committed with text modifying commit char (e.g. space, '(', etc.)
124-
// so we retry a couple time here as a tempory workaround. We need to either figure our the reason of the failure, and/or try the
125-
// approach of sending another edit request to server with updated document.
126-
for (let i = 0; i < 3; i++) {
127-
if (isSnippetString) {
128-
editor.selection = new vscode.Selection(newRange.start, newRange.end);
129-
success = await editor.insertSnippet(new vscode.SnippetString(textEdit.newText));
130-
} else {
131-
const edit = new vscode.WorkspaceEdit();
132-
const newTextEdit = vscode.TextEdit.replace(newRange, textEdit.newText);
133-
edit.set(editor.document.uri, [newTextEdit]);
134-
success = await vscode.workspace.applyEdit(edit);
135-
136-
if (success && newOffset >= 0) {
137-
const newPosition = editor.document.positionAt(newOffset);
138-
editor.selections = [new vscode.Selection(newPosition, newPosition)];
139-
}
140-
}
108+
// Find TextDocument, opening if needed.
109+
const document = await vscode.workspace.openTextDocument(uriStr);
110+
if (document === undefined) {
111+
outputAndThrow(outputChannel, `${componentName} Can't open document with path: '${uriStr}'`);
112+
}
141113

142-
if (success) {
143-
break;
144-
}
114+
// Use editor if we need to deal with selection or snippets.
115+
let editor: vscode.TextEditor | undefined = undefined;
116+
if (isSnippetString || newOffset >= 0) {
117+
editor = await vscode.window.showTextDocument(document);
118+
if (editor == undefined) {
119+
outputAndThrow(outputChannel, `${componentName} Editor unavailable for document with path: '${uriStr}'`);
145120
}
146121
}
147122

148-
if (!success) {
149-
const componentName = '[roslyn.client.completionComplexEdit]';
150-
const errorMessage = 'Failed to make a complex text edit for completion.';
151-
outputChannel.show();
152-
outputChannel.appendLine(`${componentName} ${errorMessage}`);
153-
154-
if (editor === undefined) {
155-
outputChannel.appendLine(
156-
`${componentName} Can't find visible document with uri.fsPath: '${uri.fsPath}' and uri.path: '${uri.path}'`
157-
);
158-
159-
outputChannel.appendLine(`${componentName} URIs of all visible documents:`);
160-
for (const visibleEditor of vscode.window.visibleTextEditors) {
161-
outputChannel.appendLine(
162-
`${componentName} - uri.fsPath: '${visibleEditor.document.uri.fsPath}' and uri.path: '${visibleEditor.document.uri.path}'`
163-
);
164-
}
123+
const newRange = document.validateRange(
124+
new vscode.Range(
125+
textEdit.range.start.line,
126+
textEdit.range.start.character,
127+
textEdit.range.end.line,
128+
textEdit.range.end.character
129+
)
130+
);
131+
132+
// HACK:
133+
// ApplyEdit would fail the first time it's called when an item was committed with text modifying commit char (e.g. space, '(', etc.)
134+
// so we retry a couple time here as a tempory workaround. We need to either figure our the reason of the failure, and/or try the
135+
// approach of sending another edit request to server with updated document.
136+
let success = false;
137+
for (let i = 0; i < 3; i++) {
138+
if (isSnippetString) {
139+
editor!.selection = new vscode.Selection(newRange.start, newRange.end);
140+
success = await editor!.insertSnippet(new vscode.SnippetString(textEdit.newText));
165141
} else {
166-
outputChannel.appendLine(
167-
`${componentName} ${isSnippetString ? 'TextEditor.insertSnippet' : 'workspace.applyEdit'} failed.`
168-
);
142+
const edit = new vscode.WorkspaceEdit();
143+
const newTextEdit = vscode.TextEdit.replace(newRange, textEdit.newText);
144+
edit.set(document.uri, [newTextEdit]);
145+
success = await vscode.workspace.applyEdit(edit);
146+
147+
if (success && newOffset >= 0) {
148+
const newPosition = document.positionAt(newOffset);
149+
editor!.selections = [new vscode.Selection(newPosition, newPosition)];
150+
}
169151
}
170152

171-
throw new Error(`${componentName} ${errorMessage}`);
153+
if (success) {
154+
return;
155+
}
172156
}
157+
158+
if (!success) {
159+
outputAndThrow(
160+
outputChannel,
161+
`${componentName} ${isSnippetString ? 'TextEditor.insertSnippet' : 'workspace.applyEdit'} failed.`
162+
);
163+
}
164+
}
165+
166+
function outputAndThrow(outputChannel: vscode.OutputChannel, message: string): void {
167+
outputChannel.show();
168+
outputChannel.appendLine(message);
169+
throw new Error(message);
173170
}
174171

175172
async function openSolution(languageServer: RoslynLanguageServer): Promise<vscode.Uri | undefined> {

0 commit comments

Comments
 (0)