@@ -53,15 +53,22 @@ const PrepareRenameSymbolRequestType = new RequestType<IPrepareRenameSymbolReque
5353
5454export 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