@@ -6,7 +6,7 @@ import { inject, injectable } from 'inversify';
66import { DiagnosticSeverity , l10n } from 'vscode' ;
77import '../../../common/extensions' ;
88import * as path from 'path' ;
9- import { IDisposableRegistry , IInterpreterPathService , Resource } from '../../../common/types' ;
9+ import { IConfigurationService , IDisposableRegistry , IInterpreterPathService , Resource } from '../../../common/types' ;
1010import { IInterpreterService } from '../../../interpreter/contracts' ;
1111import { IServiceContainer } from '../../../ioc/types' ;
1212import { BaseDiagnostic , BaseDiagnosticsService } from '../base' ;
@@ -28,10 +28,11 @@ import { EventName } from '../../../telemetry/constants';
2828import { IExtensionSingleActivationService } from '../../../activation/types' ;
2929import { cache } from '../../../common/utils/decorators' ;
3030import { noop } from '../../../common/utils/misc' ;
31- import { IPythonExecutionFactory } from '../../../common/process/types' ;
3231import { getOSType , OSType } from '../../../common/utils/platform' ;
3332import { IFileSystem } from '../../../common/platform/types' ;
3433import { traceError } from '../../../logging' ;
34+ import { getExecutable } from '../../../common/process/internal/python' ;
35+ import { shellExec } from '../../../common/process/rawProcessApis' ;
3536
3637const messages = {
3738 [ DiagnosticCodes . NoPythonInterpretersDiagnostic ] : l10n . t (
@@ -41,7 +42,7 @@ const messages = {
4142 'An Invalid Python interpreter is selected{0}, please try changing it to enable features such as IntelliSense, linting, and debugging. See output for more details regarding why the interpreter is invalid.' ,
4243 ) ,
4344 [ DiagnosticCodes . InvalidComspecDiagnostic ] : l10n . t (
44- "The environment variable 'Comspec' seems to be set to an invalid value. Please correct it to carry valid path to Command Prompt to enable features such as IntelliSense, linting, and debugging. See instructions which might help." ,
45+ 'We detected an issue with one of your environment variables that breaks features such as IntelliSense, linting and debugging. Try setting the "ComSpec" to a valid Command Prompt path in your system to fix it.' ,
4546 ) ,
4647} ;
4748
@@ -112,20 +113,16 @@ export class InvalidPythonInterpreterService extends BaseDiagnosticsService
112113 ) ;
113114 }
114115
115- // eslint-disable-next-line class-methods-use-this
116- public async diagnose ( _resource : Resource ) : Promise < IDiagnostic [ ] > {
117- return [ ] ;
116+ public async diagnose ( resource : Resource ) : Promise < IDiagnostic [ ] > {
117+ return this . diagnoseDefaultShell ( resource ) ;
118118 }
119119
120120 public async _manualDiagnose ( resource : Resource ) : Promise < IDiagnostic [ ] > {
121121 const workspaceService = this . serviceContainer . get < IWorkspaceService > ( IWorkspaceService ) ;
122122 const interpreterService = this . serviceContainer . get < IInterpreterService > ( IInterpreterService ) ;
123- const currentInterpreter = await interpreterService . getActiveInterpreter ( resource ) ;
124- if ( ! currentInterpreter ) {
125- const diagnostics = await this . diagnoseDefaultShell ( resource ) ;
126- if ( diagnostics . length ) {
127- return diagnostics ;
128- }
123+ const diagnostics = await this . diagnoseDefaultShell ( resource ) ;
124+ if ( diagnostics . length ) {
125+ return diagnostics ;
129126 }
130127 const hasInterpreters = await interpreterService . hasInterpreters ( ) ;
131128 const interpreterPathService = this . serviceContainer . get < IInterpreterPathService > ( IInterpreterPathService ) ;
@@ -142,6 +139,7 @@ export class InvalidPythonInterpreterService extends BaseDiagnosticsService
142139 ] ;
143140 }
144141
142+ const currentInterpreter = await interpreterService . getActiveInterpreter ( resource ) ;
145143 if ( ! currentInterpreter ) {
146144 return [
147145 new InvalidPythonInterpreterDiagnostic (
@@ -189,7 +187,7 @@ export class InvalidPythonInterpreterService extends BaseDiagnosticsService
189187 if ( diagnostic . code === DiagnosticCodes . InvalidComspecDiagnostic ) {
190188 return [
191189 {
192- prompt : Common . instructions ,
190+ prompt : Common . seeInstructions ,
193191 command : commandFactory . createCommand ( diagnostic , {
194192 type : 'launch' ,
195193 options : 'https://aka.ms/AAk3djo' ,
@@ -222,12 +220,16 @@ export class InvalidPythonInterpreterService extends BaseDiagnosticsService
222220 if ( getOSType ( ) !== OSType . Windows ) {
223221 return [ ] ;
224222 }
225- const executionFactory = this . serviceContainer . get < IPythonExecutionFactory > ( IPythonExecutionFactory ) ;
226- const executionService = await executionFactory . create ( { resource } ) ;
223+ const interpreterService = this . serviceContainer . get < IInterpreterService > ( IInterpreterService ) ;
224+ const currentInterpreter = await interpreterService . getActiveInterpreter ( resource ) ;
225+ if ( currentInterpreter ) {
226+ return [ ] ;
227+ }
227228 try {
228- await executionService . getExecutablePath ( { throwOnError : true } ) ;
229+ await this . shellExecPython ( ) ;
229230 } catch ( ex ) {
230- if ( ( ex as Error ) . message ?. includes ( '4058' ) ) {
231+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
232+ if ( ( ex as any ) . errno === - 4058 ) {
231233 // ENOENT (-4058) error is thrown by Node when the default shell is invalid.
232234 if ( await this . isComspecInvalid ( ) ) {
233235 traceError ( 'ComSpec is set to an invalid value' , process . env . ComSpec ) ;
@@ -241,7 +243,22 @@ export class InvalidPythonInterpreterService extends BaseDiagnosticsService
241243 private async isComspecInvalid ( ) {
242244 const comSpec = process . env . ComSpec ?? '' ;
243245 const fs = this . serviceContainer . get < IFileSystem > ( IFileSystem ) ;
244- return fs . fileExists ( comSpec ) ;
246+ return fs . fileExists ( comSpec ) . then ( ( exists ) => ! exists ) ;
247+ }
248+
249+ @cache ( - 1 , true )
250+ // eslint-disable-next-line class-methods-use-this
251+ private async shellExecPython ( ) {
252+ const configurationService = this . serviceContainer . get < IConfigurationService > ( IConfigurationService ) ;
253+ const { pythonPath } = configurationService . getSettings ( ) ;
254+ const [ args ] = getExecutable ( ) ;
255+ const argv = [ pythonPath , ...args ] ;
256+ // Concat these together to make a set of quoted strings
257+ const quoted = argv . reduce (
258+ ( p , c ) => ( p ? `${ p } ${ c . toCommandArgumentForPythonExt ( ) } ` : `${ c . toCommandArgumentForPythonExt ( ) } ` ) ,
259+ '' ,
260+ ) ;
261+ return shellExec ( quoted , { timeout : 15000 } ) ;
245262 }
246263}
247264
0 commit comments