-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathrenameProvider.ts
88 lines (78 loc) · 4.68 KB
/
renameProvider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { Position, RequestType, ResponseError } from 'vscode-languageclient';
import * as nls from 'vscode-nls';
import * as util from '../../common';
import { DefaultClient, workspaceReferences } from '../client';
import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { CancellationSender, ReferenceType, ReferencesParams, ReferencesResult, getReferenceItemIconPath, getReferenceTagString } from '../references';
import { CppSettings } from '../settings';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
const RenameRequest: RequestType<ReferencesParams, ReferencesResult, void> =
new RequestType<ReferencesParams, ReferencesResult, void>('cpptools/rename');
export class RenameProvider implements vscode.RenameProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
public async provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string, _token: vscode.CancellationToken): Promise<vscode.WorkspaceEdit | undefined> {
await this.client.ready;
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
const settings: CppSettings = new CppSettings();
if (settings.renameRequiresIdentifier && !util.isValidIdentifier(newName)) {
void vscode.window.showErrorMessage(localize("invalid.identifier.for.rename", "Invalid identifier provided for the Rename Symbol operation."));
return undefined;
}
// Listen to a cancellation for this request. When this request is cancelled,
// use a local cancellation source to explicitly cancel a token.
// Don't listen to the token from the provider, as it will cancel when the cursor is moved to a different position.
const cancelSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(_sender => { cancelSource.cancel(); });
// Send the request to the language server.
workspaceReferences.startRename();
const workspaceEditResult: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
const params: ReferencesParams = {
newName: newName,
position: Position.create(position.line, position.character),
textDocument: { uri: document.uri.toString() }
};
let response: ReferencesResult;
try {
response = await this.client.languageClient.sendRequest(RenameRequest, params, cancelSource.token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
throw new vscode.CancellationError();
}
throw e;
}
finally {
// Reset anything that can be cleared before processing the result.
workspaceReferences.resetProgressBar();
workspaceReferences.resetReferences();
requestCanceledListener.dispose();
}
// Process the result.
if (cancelSource.token.isCancellationRequested || response.isCanceled) {
throw new vscode.CancellationError();
} else if (response.referenceInfos.length === 0) {
void vscode.window.showErrorMessage(localize("unable.to.locate.selected.symbol", "A definition for the selected symbol could not be located."));
} else {
for (const reference of response.referenceInfos) {
const uri: vscode.Uri = vscode.Uri.file(reference.file);
const range: vscode.Range = new vscode.Range(reference.position.line, reference.position.character,
reference.position.line, reference.position.character + response.text.length);
const metadata: vscode.WorkspaceEditEntryMetadata = {
needsConfirmation: reference.type !== ReferenceType.Confirmed,
label: getReferenceTagString(reference.type, false, true),
iconPath: getReferenceItemIconPath(reference.type, false)
};
workspaceEditResult.replace(uri, range, newName, metadata);
}
}
return workspaceEditResult;
}
}