@zzzen/pyright-internal 1.2.0-dev.20230312 → 1.2.0-dev.20230319

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dist/analyzer/backgroundAnalysisProgram.d.ts +1 -1
  2. package/dist/analyzer/backgroundAnalysisProgram.js +1 -1
  3. package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
  4. package/dist/analyzer/cacheManager.d.ts +4 -0
  5. package/dist/analyzer/cacheManager.js +13 -0
  6. package/dist/analyzer/cacheManager.js.map +1 -1
  7. package/dist/analyzer/checker.d.ts +2 -1
  8. package/dist/analyzer/checker.js +70 -26
  9. package/dist/analyzer/checker.js.map +1 -1
  10. package/dist/analyzer/codeFlowEngine.js +17 -11
  11. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  12. package/dist/analyzer/program.d.ts +1 -1
  13. package/dist/analyzer/program.js +16 -15
  14. package/dist/analyzer/program.js.map +1 -1
  15. package/dist/analyzer/properties.js +0 -1
  16. package/dist/analyzer/properties.js.map +1 -1
  17. package/dist/analyzer/service.d.ts +2 -1
  18. package/dist/analyzer/service.js +9 -3
  19. package/dist/analyzer/service.js.map +1 -1
  20. package/dist/analyzer/sourceFile.d.ts +2 -2
  21. package/dist/analyzer/sourceFile.js +2 -2
  22. package/dist/analyzer/sourceFile.js.map +1 -1
  23. package/dist/analyzer/sourceFileInfoUtils.d.ts +1 -0
  24. package/dist/analyzer/sourceFileInfoUtils.js +17 -1
  25. package/dist/analyzer/sourceFileInfoUtils.js.map +1 -1
  26. package/dist/analyzer/typeEvaluator.js +48 -54
  27. package/dist/analyzer/typeEvaluator.js.map +1 -1
  28. package/dist/analyzer/typeEvaluatorTypes.d.ts +0 -2
  29. package/dist/analyzer/typeEvaluatorTypes.js +0 -3
  30. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  31. package/dist/analyzer/typeStubWriter.js +2 -0
  32. package/dist/analyzer/typeStubWriter.js.map +1 -1
  33. package/dist/analyzer/typeUtils.js +20 -0
  34. package/dist/analyzer/typeUtils.js.map +1 -1
  35. package/dist/analyzer/typedDicts.js +27 -0
  36. package/dist/analyzer/typedDicts.js.map +1 -1
  37. package/dist/analyzer/types.d.ts +4 -1
  38. package/dist/analyzer/types.js +3 -1
  39. package/dist/analyzer/types.js.map +1 -1
  40. package/dist/commands/dumpFileDebugInfoCommand.js +4 -4
  41. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  42. package/dist/commands/quickActionCommand.js +2 -2
  43. package/dist/commands/quickActionCommand.js.map +1 -1
  44. package/dist/common/configOptions.d.ts +1 -0
  45. package/dist/common/configOptions.js +4 -0
  46. package/dist/common/configOptions.js.map +1 -1
  47. package/dist/common/console.d.ts +1 -0
  48. package/dist/common/console.js +19 -1
  49. package/dist/common/console.js.map +1 -1
  50. package/dist/common/diagnosticRules.d.ts +2 -1
  51. package/dist/common/diagnosticRules.js +1 -0
  52. package/dist/common/diagnosticRules.js.map +1 -1
  53. package/dist/common/extensibility.d.ts +2 -2
  54. package/dist/common/extensibility.js.map +1 -1
  55. package/dist/common/extensions.js +3 -1
  56. package/dist/common/extensions.js.map +1 -1
  57. package/dist/languageServerBase.d.ts +21 -46
  58. package/dist/languageServerBase.js +109 -151
  59. package/dist/languageServerBase.js.map +1 -1
  60. package/dist/languageService/analyzerServiceExecutor.d.ts +4 -3
  61. package/dist/languageService/analyzerServiceExecutor.js +9 -7
  62. package/dist/languageService/analyzerServiceExecutor.js.map +1 -1
  63. package/dist/languageService/codeActionProvider.d.ts +2 -2
  64. package/dist/languageService/codeActionProvider.js +4 -4
  65. package/dist/languageService/codeActionProvider.js.map +1 -1
  66. package/dist/languageService/completionProvider.js +3 -5
  67. package/dist/languageService/completionProvider.js.map +1 -1
  68. package/dist/languageService/definitionProvider.js +1 -1
  69. package/dist/languageService/definitionProvider.js.map +1 -1
  70. package/dist/languageService/documentSymbolCollector.d.ts +2 -1
  71. package/dist/languageService/documentSymbolCollector.js +23 -2
  72. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  73. package/dist/languageService/hoverProvider.d.ts +2 -1
  74. package/dist/languageService/hoverProvider.js +21 -5
  75. package/dist/languageService/hoverProvider.js.map +1 -1
  76. package/dist/languageService/referencesProvider.d.ts +3 -2
  77. package/dist/languageService/referencesProvider.js +4 -4
  78. package/dist/languageService/referencesProvider.js.map +1 -1
  79. package/dist/localization/localize.d.ts +14 -6
  80. package/dist/localization/localize.js +5 -4
  81. package/dist/localization/localize.js.map +1 -1
  82. package/dist/localization/package.nls.en-us.json +7 -6
  83. package/dist/parser/parser.js +4 -2
  84. package/dist/parser/parser.js.map +1 -1
  85. package/dist/server.d.ts +3 -2
  86. package/dist/server.js +1 -4
  87. package/dist/server.js.map +1 -1
  88. package/dist/tests/cacheManager.test.d.ts +1 -0
  89. package/dist/tests/cacheManager.test.js +69 -0
  90. package/dist/tests/cacheManager.test.js.map +1 -0
  91. package/dist/tests/checker.test.js +2 -2
  92. package/dist/tests/completions.test.js +2 -2
  93. package/dist/tests/completions.test.js.map +1 -1
  94. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.d.ts +7 -0
  95. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.js +45 -0
  96. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.js.map +1 -0
  97. package/dist/tests/harness/fourslash/testLanguageService.d.ts +7 -6
  98. package/dist/tests/harness/fourslash/testLanguageService.js +14 -13
  99. package/dist/tests/harness/fourslash/testLanguageService.js.map +1 -1
  100. package/dist/tests/harness/fourslash/testState.d.ts +5 -4
  101. package/dist/tests/harness/fourslash/testState.js +14 -13
  102. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  103. package/dist/tests/moveSymbol.misc.test.js +1 -1
  104. package/dist/tests/moveSymbol.misc.test.js.map +1 -1
  105. package/dist/tests/service.test.js +4 -4
  106. package/dist/tests/service.test.js.map +1 -1
  107. package/dist/tests/signatureHelp.test.js +2 -2
  108. package/dist/tests/signatureHelp.test.js.map +1 -1
  109. package/dist/tests/sourceFile.test.js +3 -3
  110. package/dist/tests/sourceFile.test.js.map +1 -1
  111. package/dist/tests/typeEvaluator2.test.js +2 -2
  112. package/dist/tests/typeEvaluator3.test.js +1 -1
  113. package/dist/tests/typeEvaluator4.test.js +1 -1
  114. package/dist/tests/typeEvaluator5.test.js +12 -0
  115. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  116. package/dist/tests/workspaceEditUtils.test.js +2 -2
  117. package/dist/tests/workspaceEditUtils.test.js.map +1 -1
  118. package/dist/workspaceFactory.d.ts +72 -0
  119. package/dist/workspaceFactory.js +421 -0
  120. package/dist/workspaceFactory.js.map +1 -0
  121. package/package.json +4 -4
  122. package/dist/workspaceMap.d.ts +0 -14
  123. package/dist/workspaceMap.js +0 -172
  124. package/dist/workspaceMap.js.map +0 -1
