@@ -6,12 +6,12 @@ import * as path from 'path';
66import  {  OutputChannel ,  Uri  }  from  'vscode' ; 
77import  {  Disposable ,  LanguageClient ,  LanguageClientOptions ,  ServerOptions  }  from  'vscode-languageclient' ; 
88import  {  IApplicationShell ,  ICommandManager ,  IWorkspaceService  }  from  '../common/application/types' ; 
9+ import  {  PythonSettings  }  from  '../common/configSettings' ; 
910import  {  isTestExecution ,  STANDARD_OUTPUT_CHANNEL  }  from  '../common/constants' ; 
1011import  {  createDeferred ,  Deferred  }  from  '../common/helpers' ; 
1112import  {  IFileSystem ,  IPlatformService  }  from  '../common/platform/types' ; 
1213import  {  StopWatch  }  from  '../common/stopWatch' ; 
13- import  {  IConfigurationService ,  IExtensionContext ,  IOutputChannel  }  from  '../common/types' ; 
14- import  {  IInterpreterService  }  from  '../interpreter/contracts' ; 
14+ import  {  IConfigurationService ,  IExtensionContext ,  IOutputChannel ,  IPythonSettings  }  from  '../common/types' ; 
1515import  {  IServiceContainer  }  from  '../ioc/types' ; 
1616import  { 
1717 PYTHON_ANALYSIS_ENGINE_DOWNLOADED , 
@@ -38,7 +38,6 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
3838 private  readonly  fs : IFileSystem ; 
3939 private  readonly  sw  =  new  StopWatch ( ) ; 
4040 private  readonly  platformData : PlatformData ; 
41-  private  readonly  interpreterService : IInterpreterService ; 
4241 private  readonly  startupCompleted : Deferred < void > ; 
4342 private  readonly  disposables : Disposable [ ]  =  [ ] ; 
4443 private  readonly  context : IExtensionContext ; 
@@ -47,6 +46,8 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
4746
4847 private  languageClient : LanguageClient  |  undefined ; 
4948 private  interpreterHash : string  =  '' ; 
49+  private  excludedFiles : string [ ]  =  [ ] ; 
50+  private  typeshedPaths : string [ ]  =  [ ] ; 
5051 private  loadExtensionArgs : { }  |  undefined ; 
5152
5253 constructor ( @inject ( IServiceContainer )  private  readonly  services : IServiceContainer )  { 
@@ -56,7 +57,6 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
5657 this . output  =  this . services . get < OutputChannel > ( IOutputChannel ,  STANDARD_OUTPUT_CHANNEL ) ; 
5758 this . fs  =  this . services . get < IFileSystem > ( IFileSystem ) ; 
5859 this . platformData  =  new  PlatformData ( services . get < IPlatformService > ( IPlatformService ) ,  this . fs ) ; 
59-  this . interpreterService  =  this . services . get < IInterpreterService > ( IInterpreterService ) ; 
6060 this . workspace  =  this . services . get < IWorkspaceService > ( IWorkspaceService ) ; 
6161
6262 // Currently only a single root. Multi-root support is future. 
@@ -76,6 +76,8 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
7676 } 
7777 } 
7878 ) ) ; 
79+ 
80+  ( this . configuration . getSettings ( )  as  PythonSettings ) . addListener ( 'change' ,  this . onSettingsChanged ) ; 
7981 } 
8082
8183 public  async  activate ( ) : Promise < boolean >  { 
@@ -84,7 +86,6 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
8486 if  ( ! clientOptions )  { 
8587 return  false ; 
8688 } 
87-  this . disposables . push ( this . interpreterService . onDidChangeInterpreter ( ( )  =>  this . restartLanguageServer ( ) ) ) ; 
8889 return  this . startLanguageServer ( clientOptions ) ; 
8990 } 
9091
@@ -96,19 +97,7 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
9697 for  ( const  d  of  this . disposables )  { 
9798 d . dispose ( ) ; 
9899 } 
99-  } 
100- 
101-  private  async  restartLanguageServer ( ) : Promise < void >  { 
102-  if  ( ! this . context )  { 
103-  return ; 
104-  } 
105-  const  ids  =  new  InterpreterDataService ( this . context ,  this . services ) ; 
106-  const  idata  =  await  ids . getInterpreterData ( ) ; 
107-  if  ( ! idata  ||  idata . hash  !==  this . interpreterHash )  { 
108-  this . interpreterHash  =  idata  ? idata . hash  : '' ; 
109-  await  this . deactivate ( ) ; 
110-  await  this . activate ( ) ; 
111-  } 
100+  ( this . configuration . getSettings ( )  as  PythonSettings ) . removeListener ( 'change' ,  this . onSettingsChanged ) ; 
112101 } 
113102
114103 private  async  startLanguageServer ( clientOptions : LanguageClientOptions ) : Promise < boolean >  { 
@@ -204,34 +193,27 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
204193 properties [ 'PrefixPath' ]  =  interpreterData . prefix ; 
205194 } 
206195
207-  let   searchPathsString   =   interpreterData  ?  interpreterData . searchPaths  :  '' ; 
208-  let   typeshedPaths :  string [ ]  =  [ ] ; 
196+  // tslint:disable-next-line:no-string-literal 
197+  properties [ 'DatabasePath' ]  =  path . join ( this . context . extensionPath ,   analysisEngineFolder ) ; 
209198
199+  let  searchPaths  =  interpreterData  ? interpreterData . searchPaths . split ( path . delimiter )  : [ ] ; 
210200 const  settings  =  this . configuration . getSettings ( ) ; 
211201 if  ( settings . autoComplete )  { 
212202 const  extraPaths  =  settings . autoComplete . extraPaths ; 
213203 if  ( extraPaths  &&  extraPaths . length  >  0 )  { 
214-  searchPathsString   =   ` ${ searchPathsString } ; ${ extraPaths . join ( ';' ) } ` ; 
204+  searchPaths . push ( ... extraPaths ) ; 
215205 } 
216-  typeshedPaths  =  settings . autoComplete . typeshedPaths ; 
217206 } 
218207
219-  // tslint:disable-next-line:no-string-literal 
220-  properties [ 'DatabasePath' ]  =  path . join ( this . context . extensionPath ,  analysisEngineFolder ) ; 
221- 
222208 // Make sure paths do not contain multiple slashes so file URIs 
223209 // in VS Code (Node.js) and in the language server (.NET) match. 
224210 // Note: for the language server paths separator is always ; 
225-  const  searchPaths  =  searchPathsString . split ( path . delimiter ) . map ( p  =>  path . normalize ( p ) ) ; 
226-  // tslint:disable-next-line:no-string-literal 
227-  properties [ 'SearchPaths' ]  =  `${ searchPaths . join ( ';' ) } ${ pythonPath }  ; 
228- 
229-  if  ( ! typeshedPaths  ||  typeshedPaths . length  ===  0 )  { 
230-  typeshedPaths  =  [ path . join ( this . context . extensionPath ,  'typeshed' ) ] ; 
231-  } 
211+  searchPaths . push ( pythonPath ) ; 
212+  searchPaths  =  searchPaths . map ( p  =>  path . normalize ( p ) ) ; 
232213
233214 const  selector  =  [ {  language : PYTHON ,  scheme : 'file'  } ] ; 
234-  const  excludeFiles  =  this . getExcludedFiles ( ) ; 
215+  this . excludedFiles  =  this . getExcludedFiles ( ) ; 
216+  this . typeshedPaths  =  this . getTypeshedPaths ( settings ) ; 
235217
236218 // Options to control the language client 
237219 return  { 
@@ -253,9 +235,8 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
253235 maxDocumentationTextLength : 0 
254236 } , 
255237 searchPaths, 
256-  typeStubSearchPaths : typeshedPaths , 
257-  asyncStartup : true , 
258-  excludeFiles : excludeFiles , 
238+  typeStubSearchPaths : this . typeshedPaths , 
239+  excludeFiles : this . excludedFiles , 
259240 testEnvironment : isTestExecution ( ) 
260241 } 
261242 } ; 
@@ -289,4 +270,49 @@ export class AnalysisExtensionActivator implements IExtensionActivator {
289270 . forEach ( p  =>  list . push ( p ) ) ; 
290271 } 
291272 } 
273+ 
274+  private  getTypeshedPaths ( settings : IPythonSettings ) : string [ ]  { 
275+  return  settings . analysis . typeshedPaths  &&  settings . analysis . typeshedPaths . length  >  0 
276+  ? settings . analysis . typeshedPaths 
277+  : [ path . join ( this . context . extensionPath ,  'typeshed' ) ] ; 
278+  } 
279+ 
280+  private  async  onSettingsChanged ( ) : Promise < void >  { 
281+  const  ids  =  new  InterpreterDataService ( this . context ,  this . services ) ; 
282+  const  idata  =  await  ids . getInterpreterData ( ) ; 
283+  if  ( ! idata  ||  idata . hash  !==  this . interpreterHash )  { 
284+  this . interpreterHash  =  idata  ? idata . hash  : '' ; 
285+  await  this . restartLanguageServer ( ) ; 
286+  return ; 
287+  } 
288+ 
289+  const  excludedFiles  =  this . getExcludedFiles ( ) ; 
290+  await  this . restartLanguageServerIfArrayChanged ( this . excludedFiles ,  excludedFiles ) ; 
291+ 
292+  const  settings  =  this . configuration . getSettings ( ) ; 
293+  const  typeshedPaths  =  this . getTypeshedPaths ( settings ) ; 
294+  await  this . restartLanguageServerIfArrayChanged ( this . typeshedPaths ,  typeshedPaths ) ; 
295+  } 
296+ 
297+  private  async  restartLanguageServerIfArrayChanged ( oldArray : string [ ] ,  newArray : string [ ] ) : Promise < void >  { 
298+  if  ( newArray . length  !==  oldArray . length )  { 
299+  await  this . restartLanguageServer ( ) ; 
300+  return ; 
301+  } 
302+ 
303+  for  ( let  i  =  0 ;  i  <  oldArray . length ;  i  +=  1 )  { 
304+  if  ( oldArray [ i ]  !==  newArray [ i ] )  { 
305+  await  this . restartLanguageServer ( ) ; 
306+  return ; 
307+  } 
308+  } 
309+  } 
310+ 
311+  private  async  restartLanguageServer ( ) : Promise < void >  { 
312+  if  ( ! this . context )  { 
313+  return ; 
314+  } 
315+  await  this . deactivate ( ) ; 
316+  await  this . activate ( ) ; 
317+  } 
292318} 
0 commit comments