@@ -11,7 +11,10 @@ import { STANDARD_OUTPUT_CHANNEL } from '../constants';
11
11
import { IPlatformService } from '../platform/types' ;
12
12
import { IProcessServiceFactory , IPythonExecutionFactory } from '../process/types' ;
13
13
import { ITerminalServiceFactory } from '../terminal/types' ;
14
- import { IConfigurationService , IInstaller , ILogger , InstallerResponse , IOutputChannel , ModuleNamePurpose , Product , ProductType } from '../types' ;
14
+ import {
15
+ IConfigurationService , IInstaller , ILogger , InstallerResponse , IOutputChannel ,
16
+ IPersistentStateFactory , ModuleNamePurpose , Product , ProductType
17
+ } from '../types' ;
15
18
import { ProductNames } from './productNames' ;
16
19
import { IInstallationChannelManager , IProductPathService , IProductService } from './types' ;
17
20
@@ -88,6 +91,7 @@ export abstract class BaseInstaller {
88
91
. catch ( ( ) => false ) ;
89
92
}
90
93
}
94
+
91
95
protected abstract promptToInstallImplementation ( product : Product , resource ?: Uri ) : Promise < InstallerResponse > ;
92
96
protected getExecutableNameFromSettings ( product : Product , resource ?: Uri ) : string {
93
97
const productType = this . productService . getProductType ( product ) ;
@@ -168,12 +172,21 @@ export class FormatterInstaller extends BaseInstaller {
168
172
169
173
export class LinterInstaller extends BaseInstaller {
170
174
protected async promptToInstallImplementation ( product : Product , resource ?: Uri ) : Promise < InstallerResponse > {
175
+ const isPylint = product === Product . pylint ;
176
+
171
177
const productName = ProductNames . get ( product ) ! ;
172
178
const install = 'Install' ;
173
179
const disableAllLinting = 'Disable linting' ;
174
180
const disableThisLinter = `Disable ${ productName } ` ;
181
+ const disableInstallPrompt = 'Do not show again' ;
182
+ const disableLinterInstallPromptKey = `${ productName } _DisableLinterInstallPrompt` ;
183
+
184
+ if ( isPylint && this . getStoredResponse ( disableLinterInstallPromptKey ) === true ) {
185
+ return InstallerResponse . Ignore ;
186
+ }
187
+
188
+ const options = isPylint ? [ disableThisLinter , disableAllLinting , disableInstallPrompt ] : [ disableThisLinter , disableAllLinting ] ;
175
189
176
- const options = [ disableThisLinter , disableAllLinting ] ;
177
190
let message = `Linter ${ productName } is not installed.` ;
178
191
if ( this . isExecutableAModule ( product , resource ) ) {
179
192
options . splice ( 0 , 0 , install ) ;
@@ -185,7 +198,11 @@ export class LinterInstaller extends BaseInstaller {
185
198
const response = await this . appShell . showErrorMessage ( message , ...options ) ;
186
199
if ( response === install ) {
187
200
return this . install ( product , resource ) ;
201
+ } else if ( response === disableInstallPrompt ) {
202
+ await this . setStoredResponse ( disableLinterInstallPromptKey , true ) ;
203
+ return InstallerResponse . Ignore ;
188
204
}
205
+
189
206
const lm = this . serviceContainer . get < ILinterManager > ( ILinterManager ) ;
190
207
if ( response === disableAllLinting ) {
191
208
await lm . enableLintingAsync ( false ) ;
@@ -196,6 +213,37 @@ export class LinterInstaller extends BaseInstaller {
196
213
}
197
214
return InstallerResponse . Ignore ;
198
215
}
216
+
217
+ /**
218
+ * For installers that want to avoid prompting the user over and over, they can make use of a
219
+ * persisted true/false value representing user responses to 'stop showing this prompt'. This method
220
+ * gets the persisted value given the installer-defined key.
221
+ *
222
+ * @param key Key to use to get a persisted response value, each installer must define this for themselves.
223
+ * @returns Boolean: The current state of the stored response key given.
224
+ */
225
+ private getStoredResponse ( key : string ) : boolean {
226
+ const factory = this . serviceContainer . get < IPersistentStateFactory > ( IPersistentStateFactory ) ;
227
+ const state = factory . createGlobalPersistentState < boolean | undefined > ( key , undefined ) ;
228
+ return state . value ;
229
+ }
230
+
231
+ /**
232
+ * For installers that want to avoid prompting the user over and over, they can make use of a
233
+ * persisted true/false value representing user responses to 'stop showing this prompt'. This
234
+ * method will set that persisted value given the installer-defined key.
235
+ *
236
+ * @param key Key to use to get a persisted response value, each installer must define this for themselves.
237
+ * @param value Boolean value to store for the user - if they choose to not be prompted again for instance.
238
+ * @returns Boolean: The current state of the stored response key given.
239
+ */
240
+ private async setStoredResponse ( key : string , value : boolean ) : Promise < void > {
241
+ const factory = this . serviceContainer . get < IPersistentStateFactory > ( IPersistentStateFactory ) ;
242
+ const state = factory . createGlobalPersistentState < boolean | undefined > ( key , undefined ) ;
243
+ if ( state && state . value !== value ) {
244
+ await state . updateValue ( value ) ;
245
+ }
246
+ }
199
247
}
200
248
201
249
export class TestFrameworkInstaller extends BaseInstaller {
0 commit comments