Skip to content

Commit c679056

Browse files
authored
Merge pull request #6814 from etvorun/dev/evgenyt/improve_complex_edit
Improve completionComplexEdit command
2 parents 4be5393 + d1c6aa0 commit c679056

File tree

1 file changed

+54
-57
lines changed

1 file changed

+54
-57
lines changed

src/lsptoolshost/commands.ts

Lines changed: 54 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -103,75 +103,72 @@ 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}`);
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+
);
153131

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-
}
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+
}
151+
}
152+
153+
if (success) {
154+
return;
169155
}
156+
}
170157

171-
throw new Error(`${componentName} ${errorMessage}`);
158+
if (!success) {
159+
outputAndThrow(
160+
outputChannel,
161+
`${componentName} ${isSnippetString ? 'TextEditor.insertSnippet' : 'workspace.applyEdit'} failed.`
162+
);
172163
}
173164
}
174165

166+
function outputAndThrow(outputChannel: vscode.OutputChannel, message: string): void {
167+
outputChannel.show();
168+
outputChannel.appendLine(message);
169+
throw new Error(message);
170+
}
171+
175172
async function openSolution(languageServer: RoslynLanguageServer): Promise<vscode.Uri | undefined> {
176173
if (!vscode.workspace.workspaceFolders) {
177174
return undefined;

0 commit comments

Comments
 (0)