@@ -10,7 +10,7 @@
10
10
  * from the same core functionality.
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.LanguageServerBase = exports.createInitStatus = exports.WellKnownWorkspaceKinds = void 0;
13
+ exports.LanguageServerBase = void 0;
14
14
  require("./common/extensions");
15
15
  const vscode_languageserver_1 = require("vscode-languageserver");
16
16
  const progress_1 = require("vscode-languageserver/lib/common/progress");
@@ -24,12 +24,12 @@ const collectionUtils_1 = require("./common/collectionUtils");
24
24
  const commandLineOptions_1 = require("./common/commandLineOptions");
25
25
  const configOptions_1 = require("./common/configOptions");
26
26
  const console_1 = require("./common/console");
27
- const deferred_1 = require("./common/deferred");
28
27
  const diagnostic_1 = require("./common/diagnostic");
29
28
  const extensibility_1 = require("./common/extensibility");
30
29
  const lspUtils_1 = require("./common/lspUtils");
31
30
  const pathUtils_1 = require("./common/pathUtils");
32
31
  const progressReporter_1 = require("./common/progressReporter");
32
+ const stringUtils_1 = require("./common/stringUtils");
33
33
  const uriParser_1 = require("./common/uriParser");
34
34
  const workspaceEditUtils_1 = require("./common/workspaceEditUtils");
35
35
  const analyzerServiceExecutor_1 = require("./languageService/analyzerServiceExecutor");
