Skip to content

Commit df907ec

Browse files
committed
Add Rename Disclaimer. Fully detailed disclaimer to come next
1 parent 8b3b660 commit df907ec

File tree

2 files changed

+70
-9
lines changed

2 files changed

+70
-9
lines changed

Diff for: package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,12 @@
10161016
"powershell.renameSymbol.createAlias": {
10171017
"type": "boolean",
10181018
"default": true,
1019-
"description": "Should an Alias be created when renaming a function parameter"
1019+
"description": "If set, an [Alias] attribute will be added when renaming a function parameter so that the previous parameter name still works. This helps avoid breaking changes."
1020+
},
1021+
"powershell.renameSymbol.acceptRenameDisclaimer": {
1022+
"type": "boolean",
1023+
"default": false,
1024+
"description": "Accepts the disclaimer about risks and limitations to the PowerShell rename functionality"
10201025
}
10211026
}
10221027
},

Diff for: src/features/RenameSymbol.ts

+64-8
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,22 @@ const PrepareRenameSymbolRequestType = new RequestType<IPrepareRenameSymbolReque
5353

5454
export class RenameSymbolFeature extends LanguageClientConsumer implements RenameProvider {
5555
private languageRenameProvider:vscode.Disposable;
56+
// Used to singleton the disclaimer prompt in case multiple renames are triggered
57+
private disclaimerPromise?: Promise<boolean>;
5658

5759
constructor(documentSelector:DocumentSelector,private logger: ILogger){
5860
super();
5961

6062
this.languageRenameProvider = vscode.languages.registerRenameProvider(documentSelector,this);
6163
}
64+
6265
// eslint-disable-next-line @typescript-eslint/no-empty-function
6366
public override onLanguageClientSet(_languageClient: LanguageClient): void {}
64-
public async provideRenameEdits(document: TextDocument, position: Position, newName: string, _token: CancellationToken): Promise<WorkspaceEdit | undefined> {
67+
68+
public async provideRenameEdits(document: TextDocument, position: Position, newName: string, _token: CancellationToken): Promise<WorkspaceEdit | undefined | null> {
69+
70+
const disclaimerAccepted = await this.acknowledgeDisclaimer();
71+
if (!disclaimerAccepted) {return undefined;}
6572

6673
const req:IRenameSymbolRequestArguments = {
6774
FileName : document.fileName,
@@ -84,22 +91,29 @@ export class RenameSymbolFeature extends LanguageClientConsumer implements Renam
8491

8592
const edit = new WorkspaceEdit();
8693
for (const file of response.changes) {
87-
8894
const uri = Uri.file(file.fileName);
89-
9095
for (const change of file.changes) {
91-
edit.replace(uri,
96+
edit.replace(
97+
uri,
9298
new Range(change.startLine, change.startColumn, change.endLine, change.endColumn),
93-
change.newText);
99+
change.newText
100+
);
94101
}
95102
}
96103
return edit;
97-
}catch (error) {
104+
} catch (error) {
98105
return undefined;
99106
}
100107
}
101-
public async prepareRename(document: vscode.TextDocument, position: vscode.Position, _token: vscode.CancellationToken): Promise<vscode.Range | {
102-
range: vscode.Range; placeholder: string;} | null> {
108+
109+
public async prepareRename(
110+
document: vscode.TextDocument,
111+
position: vscode.Position,
112+
_token: vscode.CancellationToken
113+
): Promise<vscode.Range | {range: vscode.Range; placeholder: string;} | undefined | null> {
114+
115+
const disclaimerAccepted = await this.acknowledgeDisclaimer();
116+
if (!disclaimerAccepted) {return undefined;}
103117

104118
const req:IRenameSymbolRequestArguments = {
105119
FileName : document.fileName,
@@ -134,7 +148,49 @@ export class RenameSymbolFeature extends LanguageClientConsumer implements Renam
134148
throw new Error(msg);
135149
}
136150
}
151+
152+
153+
/** Prompts the user to acknowledge the risks inherent with the rename provider and does not proceed until it is accepted */
154+
async acknowledgeDisclaimer(): Promise<boolean> {
155+
if (!this.disclaimerPromise) {
156+
this.disclaimerPromise = this.acknowledgeDisclaimerImpl();
157+
}
158+
return this.disclaimerPromise;
159+
}
160+
161+
/** This is a separate function so that it only runs once as a singleton and the promise only resolves once */
162+
async acknowledgeDisclaimerImpl(): Promise<boolean>
163+
{
164+
const config = vscode.workspace.getConfiguration();
165+
const acceptRenameDisclaimer = config.get<boolean>("powershell.renameSymbol.acceptRenameDisclaimer", false);
166+
167+
if (!acceptRenameDisclaimer) {
168+
const result = await vscode.window.showWarningMessage(
169+
//TODO: Provide a link to a markdown document that appears in the editor window, preferably one hosted with the extension itself.
170+
"The PowerShell Rename functionality has limitations. Do you accept the limitations and risks?",
171+
"Yes",
172+
"Workspace Only",
173+
"No"
174+
);
175+
176+
switch (result) {
177+
case "Yes":
178+
await config.update("powershell.renameSymbol.acceptRenameDisclaimer", true, vscode.ConfigurationTarget.Global);
179+
break;
180+
case "Workspace Only":
181+
await config.update("powershell.renameSymbol.acceptRenameDisclaimer", true, vscode.ConfigurationTarget.Workspace);
182+
break;
183+
default:
184+
void vscode.window.showInformationMessage("Rename operation cancelled and rename has been disabled until the extension is restarted.");
185+
break;
186+
}
187+
}
188+
189+
return config.get<boolean>("powershell.renameSymbol.acceptRenameDisclaimer", false);
190+
}
191+
137192
public dispose(): void {
138193
this.languageRenameProvider.dispose();
139194
}
195+
140196
}

0 commit comments

Comments
 (0)