@@ -53,15 +53,22 @@ const PrepareRenameSymbolRequestType = new RequestType<IPrepareRenameSymbolReque
53
53
54
54
export class RenameSymbolFeature extends LanguageClientConsumer implements RenameProvider {
55
55
private languageRenameProvider :vscode . Disposable ;
56
+ // Used to singleton the disclaimer prompt in case multiple renames are triggered
57
+ private disclaimerPromise ?: Promise < boolean > ;
56
58
57
59
constructor ( documentSelector :DocumentSelector , private logger : ILogger ) {
58
60
super ( ) ;
59
61
60
62
this . languageRenameProvider = vscode . languages . registerRenameProvider ( documentSelector , this ) ;
61
63
}
64
+
62
65
// eslint-disable-next-line @typescript-eslint/no-empty-function
63
66
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 ; }
65
72
66
73
const req :IRenameSymbolRequestArguments = {
67
74
FileName : document . fileName ,
@@ -84,22 +91,29 @@ export class RenameSymbolFeature extends LanguageClientConsumer implements Renam
84
91
85
92
const edit = new WorkspaceEdit ( ) ;
86
93
for ( const file of response . changes ) {
87
-
88
94
const uri = Uri . file ( file . fileName ) ;
89
-
90
95
for ( const change of file . changes ) {
91
- edit . replace ( uri ,
96
+ edit . replace (
97
+ uri ,
92
98
new Range ( change . startLine , change . startColumn , change . endLine , change . endColumn ) ,
93
- change . newText ) ;
99
+ change . newText
100
+ ) ;
94
101
}
95
102
}
96
103
return edit ;
97
- } catch ( error ) {
104
+ } catch ( error ) {
98
105
return undefined ;
99
106
}
100
107
}
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 ; }
103
117
104
118
const req :IRenameSymbolRequestArguments = {
105
119
FileName : document . fileName ,
@@ -134,7 +148,49 @@ export class RenameSymbolFeature extends LanguageClientConsumer implements Renam
134
148
throw new Error ( msg ) ;
135
149
}
136
150
}
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
+
137
192
public dispose ( ) : void {
138
193
this . languageRenameProvider . dispose ( ) ;
139
194
}
195
+
140
196
}
0 commit comments