@@ -38,46 +38,7 @@ const documentSymbolProvider_1 = require("./languageService/documentSymbolProvid
38
38
  const hoverProvider_1 = require("./languageService/hoverProvider");
39
39
  const localize_1 = require("./localization/localize");
40
40
  const pyrightFileSystem_1 = require("./pyrightFileSystem");
41
- var WellKnownWorkspaceKinds;
42
- (function (WellKnownWorkspaceKinds) {
43
- WellKnownWorkspaceKinds["Default"] = "default";
44
- WellKnownWorkspaceKinds["Regular"] = "regular";
45
- WellKnownWorkspaceKinds["Limited"] = "limited";
46
- WellKnownWorkspaceKinds["Cloned"] = "cloned";
47
- WellKnownWorkspaceKinds["Test"] = "test";
48
- })(WellKnownWorkspaceKinds = exports.WellKnownWorkspaceKinds || (exports.WellKnownWorkspaceKinds = {}));
49
- function createInitStatus() {
50
- // Due to the way we get `python path`, `include/exclude` from settings to initialize workspace,
51
- // we need to wait for getSettings to finish before letting IDE features to use workspace (`isInitialized` field).
52
- // So most of cases, whenever we create new workspace, we send request to workspace/configuration right way
53
- // except one place which is `initialize` LSP call.
54
- // In `initialize` method where we create `initial workspace`, we can't do that since LSP spec doesn't allow
55
- // LSP server from sending any request to client until `initialized` method is called.
56
- // This flag indicates whether we had our initial updateSetting call or not after `initialized` call.
57
- let called = false;
58
- const deferred = (0, deferred_1.createDeferred)();
59
- const self = {
60
- promise: deferred.promise,
61
- resolve: () => {
62
- called = true;
63
- deferred.resolve();
64
- },
65
- markCalled: () => {
66
- called = true;
67
- },
68
- reset: () => {
69
- if (!called) {
70
- return self;
71
- }
72
- return createInitStatus();
73
- },
74
- resolved: () => {
75
- return deferred.resolved;
76
- },
77
- };
78
- return self;
79
- }
80
- exports.createInitStatus = createInitStatus;
41
+ const workspaceFactory_1 = require("./workspaceFactory");
81
42
  const nullProgressReporter = (0, progress_1.attachWorkDone)(undefined, /* params */ undefined);
82
43
  /*
83
44
  * Additional DiagnosticTag values that are specific to Visual Studio.
@@ -144,6 +105,7 @@ class LanguageServerBase {
144
105
  this._connection = _connection;
145
106
  this.console = console;
146
107
  this._lastTriggerKind = vscode_languageserver_1.CompletionTriggerKind.Invoked;
108
+ this._initialized = false;
147
109
  // Global root path - the basis for all global settings.
148
110
  this.rootPath = '';
149
111
  this.client = {
@@ -175,9 +137,9 @@ class LanguageServerBase {
175
137
  this.console.info(`${_serverOptions.productName} language server ${_serverOptions.version && _serverOptions.version + ' '}starting`);
176
138
  this.console.info(`Server root directory: ${_serverOptions.rootDirectory}`);
177
139
  this._cacheManager = new cacheManager_1.CacheManager();
178
- this._workspaceMap = this._serverOptions.workspaceMap;
179
140
  this._serviceFS = new pyrightFileSystem_1.PyrightFileSystem(this._serverOptions.fileSystem);
180
141
  this._uriParser = uriParserFactory(this._serviceFS);
142
+ this._workspaceFactory = new workspaceFactory_1.WorkspaceFactory(this.console, this._uriParser, this.createAnalyzerServiceForWorkspace.bind(this), this.isPythonPathImmutable.bind(this), this.onWorkspaceCreated.bind(this));
181
143
  // Set the working directory to a known location within
182
144
  // the extension directory. Otherwise the execution of
183
145
  // python can have unintended and surprising results.
@@ -197,6 +159,12 @@ class LanguageServerBase {
197
159
  decodeTextDocumentUri(uriString) {
198
160
  return this._uriParser.decodeTextDocumentUri(uriString);
199
161
  }
162
+ isPythonPathImmutable(filePath) {
163
+ // This function is called to determine if the file is using
164
+ // a special pythonPath separate from a workspace or not.
165
+ // The default is no.
166
+ return false;
167
+ }
200
168
  async getConfiguration(scopeUri, section) {
201
169
  if (this.client.hasConfigurationCapability) {
202
170
  const item = {};
@@ -266,23 +234,26 @@ class LanguageServerBase {
266
234
  return service;
267
235
  }
268
236
  async test_getWorkspaces() {
269
- const workspaces = [...this._workspaceMap.values()];
237
+ const workspaces = [...this._workspaceFactory.items()];
270
238
  for (const workspace of workspaces) {
271
239
  await workspace.isInitialized.promise;
272
240
  }
273
241
  return workspaces;
274
242
  }
275
- async getWorkspaceForFile(filePath) {
276
- return this._workspaceMap.getWorkspaceForFile(this, filePath);
243
+ async getWorkspaceForFile(filePath, pythonPath) {
244
+ return this._workspaceFactory.getWorkspaceForFile(filePath, pythonPath);
245
+ }
246
+ async getContainingWorkspacesForFile(filePath) {
247
+ return this._workspaceFactory.getContainingWorkspacesForFile(filePath);
277
248
  }
278
249
  reanalyze() {
279
- this._workspaceMap.forEach((workspace) => {
280
- workspace.serviceInstance.invalidateAndForceReanalysis();
250
+ this._workspaceFactory.items().forEach((workspace) => {
251
+ workspace.service.invalidateAndForceReanalysis();
281
252
  });
282
253
  }
283
254
  restart() {
284
- this._workspaceMap.forEach((workspace) => {
285
- workspace.serviceInstance.restart();
255
+ this._workspaceFactory.items().forEach((workspace) => {
256
+ workspace.service.restart();
286
257
  });
287
258
  }
288
259
  setupConnection(supportedCommands, supportedCodeActions) {
@@ -356,15 +327,7 @@ class LanguageServerBase {
356
327
  this.client.completionItemResolveSupportsAdditionalTextEdits =
357
328
  !!((_19 = (_18 = (_17 = (_16 = capabilities.textDocument) === null || _16 === void 0 ? void 0 : _16.completion) === null || _17 === void 0 ? void 0 : _17.completionItem) === null || _18 === void 0 ? void 0 : _18.resolveSupport) === null || _19 === void 0 ? void 0 : _19.properties.some((p) => p === 'additionalTextEdits'));
358
329
  // Create a service instance for each of the workspace folders.
359
- if (params.workspaceFolders) {
360
- params.workspaceFolders.forEach((folder) => {
361
- const path = this._uriParser.decodeTextDocumentUri(folder.uri);
362
- this._workspaceMap.set(path, this.createWorkspaceServiceInstance(folder, path, path));
363
- });
364
- }
365
- else if (params.rootPath) {
366
- this._workspaceMap.set(params.rootPath, this.createWorkspaceServiceInstance(undefined, params.rootPath, params.rootPath));
367
- }
330
+ this._workspaceFactory.handleInitialize(params);
368
331
  const result = {
369
332
  capabilities: {
370
333
  textDocumentSync: vscode_languageserver_1.TextDocumentSyncKind.Incremental,
@@ -411,22 +374,16 @@ class LanguageServerBase {
411
374
  return result;
412
375
  }
413
376
  onInitialized() {
377
+ // Mark as initialized. We need this to make sure to
378
+ // not send config updates before this point.
379
+ this._initialized = true;
414
380
  if (!this.client.hasWorkspaceFoldersCapability) {
415
381
  // If folder capability is not supported, initialize ones given by onInitialize.
416
382
  this.updateSettingsForAllWorkspaces();
417
383
  return;
418
384
  }
419
385
  this._connection.workspace.onDidChangeWorkspaceFolders((event) => {
420
- event.removed.forEach((workspaceInfo) => {
421
- const rootPath = this._uriParser.decodeTextDocumentUri(workspaceInfo.uri);
422
- this._workspaceMap.delete(rootPath);
423
- });
424
- event.added.forEach((workspaceInfo) => {
425
- const rootPath = this._uriParser.decodeTextDocumentUri(workspaceInfo.uri);
426
- const newWorkspace = this.createWorkspaceServiceInstance(workspaceInfo, rootPath, rootPath);
427
- this._workspaceMap.set(rootPath, newWorkspace);
428
- this.updateSettingsForWorkspace(newWorkspace, newWorkspace.isInitialized).ignoreErrors();
429
- });
386
+ this._workspaceFactory.handleWorkspaceFoldersChanged(event);
430
387
  this._setupFileWatcher();
431
388
  });
432
389
  this._setupFileWatcher();
@@ -446,7 +403,7 @@ class LanguageServerBase {
446
403
  // Dedup search paths from all workspaces.
447
404
  // Get rid of any search path under workspace root since it is already watched by
448
405
  // "**" above.
449
- const foldersToWatch = (0, pathUtils_1.deduplicateFolders)(this._workspaceMap
406
+ const foldersToWatch = (0, pathUtils_1.deduplicateFolders)(this._workspaceFactory
450
407
  .getNonDefaultWorkspaces()
451
408
  .map((w) => w.searchPathsToWatch.filter((p) => !p.startsWith(w.rootPath))));
452
409
  foldersToWatch.forEach((p) => {
@@ -472,13 +429,13 @@ class LanguageServerBase {
472
429
  this.updateSettingsForAllWorkspaces();
473
430
  }
474
431
  async onDefinition(params, token) {
475
- return this.getDefinitions(params, token, this.client.hasGoToDeclarationCapability ? definitionProvider_1.DefinitionFilter.PreferSource : definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, filter, token) => workspace.serviceInstance.getDefinitionForPosition(filePath, position, filter, token));
432
+ return this.getDefinitions(params, token, this.client.hasGoToDeclarationCapability ? definitionProvider_1.DefinitionFilter.PreferSource : definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, filter, token) => workspace.service.getDefinitionForPosition(filePath, position, filter, token));
476
433
  }
477
434
  async onDeclaration(params, token) {
478
- return this.getDefinitions(params, token, this.client.hasGoToDeclarationCapability ? definitionProvider_1.DefinitionFilter.PreferStubs : definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, filter, token) => workspace.serviceInstance.getDefinitionForPosition(filePath, position, filter, token));
435
+ return this.getDefinitions(params, token, this.client.hasGoToDeclarationCapability ? definitionProvider_1.DefinitionFilter.PreferStubs : definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, filter, token) => workspace.service.getDefinitionForPosition(filePath, position, filter, token));
479
436
  }
480
437
  async onTypeDefinition(params, token) {
481
- return this.getDefinitions(params, token, definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, _, token) => workspace.serviceInstance.getTypeDefinitionForPosition(filePath, position, token));
438
+ return this.getDefinitions(params, token, definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, _, token) => workspace.service.getTypeDefinitionForPosition(filePath, position, token));
482
439
  }
483
440
  async getDefinitions(params, token, filter, getDefinitionsFunc) {
484
441
  this.recordUserInteractionTime();
@@ -492,8 +449,8 @@ class LanguageServerBase {
492
449
  return undefined;
493
450
  }
494
451
  return locations
495
- .filter((loc) => this.canNavigateToFile(loc.path, workspace.serviceInstance.fs))
496
- .map((loc) => vscode_languageserver_1.Location.create((0, pathUtils_1.convertPathToUri)(workspace.serviceInstance.fs, loc.path), loc.range));
452
+ .filter((loc) => this.canNavigateToFile(loc.path, workspace.service.fs))
453
+ .map((loc) => vscode_languageserver_1.Location.create((0, pathUtils_1.convertPathToUri)(workspace.service.fs, loc.path), loc.range));
497
454
  }
498
455
  async onReferences(params, token, workDoneReporter, resultReporter) {
499
456
  if (this._pendingFindAllRefsCancellationSource) {
@@ -514,14 +471,14 @@ class LanguageServerBase {
514
471
  }
515
472
  const convert = (locs) => {
516
473
  return locs
517
- .filter((loc) => this.canNavigateToFile(loc.path, workspace.serviceInstance.fs))
518
- .map((loc) => vscode_languageserver_1.Location.create((0, pathUtils_1.convertPathToUri)(workspace.serviceInstance.fs, loc.path), loc.range));
474
+ .filter((loc) => this.canNavigateToFile(loc.path, workspace.service.fs))
475
+ .map((loc) => vscode_languageserver_1.Location.create((0, pathUtils_1.convertPathToUri)(workspace.service.fs, loc.path), loc.range));
519
476
  };
520
477
  const locations = [];
521
478
  const reporter = resultReporter
522
479
  ? (locs) => resultReporter.report(convert(locs))
523
480
  : (locs) => (0, collectionUtils_1.appendArray)(locations, convert(locs));
524
- workspace.serviceInstance.reportReferencesForPosition(filePath, position, params.context.includeDeclaration, reporter, source.token);
481
+ workspace.service.reportReferencesForPosition(filePath, position, params.context.includeDeclaration, reporter, source.token);
525
482
  return locations;
526
483
  }
527
484
  finally {
@@ -537,7 +494,7 @@ class LanguageServerBase {
537
494
  return undefined;
538
495
  }
539
496
  const symbolList = [];
540
- workspace.serviceInstance.addSymbolsForDocument(filePath, symbolList, token);
497
+ workspace.service.addSymbolsForDocument(filePath, symbolList, token);
541
498
  if (this.client.hasHierarchicalDocumentSymbolCapability) {
542
499
  return symbolList;
543
500
  }
@@ -548,10 +505,10 @@ class LanguageServerBase {
548
505
  const reporter = resultReporter
549
506
  ? (symbols) => resultReporter.report(symbols)
550
507
  : (symbols) => (0, collectionUtils_1.appendArray)(symbolList, symbols);
551
- for (const workspace of this._workspaceMap.values()) {
508
+ for (const workspace of this._workspaceFactory.items()) {
552
509
  await workspace.isInitialized.promise;
553
510
  if (!workspace.disableLanguageServices && !workspace.disableWorkspaceSymbol) {
554
- workspace.serviceInstance.reportSymbolsForWorkspace(params.query, reporter, token);
511
+ workspace.service.reportSymbolsForWorkspace(params.query, reporter, token);
555
512
  }
556
513
  }
557
514
  return symbolList;
@@ -559,13 +516,13 @@ class LanguageServerBase {
559
516
  async onHover(params, token) {
560
517
  const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
561
518
  const workspace = await this.getWorkspaceForFile(filePath);
562
- const hoverResults = workspace.serviceInstance.getHoverForPosition(filePath, position, this.client.hoverContentFormat, token);
563
- return (0, hoverProvider_1.convertHoverResults)(this.client.hoverContentFormat, hoverResults);
519
+ const hoverResults = workspace.service.getHoverForPosition(filePath, position, this.client.hoverContentFormat, token);
520
+ return (0, hoverProvider_1.convertHoverResults)(this.client.hoverContentFormat, hoverResults, !!this._serverOptions.supportsTelemetry);
564
521
  }
565
522
  async onDocumentHighlight(params, token) {
566
523
  const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
567
524
  const workspace = await this.getWorkspaceForFile(filePath);
568
- return workspace.serviceInstance.getDocumentHighlight(filePath, position, token);
525
+ return workspace.service.getDocumentHighlight(filePath, position, token);
569
526
  }
570
527
  async onSignatureHelp(params, token) {
571
528
  var _a, _b;
@@ -574,7 +531,7 @@ class LanguageServerBase {
574
531
  if (workspace.disableLanguageServices) {
575
532
  return;
576
533
  }
577
- const signatureHelpResults = workspace.serviceInstance.getSignatureHelpForPosition(filePath, position, this.client.signatureDocFormat, token);
534
+ const signatureHelpResults = workspace.service.getSignatureHelpForPosition(filePath, position, this.client.signatureDocFormat, token);
578
535
  if (!signatureHelpResults) {
579
536
  return undefined;
580
537
  }
@@ -669,6 +626,19 @@ class LanguageServerBase {
669
626
  if (completions) {
670
627
  completions.completionList.isIncomplete = completionIncomplete;
671
628
  }
629
+ // Add memberAccessInfo.lastKnownModule if we have it. The client side
630
+ // will use this to send extra telemetry
631
+ if ((completions === null || completions === void 0 ? void 0 : completions.memberAccessInfo) &&
632
+ completions.completionList &&
633
+ completions.completionList.items.length > 0 &&
634
+ completions.memberAccessInfo.lastKnownModule &&
635
+ this._serverOptions.supportsTelemetry) {
636
+ // Just stick it on the first item. It only checks the first one
637
+ completions.completionList.items[0].data = {
638
+ ...completions.completionList.items[0].data,
639
+ moduleHash: (0, stringUtils_1.hashString)(completions.memberAccessInfo.lastKnownModule),
640
+ };
641
+ }
672
642
  return completions === null || completions === void 0 ? void 0 : completions.completionList;
673
643
  }
674
644
  // Cancellation bugs in vscode and LSP:
@@ -692,7 +662,7 @@ class LanguageServerBase {
692
662
  if (workspace.disableLanguageServices) {
693
663
  return null;
694
664
  }
695
- const result = workspace.serviceInstance.canRenameSymbolAtPosition(filePath, position, workspace.path === '', this.allowModuleRename, token);
665
+ const result = workspace.service.canRenameSymbolAtPosition(filePath, position, workspace.kinds.includes(workspaceFactory_1.WellKnownWorkspaceKinds.Default), this.allowModuleRename, token);
696
666
  return (_a = result === null || result === void 0 ? void 0 : result.range) !== null && _a !== void 0 ? _a : null;
697
667
  }
698
668
  async onRenameRequest(params, token) {
@@ -701,11 +671,11 @@ class LanguageServerBase {
701
671
  if (workspace.disableLanguageServices) {
702
672
  return;
703
673
  }
704
- const editActions = workspace.serviceInstance.renameSymbolAtPosition(filePath, position, params.newName, workspace.path === '', this.allowModuleRename, token);
674
+ const editActions = workspace.service.renameSymbolAtPosition(filePath, position, params.newName, workspace.kinds.includes(workspaceFactory_1.WellKnownWorkspaceKinds.Default), this.allowModuleRename, token);
705
675
  if (!editActions) {
706
676
  return undefined;
707
677
  }
708
- return (0, workspaceEditUtils_1.convertToWorkspaceEdit)(workspace.serviceInstance.fs, editActions);
678
+ return (0, workspaceEditUtils_1.convertToWorkspaceEdit)(workspace.service.fs, editActions);
709
679
  }
710
680
  async onPrepare(params, token) {
711
681
  const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
@@ -713,15 +683,15 @@ class LanguageServerBase {
713
683
  if (workspace.disableLanguageServices) {
714
684
  return null;
715
685
  }
716
- const callItem = workspace.serviceInstance.getCallForPosition(filePath, position, token) || null;
686
+ const callItem = workspace.service.getCallForPosition(filePath, position, token) || null;
717
687
  if (!callItem) {
718
688
  return null;
719
689
  }
720
- if (!this.canNavigateToFile(callItem.uri, workspace.serviceInstance.fs)) {
690
+ if (!this.canNavigateToFile(callItem.uri, workspace.service.fs)) {
721
691
  return null;
722
692
  }
723
693
  // Convert the file path in the item to proper URI.
724
- callItem.uri = (0, pathUtils_1.convertPathToUri)(workspace.serviceInstance.fs, callItem.uri);
694
+ callItem.uri = (0, pathUtils_1.convertPathToUri)(workspace.service.fs, callItem.uri);
725
695
  return [callItem];
726
696
  }
727
697
  async onIncomingCalls(params, token) {
@@ -730,14 +700,14 @@ class LanguageServerBase {
730
700
  if (workspace.disableLanguageServices) {
731
701
  return null;
732
702
  }
733
- let callItems = workspace.serviceInstance.getIncomingCallsForPosition(filePath, position, token) || null;
703
+ let callItems = workspace.service.getIncomingCallsForPosition(filePath, position, token) || null;
734
704
  if (!callItems || callItems.length === 0) {
735
705
  return null;
736
706
  }
737
- callItems = callItems.filter((item) => this.canNavigateToFile(item.from.uri, workspace.serviceInstance.fs));
707
+ callItems = callItems.filter((item) => this.canNavigateToFile(item.from.uri, workspace.service.fs));
738
708
  // Convert the file paths in the items to proper URIs.
739
709
  callItems.forEach((item) => {
740
- item.from.uri = (0, pathUtils_1.convertPathToUri)(workspace.serviceInstance.fs, item.from.uri);
710
+ item.from.uri = (0, pathUtils_1.convertPathToUri)(workspace.service.fs, item.from.uri);
741
711
  });
742
712
  return callItems;
743
713
  }
@@ -747,14 +717,14 @@ class LanguageServerBase {
747
717
  if (workspace.disableLanguageServices) {
748
718
  return null;
749
719
  }
750
- let callItems = workspace.serviceInstance.getOutgoingCallsForPosition(filePath, position, token) || null;
720
+ let callItems = workspace.service.getOutgoingCallsForPosition(filePath, position, token) || null;
751
721
  if (!callItems || callItems.length === 0) {
752
722
  return null;
753
723
  }
754
- callItems = callItems.filter((item) => this.canNavigateToFile(item.to.uri, workspace.serviceInstance.fs));
724
+ callItems = callItems.filter((item) => this.canNavigateToFile(item.to.uri, workspace.service.fs));
755
725
  // Convert the file paths in the items to proper URIs.
756
726
  callItems.forEach((item) => {
757
- item.to.uri = (0, pathUtils_1.convertPathToUri)(workspace.serviceInstance.fs, item.to.uri);
727
+ item.to.uri = (0, pathUtils_1.convertPathToUri)(workspace.service.fs, item.to.uri);
758
728
  });
759
729
  return callItems;
760
730
  }
@@ -764,8 +734,11 @@ class LanguageServerBase {
764
734
  // We do not support opening 1 file with 2 different uri.
765
735
  return;
766
736
  }
767
- const workspace = await this.getWorkspaceForFile(filePath);
768
- workspace.serviceInstance.setFileOpened(filePath, params.textDocument.version, params.textDocument.text, ipythonMode);
737
+ // Send this open to all the workspaces that might contain this file.
738
+ const workspaces = await this.getContainingWorkspacesForFile(filePath);
739
+ workspaces.forEach((w) => {
740
+ w.service.setFileOpened(filePath, params.textDocument.version, params.textDocument.text, ipythonMode);
741
+ });
769
742
  }
770
743
  async onDidChangeTextDocument(params, ipythonMode = sourceFile_1.IPythonMode.None) {
771
744
  this.recordUserInteractionTime();
@@ -774,8 +747,11 @@ class LanguageServerBase {
774
747
  // We do not support opening 1 file with 2 different uri.
775
748
  return;
776
749
  }
777
- const workspace = await this.getWorkspaceForFile(filePath);
778
- workspace.serviceInstance.updateOpenFileContents(filePath, params.textDocument.version, params.contentChanges, ipythonMode);
750
+ // Send this change to all the workspaces that might contain this file.
751
+ const workspaces = await this.getContainingWorkspacesForFile(filePath);
752
+ workspaces.forEach((w) => {
753
+ w.service.updateOpenFileContents(filePath, params.textDocument.version, params.contentChanges, ipythonMode);
754
+ });
779
755
  }
780
756
  async onDidCloseTextDocument(params) {
781
757
  const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri);
@@ -783,8 +759,11 @@ class LanguageServerBase {
783
759
  // We do not support opening 1 file with 2 different uri.
784
760
  return;
785
761
  }
786
- const workspace = await this.getWorkspaceForFile(filePath);
787
- workspace.serviceInstance.setFileClosed(filePath);
762
+ // Send this close to all the workspaces that might contain this file.
763
+ const workspaces = await this.getContainingWorkspacesForFile(filePath);
764
+ workspaces.forEach((w) => {
765
+ w.service.setFileClosed(filePath);
766
+ });
788
767
  }
789
768
  onDidChangeWatchedFiles(params) {
790
769
  params.changes.forEach((change) => {
@@ -834,19 +813,19 @@ class LanguageServerBase {
834
813
  }
835
814
  onShutdown(token) {
836
815
  // Shutdown remaining workspaces.
837
- this._workspaceMap.forEach((_, key) => this._workspaceMap.delete(key));
816
+ this._workspaceFactory.clear();
838
817
  return Promise.resolve();
839
818
  }
840
819
  resolveWorkspaceCompletionItem(workspace, filePath, item, token) {
841
- workspace.serviceInstance.resolveCompletionItem(filePath, item, this.getCompletionOptions(workspace),
820
+ workspace.service.resolveCompletionItem(filePath, item, this.getCompletionOptions(workspace),
842
821
  /* nameMap */ undefined, token);
843
822
  }
844
823
  getWorkspaceCompletionsForPosition(workspace, filePath, position, options, token) {
845
- return workspace.serviceInstance.getCompletionsForPosition(filePath, position, workspace.path, options, undefined, token);
824
+ return workspace.service.getCompletionsForPosition(filePath, position, workspace.rootPath, options, undefined, token);
846
825
  }
847
826
  updateSettingsForAllWorkspaces() {
848
827
  const tasks = [];
849
- this._workspaceMap.forEach((workspace) => {
828
+ this._workspaceFactory.items().forEach((workspace) => {
850
829
  // Updating settings can change workspace's file ownership. Make workspace uninitialized so that
851
830
  // features can wait until workspace gets new settings.
852
831
  // the file's ownership can also changed by `pyrightconfig.json` changes, but those are synchronous
@@ -871,32 +850,6 @@ class LanguageServerBase {
871
850
  triggerCharacter: (_a = params === null || params === void 0 ? void 0 : params.context) === null || _a === void 0 ? void 0 : _a.triggerCharacter,
872
851
  };
873
852
  }
874
- createWorkspaceServiceInstance(workspaceFolder, rootPath, path, kinds = [WellKnownWorkspaceKinds.Regular], services) {
875
- var _a, _b, _c;
876
- // 5 seconds default
877
- const defaultBackOffTime = 5 * 1000;
878
- // 10 seconds back off for multi workspace.
879
- const multiWorkspaceBackOffTime = 10 * 1000;
880
- const libraryReanalysisTimeProvider = kinds.length === 1 && kinds[0] === WellKnownWorkspaceKinds.Regular
881
- ? () => this._workspaceMap.hasMultipleWorkspaces(kinds[0])
882
- ? multiWorkspaceBackOffTime
883
- : defaultBackOffTime
884
- : () => defaultBackOffTime;
885
- const rootUri = (_a = workspaceFolder === null || workspaceFolder === void 0 ? void 0 : workspaceFolder.uri) !== null && _a !== void 0 ? _a : '';
886
- return {
887
- workspaceName: (_b = workspaceFolder === null || workspaceFolder === void 0 ? void 0 : workspaceFolder.name) !== null && _b !== void 0 ? _b : '',
888
- rootPath,
889
- path,
890
- uri: rootUri,
891
- kinds,
892
- serviceInstance: this.createAnalyzerService((_c = workspaceFolder === null || workspaceFolder === void 0 ? void 0 : workspaceFolder.name) !== null && _c !== void 0 ? _c : path, services, libraryReanalysisTimeProvider),
893
- disableLanguageServices: false,
894
- disableOrganizeImports: false,
895
- disableWorkspaceSymbol: false,
896
- isInitialized: createInitStatus(),
897
- searchPathsToWatch: [],
898
- };
899
- }
900
853
  convertDiagnostics(fs, fileDiagnostics) {
901
854
  return [
902
855
  {
@@ -943,6 +896,9 @@ class LanguageServerBase {
943
896
  serverSettings = serverSettings !== null && serverSettings !== void 0 ? serverSettings : (await this.getSettings(workspace));
944
897
  // Set logging level first.
945
898
  this.console.level = (_a = serverSettings.logLevel) !== null && _a !== void 0 ? _a : console_1.LogLevel.Info;
899
+ // Apply the new path to the workspace (before restarting the service).
900
+ serverSettings.pythonPath = this._workspaceFactory.applyPythonPath(workspace, serverSettings.pythonPath);
901
+ // Then use the updated settings to restart the service.
946
902
  this.updateOptionsAndRestartService(workspace, serverSettings);
947
903
  workspace.disableLanguageServices = !!serverSettings.disableLanguageServices;
948
904
  workspace.disableOrganizeImports = !!serverSettings.disableOrganizeImports;
@@ -954,24 +910,26 @@ class LanguageServerBase {
954
910
  updateOptionsAndRestartService(workspace, serverSettings, typeStubTargetImportName) {
955
911
  var _a;
956
912
  analyzerServiceExecutor_1.AnalyzerServiceExecutor.runWithOptions(this.rootPath, workspace, serverSettings, typeStubTargetImportName);
957
- workspace.searchPathsToWatch = (_a = workspace.serviceInstance.librarySearchPathsToWatch) !== null && _a !== void 0 ? _a : [];
913
+ workspace.searchPathsToWatch = (_a = workspace.service.librarySearchPathsToWatch) !== null && _a !== void 0 ? _a : [];
958
914
  }
959
- convertLogLevel(logLevelValue) {
960
- if (!logLevelValue) {
961
- return console_1.LogLevel.Info;
962
- }
963
- switch (logLevelValue.toLowerCase()) {
964
- case 'error':
965
- return console_1.LogLevel.Error;
966
- case 'warning':
967
- return console_1.LogLevel.Warn;
968
- case 'information':
969
- return console_1.LogLevel.Info;
970
- case 'trace':
971
- return console_1.LogLevel.Log;
972
- default:
973
- return console_1.LogLevel.Info;
915
+ onWorkspaceCreated(workspace) {
916
+ // Update settings on this workspace (but only if initialize has happened)
917
+ if (this._initialized) {
918
+ this.updateSettingsForWorkspace(workspace, workspace.isInitialized).ignoreErrors();
974
919
  }
920
+ // Otherwise the intiailize completion should cause settings to be updated on all workspaces.
921
+ }
922
+ createAnalyzerServiceForWorkspace(name, _rootPath, _uri, kinds, services) {
923
+ // 5 seconds default
924
+ const defaultBackOffTime = 5 * 1000;
925
+ // 10 seconds back off for multi workspace.
926
+ const multiWorkspaceBackOffTime = 10 * 1000;
927
+ const libraryReanalysisTimeProvider = kinds.length === 1 && kinds[0] === workspaceFactory_1.WellKnownWorkspaceKinds.Regular
928
+ ? () => this._workspaceFactory.hasMultipleWorkspaces(kinds[0])
929
+ ? multiWorkspaceBackOffTime
930
+ : defaultBackOffTime
931
+ : () => defaultBackOffTime;
932
+ return this.createAnalyzerService(name, services, libraryReanalysisTimeProvider);
975
933
  }
976
934
  _sendDiagnostics(params) {
977
935
  for (const param of params) {
@@ -1088,8 +1046,8 @@ class LanguageServerBase {
1088
1046
  // Tell all of the services that the user is actively
1089
1047
  // interacting with one or more editors, so they should
1090
1048
  // back off from performing any work.
1091
- this._workspaceMap.forEach((workspace) => {
1092
- workspace.serviceInstance.recordUserInteractionTime();
1049
+ this._workspaceFactory.items().forEach((workspace) => {
1050
+ workspace.service.recordUserInteractionTime();
1093
1051
  });
1094
1052
  }
1095
1053
  getDocumentationUrlForDiagnosticRule(rule) {