@zzzen/pyright-internal 1.2.0-dev.20230305 → 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 (157) 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/binder.js +23 -3
  5. package/dist/analyzer/binder.js.map +1 -1
  6. package/dist/analyzer/cacheManager.d.ts +4 -0
  7. package/dist/analyzer/cacheManager.js +13 -0
  8. package/dist/analyzer/cacheManager.js.map +1 -1
  9. package/dist/analyzer/checker.d.ts +2 -1
  10. package/dist/analyzer/checker.js +73 -29
  11. package/dist/analyzer/checker.js.map +1 -1
  12. package/dist/analyzer/codeFlowEngine.js +17 -11
  13. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  14. package/dist/analyzer/commentUtils.js +11 -1
  15. package/dist/analyzer/commentUtils.js.map +1 -1
  16. package/dist/analyzer/constructorTransform.d.ts +1 -0
  17. package/dist/analyzer/constructorTransform.js +19 -2
  18. package/dist/analyzer/constructorTransform.js.map +1 -1
  19. package/dist/analyzer/packageTypeVerifier.js +40 -40
  20. package/dist/analyzer/packageTypeVerifier.js.map +1 -1
  21. package/dist/analyzer/patternMatching.js +13 -11
  22. package/dist/analyzer/patternMatching.js.map +1 -1
  23. package/dist/analyzer/program.d.ts +1 -1
  24. package/dist/analyzer/program.js +21 -19
  25. package/dist/analyzer/program.js.map +1 -1
  26. package/dist/analyzer/properties.js +0 -1
  27. package/dist/analyzer/properties.js.map +1 -1
  28. package/dist/analyzer/service.d.ts +2 -1
  29. package/dist/analyzer/service.js +9 -3
  30. package/dist/analyzer/service.js.map +1 -1
  31. package/dist/analyzer/sourceFile.d.ts +2 -2
  32. package/dist/analyzer/sourceFile.js +14 -3
  33. package/dist/analyzer/sourceFile.js.map +1 -1
  34. package/dist/analyzer/sourceFileInfoUtils.d.ts +1 -0
  35. package/dist/analyzer/sourceFileInfoUtils.js +17 -1
  36. package/dist/analyzer/sourceFileInfoUtils.js.map +1 -1
  37. package/dist/analyzer/typeEvaluator.js +195 -87
  38. package/dist/analyzer/typeEvaluator.js.map +1 -1
  39. package/dist/analyzer/typeEvaluatorTypes.d.ts +1 -2
  40. package/dist/analyzer/typeEvaluatorTypes.js +0 -3
  41. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  42. package/dist/analyzer/typePrinter.js +63 -55
  43. package/dist/analyzer/typePrinter.js.map +1 -1
  44. package/dist/analyzer/typeStubWriter.js +2 -0
  45. package/dist/analyzer/typeStubWriter.js.map +1 -1
  46. package/dist/analyzer/typeUtils.d.ts +1 -0
  47. package/dist/analyzer/typeUtils.js +29 -3
  48. package/dist/analyzer/typeUtils.js.map +1 -1
  49. package/dist/analyzer/typedDicts.d.ts +2 -1
  50. package/dist/analyzer/typedDicts.js +84 -40
  51. package/dist/analyzer/typedDicts.js.map +1 -1
  52. package/dist/analyzer/types.d.ts +5 -1
  53. package/dist/analyzer/types.js +11 -1
  54. package/dist/analyzer/types.js.map +1 -1
  55. package/dist/commands/dumpFileDebugInfoCommand.js +82 -4
  56. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  57. package/dist/commands/quickActionCommand.js +2 -2
  58. package/dist/commands/quickActionCommand.js.map +1 -1
  59. package/dist/common/configOptions.d.ts +1 -0
  60. package/dist/common/configOptions.js +4 -0
  61. package/dist/common/configOptions.js.map +1 -1
  62. package/dist/common/console.d.ts +1 -0
  63. package/dist/common/console.js +19 -1
  64. package/dist/common/console.js.map +1 -1
  65. package/dist/common/diagnosticRules.d.ts +2 -1
  66. package/dist/common/diagnosticRules.js +1 -0
  67. package/dist/common/diagnosticRules.js.map +1 -1
  68. package/dist/common/extensibility.d.ts +2 -2
  69. package/dist/common/extensibility.js +25 -1
  70. package/dist/common/extensibility.js.map +1 -1
  71. package/dist/common/extensions.js +3 -1
  72. package/dist/common/extensions.js.map +1 -1
  73. package/dist/languageServerBase.d.ts +21 -46
  74. package/dist/languageServerBase.js +112 -152
  75. package/dist/languageServerBase.js.map +1 -1
  76. package/dist/languageService/analyzerServiceExecutor.d.ts +4 -3
  77. package/dist/languageService/analyzerServiceExecutor.js +9 -7
  78. package/dist/languageService/analyzerServiceExecutor.js.map +1 -1
  79. package/dist/languageService/codeActionProvider.d.ts +2 -2
  80. package/dist/languageService/codeActionProvider.js +4 -4
  81. package/dist/languageService/codeActionProvider.js.map +1 -1
  82. package/dist/languageService/completionProvider.d.ts +4 -2
  83. package/dist/languageService/completionProvider.js +209 -156
  84. package/dist/languageService/completionProvider.js.map +1 -1
  85. package/dist/languageService/definitionProvider.js +1 -1
  86. package/dist/languageService/definitionProvider.js.map +1 -1
  87. package/dist/languageService/documentSymbolCollector.d.ts +2 -1
  88. package/dist/languageService/documentSymbolCollector.js +23 -2
  89. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  90. package/dist/languageService/hoverProvider.d.ts +2 -1
  91. package/dist/languageService/hoverProvider.js +21 -5
  92. package/dist/languageService/hoverProvider.js.map +1 -1
  93. package/dist/languageService/referencesProvider.d.ts +3 -2
  94. package/dist/languageService/referencesProvider.js +4 -4
  95. package/dist/languageService/referencesProvider.js.map +1 -1
  96. package/dist/languageService/renameModuleProvider.d.ts +1 -1
  97. package/dist/languageService/renameModuleProvider.js +8 -1
  98. package/dist/languageService/renameModuleProvider.js.map +1 -1
  99. package/dist/languageService/tooltipUtils.js +2 -1
  100. package/dist/languageService/tooltipUtils.js.map +1 -1
  101. package/dist/localization/localize.d.ts +17 -6
  102. package/dist/localization/localize.js +6 -4
  103. package/dist/localization/localize.js.map +1 -1
  104. package/dist/localization/package.nls.en-us.json +8 -6
  105. package/dist/parser/parser.js +24 -7
  106. package/dist/parser/parser.js.map +1 -1
  107. package/dist/parser/tokenizer.js +1 -1
  108. package/dist/server.d.ts +3 -2
  109. package/dist/server.js +1 -4
  110. package/dist/server.js.map +1 -1
  111. package/dist/tests/cacheManager.test.d.ts +1 -0
  112. package/dist/tests/cacheManager.test.js +69 -0
  113. package/dist/tests/cacheManager.test.js.map +1 -0
  114. package/dist/tests/checker.test.js +2 -2
  115. package/dist/tests/completions.test.js +445 -0
  116. package/dist/tests/completions.test.js.map +1 -1
  117. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js +13 -3
  118. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js.map +1 -1
  119. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js +7 -2
  120. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js.map +1 -1
  121. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.d.ts +7 -0
  122. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.js +45 -0
  123. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.js.map +1 -0
  124. package/dist/tests/harness/fourslash/testLanguageService.d.ts +7 -6
  125. package/dist/tests/harness/fourslash/testLanguageService.js +14 -13
  126. package/dist/tests/harness/fourslash/testLanguageService.js.map +1 -1
  127. package/dist/tests/harness/fourslash/testState.d.ts +5 -4
  128. package/dist/tests/harness/fourslash/testState.js +14 -13
  129. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  130. package/dist/tests/hoverProvider.test.js +1 -1
  131. package/dist/tests/hoverProvider.test.js.map +1 -1
  132. package/dist/tests/moveSymbol.misc.test.js +27 -0
  133. package/dist/tests/moveSymbol.misc.test.js.map +1 -1
  134. package/dist/tests/service.test.js +4 -4
  135. package/dist/tests/service.test.js.map +1 -1
  136. package/dist/tests/signatureHelp.test.js +2 -2
  137. package/dist/tests/signatureHelp.test.js.map +1 -1
  138. package/dist/tests/sourceFile.test.js +3 -3
  139. package/dist/tests/sourceFile.test.js.map +1 -1
  140. package/dist/tests/typeEvaluator1.test.js +4 -0
  141. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  142. package/dist/tests/typeEvaluator2.test.js +6 -2
  143. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  144. package/dist/tests/typeEvaluator3.test.js +1 -1
  145. package/dist/tests/typeEvaluator4.test.js +5 -1
  146. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  147. package/dist/tests/typeEvaluator5.test.js +12 -0
  148. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  149. package/dist/tests/workspaceEditUtils.test.js +2 -2
  150. package/dist/tests/workspaceEditUtils.test.js.map +1 -1
  151. package/dist/workspaceFactory.d.ts +72 -0
  152. package/dist/workspaceFactory.js +421 -0
  153. package/dist/workspaceFactory.js.map +1 -0
  154. package/package.json +4 -4
  155. package/dist/workspaceMap.d.ts +0 -14
  156. package/dist/workspaceMap.js +0 -172
  157. 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,
@@ -378,7 +341,9 @@ class LanguageServerBase {
378
341
  documentHighlightProvider: { workDoneProgress: true },
379
342
  renameProvider: { prepareProvider: true, workDoneProgress: true },
380
343
  completionProvider: {
381
- triggerCharacters: this.client.hasVisualStudioExtensionsCapability ? ['.', '[', '@'] : ['.', '['],
344
+ triggerCharacters: this.client.hasVisualStudioExtensionsCapability
345
+ ? ['.', '[', '@', '"', "'"]
346
+ : ['.', '[', '"', "'"],
382
347
  resolveProvider: true,
383
348
  workDoneProgress: true,
384
349
  completionItem: {
@@ -409,22 +374,16 @@ class LanguageServerBase {
409
374
  return result;
410
375
  }
411
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;
412
380
  if (!this.client.hasWorkspaceFoldersCapability) {
413
381
  // If folder capability is not supported, initialize ones given by onInitialize.
414
382
  this.updateSettingsForAllWorkspaces();
415
383
  return;
416
384
  }
417
385
  this._connection.workspace.onDidChangeWorkspaceFolders((event) => {
418
- event.removed.forEach((workspaceInfo) => {
419
- const rootPath = this._uriParser.decodeTextDocumentUri(workspaceInfo.uri);
420
- this._workspaceMap.delete(rootPath);
421
- });
422
- event.added.forEach((workspaceInfo) => {
423
- const rootPath = this._uriParser.decodeTextDocumentUri(workspaceInfo.uri);
424
- const newWorkspace = this.createWorkspaceServiceInstance(workspaceInfo, rootPath, rootPath);
425
- this._workspaceMap.set(rootPath, newWorkspace);
426
- this.updateSettingsForWorkspace(newWorkspace, newWorkspace.isInitialized).ignoreErrors();
427
- });
386
+ this._workspaceFactory.handleWorkspaceFoldersChanged(event);
428
387
  this._setupFileWatcher();
429
388
  });
430
389
  this._setupFileWatcher();
@@ -444,7 +403,7 @@ class LanguageServerBase {
444
403
  // Dedup search paths from all workspaces.
445
404
  // Get rid of any search path under workspace root since it is already watched by
446
405
  // "**" above.
447
- const foldersToWatch = (0, pathUtils_1.deduplicateFolders)(this._workspaceMap
406
+ const foldersToWatch = (0, pathUtils_1.deduplicateFolders)(this._workspaceFactory
448
407
  .getNonDefaultWorkspaces()
449
408
  .map((w) => w.searchPathsToWatch.filter((p) => !p.startsWith(w.rootPath))));
450
409
  foldersToWatch.forEach((p) => {
@@ -470,13 +429,13 @@ class LanguageServerBase {
470
429
  this.updateSettingsForAllWorkspaces();
471
430
  }
472
431
  async onDefinition(params, token) {
473
- 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));
474
433
  }
475
434
  async onDeclaration(params, token) {
476
- 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));
477
436
  }
478
437
  async onTypeDefinition(params, token) {
479
- 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));
480
439
  }
481
440
  async getDefinitions(params, token, filter, getDefinitionsFunc) {
482
441
  this.recordUserInteractionTime();
@@ -490,8 +449,8 @@ class LanguageServerBase {
490
449
  return undefined;
491
450
  }
492
451
  return locations
493
- .filter((loc) => this.canNavigateToFile(loc.path, workspace.serviceInstance.fs))
494
- .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));
495
454
  }
496
455
  async onReferences(params, token, workDoneReporter, resultReporter) {
497
456
  if (this._pendingFindAllRefsCancellationSource) {
@@ -512,14 +471,14 @@ class LanguageServerBase {
512
471
  }
513
472
  const convert = (locs) => {
514
473
  return locs
515
- .filter((loc) => this.canNavigateToFile(loc.path, workspace.serviceInstance.fs))
516
- .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));
517
476
  };
518
477
  const locations = [];
519
478
  const reporter = resultReporter
520
479
  ? (locs) => resultReporter.report(convert(locs))
521
480
  : (locs) => (0, collectionUtils_1.appendArray)(locations, convert(locs));
522
- workspace.serviceInstance.reportReferencesForPosition(filePath, position, params.context.includeDeclaration, reporter, source.token);
481
+ workspace.service.reportReferencesForPosition(filePath, position, params.context.includeDeclaration, reporter, source.token);
523
482
  return locations;
524
483
  }
525
484
  finally {
@@ -535,7 +494,7 @@ class LanguageServerBase {
535
494
  return undefined;
536
495
  }
537
496
  const symbolList = [];
538
- workspace.serviceInstance.addSymbolsForDocument(filePath, symbolList, token);
497
+ workspace.service.addSymbolsForDocument(filePath, symbolList, token);
539
498
  if (this.client.hasHierarchicalDocumentSymbolCapability) {
540
499
  return symbolList;
541
500
  }
@@ -546,10 +505,10 @@ class LanguageServerBase {
546
505
  const reporter = resultReporter
547
506
  ? (symbols) => resultReporter.report(symbols)
548
507
  : (symbols) => (0, collectionUtils_1.appendArray)(symbolList, symbols);
549
- for (const workspace of this._workspaceMap.values()) {
508
+ for (const workspace of this._workspaceFactory.items()) {
550
509
  await workspace.isInitialized.promise;
551
510
  if (!workspace.disableLanguageServices && !workspace.disableWorkspaceSymbol) {
552
- workspace.serviceInstance.reportSymbolsForWorkspace(params.query, reporter, token);
511
+ workspace.service.reportSymbolsForWorkspace(params.query, reporter, token);
553
512
  }
554
513
  }
555
514
  return symbolList;
@@ -557,13 +516,13 @@ class LanguageServerBase {
557
516
  async onHover(params, token) {
558
517
  const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
559
518
  const workspace = await this.getWorkspaceForFile(filePath);
560
- const hoverResults = workspace.serviceInstance.getHoverForPosition(filePath, position, this.client.hoverContentFormat, token);
561
- 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);
562
521
  }
563
522
  async onDocumentHighlight(params, token) {
564
523
  const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
565
524
  const workspace = await this.getWorkspaceForFile(filePath);
566
- return workspace.serviceInstance.getDocumentHighlight(filePath, position, token);
525
+ return workspace.service.getDocumentHighlight(filePath, position, token);
567
526
  }
568
527
  async onSignatureHelp(params, token) {
569
528
  var _a, _b;
@@ -572,7 +531,7 @@ class LanguageServerBase {
572
531
  if (workspace.disableLanguageServices) {
573
532
  return;
574
533
  }
575
- const signatureHelpResults = workspace.serviceInstance.getSignatureHelpForPosition(filePath, position, this.client.signatureDocFormat, token);
534
+ const signatureHelpResults = workspace.service.getSignatureHelpForPosition(filePath, position, this.client.signatureDocFormat, token);
576
535
  if (!signatureHelpResults) {
577
536
  return undefined;
578
537
  }
@@ -667,6 +626,19 @@ class LanguageServerBase {
667
626
  if (completions) {
668
627
  completions.completionList.isIncomplete = completionIncomplete;
669
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
+ }
670
642
  return completions === null || completions === void 0 ? void 0 : completions.completionList;
671
643
  }
672
644
  // Cancellation bugs in vscode and LSP:
@@ -690,7 +662,7 @@ class LanguageServerBase {
690
662
  if (workspace.disableLanguageServices) {
691
663
  return null;
692
664
  }
693
- 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);
694
666
  return (_a = result === null || result === void 0 ? void 0 : result.range) !== null && _a !== void 0 ? _a : null;
695
667
  }
696
668
  async onRenameRequest(params, token) {
@@ -699,11 +671,11 @@ class LanguageServerBase {
699
671
  if (workspace.disableLanguageServices) {
700
672
  return;
701
673
  }
702
- 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);
703
675
  if (!editActions) {
704
676
  return undefined;
705
677
  }
706
- return (0, workspaceEditUtils_1.convertToWorkspaceEdit)(workspace.serviceInstance.fs, editActions);
678
+ return (0, workspaceEditUtils_1.convertToWorkspaceEdit)(workspace.service.fs, editActions);
707
679
  }
708
680
  async onPrepare(params, token) {
709
681
  const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
@@ -711,15 +683,15 @@ class LanguageServerBase {
711
683
  if (workspace.disableLanguageServices) {
712
684
  return null;
713
685
  }
714
- const callItem = workspace.serviceInstance.getCallForPosition(filePath, position, token) || null;
686
+ const callItem = workspace.service.getCallForPosition(filePath, position, token) || null;
715
687
  if (!callItem) {
716
688
  return null;
717
689
  }
718
- if (!this.canNavigateToFile(callItem.uri, workspace.serviceInstance.fs)) {
690
+ if (!this.canNavigateToFile(callItem.uri, workspace.service.fs)) {
719
691
  return null;
720
692
  }
721
693
  // Convert the file path in the item to proper URI.
722
- callItem.uri = (0, pathUtils_1.convertPathToUri)(workspace.serviceInstance.fs, callItem.uri);
694
+ callItem.uri = (0, pathUtils_1.convertPathToUri)(workspace.service.fs, callItem.uri);
723
695
  return [callItem];
724
696
  }
725
697
  async onIncomingCalls(params, token) {
@@ -728,14 +700,14 @@ class LanguageServerBase {
728
700
  if (workspace.disableLanguageServices) {
729
701
  return null;
730
702
  }
731
- let callItems = workspace.serviceInstance.getIncomingCallsForPosition(filePath, position, token) || null;
703
+ let callItems = workspace.service.getIncomingCallsForPosition(filePath, position, token) || null;
732
704
  if (!callItems || callItems.length === 0) {
733
705
  return null;
734
706
  }
735
- 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));
736
708
  // Convert the file paths in the items to proper URIs.
737
709
  callItems.forEach((item) => {
738
- 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);
739
711
  });
740
712
  return callItems;
741
713
  }
@@ -745,14 +717,14 @@ class LanguageServerBase {
745
717
  if (workspace.disableLanguageServices) {
746
718
  return null;
747
719
  }
748
- let callItems = workspace.serviceInstance.getOutgoingCallsForPosition(filePath, position, token) || null;
720
+ let callItems = workspace.service.getOutgoingCallsForPosition(filePath, position, token) || null;
749
721
  if (!callItems || callItems.length === 0) {
750
722
  return null;
751
723
  }
752
- 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));
753
725
  // Convert the file paths in the items to proper URIs.
754
726
  callItems.forEach((item) => {
755
- 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);
756
728
  });
757
729
  return callItems;
758
730
  }
@@ -762,8 +734,11 @@ class LanguageServerBase {
762
734
  // We do not support opening 1 file with 2 different uri.
763
735
  return;
764
736
  }
765
- const workspace = await this.getWorkspaceForFile(filePath);
766
- 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
+ });
767
742
  }
768
743
  async onDidChangeTextDocument(params, ipythonMode = sourceFile_1.IPythonMode.None) {
769
744
  this.recordUserInteractionTime();
@@ -772,8 +747,11 @@ class LanguageServerBase {
772
747
  // We do not support opening 1 file with 2 different uri.
773
748
  return;
774
749
  }
775
- const workspace = await this.getWorkspaceForFile(filePath);
776
- 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
+ });
777
755
  }
778
756
  async onDidCloseTextDocument(params) {
779
757
  const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri);
@@ -781,8 +759,11 @@ class LanguageServerBase {
781
759
  // We do not support opening 1 file with 2 different uri.
782
760
  return;
783
761
  }
784
- const workspace = await this.getWorkspaceForFile(filePath);
785
- 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
+ });
786
767
  }
787
768
  onDidChangeWatchedFiles(params) {
788
769
  params.changes.forEach((change) => {
@@ -832,19 +813,19 @@ class LanguageServerBase {
832
813
  }
833
814
  onShutdown(token) {
834
815
  // Shutdown remaining workspaces.
835
- this._workspaceMap.forEach((_, key) => this._workspaceMap.delete(key));
816
+ this._workspaceFactory.clear();
836
817
  return Promise.resolve();
837
818
  }
838
819
  resolveWorkspaceCompletionItem(workspace, filePath, item, token) {
839
- workspace.serviceInstance.resolveCompletionItem(filePath, item, this.getCompletionOptions(workspace),
820
+ workspace.service.resolveCompletionItem(filePath, item, this.getCompletionOptions(workspace),
840
821
  /* nameMap */ undefined, token);
841
822
  }
842
823
  getWorkspaceCompletionsForPosition(workspace, filePath, position, options, token) {
843
- return workspace.serviceInstance.getCompletionsForPosition(filePath, position, workspace.path, options, undefined, token);
824
+ return workspace.service.getCompletionsForPosition(filePath, position, workspace.rootPath, options, undefined, token);
844
825
  }
845
826
  updateSettingsForAllWorkspaces() {
846
827
  const tasks = [];
847
- this._workspaceMap.forEach((workspace) => {
828
+ this._workspaceFactory.items().forEach((workspace) => {
848
829
  // Updating settings can change workspace's file ownership. Make workspace uninitialized so that
849
830
  // features can wait until workspace gets new settings.
850
831
  // the file's ownership can also changed by `pyrightconfig.json` changes, but those are synchronous
@@ -869,32 +850,6 @@ class LanguageServerBase {
869
850
  triggerCharacter: (_a = params === null || params === void 0 ? void 0 : params.context) === null || _a === void 0 ? void 0 : _a.triggerCharacter,
870
851
  };
871
852
  }
872
- createWorkspaceServiceInstance(workspaceFolder, rootPath, path, kinds = [WellKnownWorkspaceKinds.Regular], services) {
873
- var _a, _b, _c;
874
- // 5 seconds default
875
- const defaultBackOffTime = 5 * 1000;
876
- // 10 seconds back off for multi workspace.
877
- const multiWorkspaceBackOffTime = 10 * 1000;
878
- const libraryReanalysisTimeProvider = kinds.length === 1 && kinds[0] === WellKnownWorkspaceKinds.Regular
879
- ? () => this._workspaceMap.hasMultipleWorkspaces(kinds[0])
880
- ? multiWorkspaceBackOffTime
881
- : defaultBackOffTime
882
- : () => defaultBackOffTime;
883
- const rootUri = (_a = workspaceFolder === null || workspaceFolder === void 0 ? void 0 : workspaceFolder.uri) !== null && _a !== void 0 ? _a : '';
884
- return {
885
- workspaceName: (_b = workspaceFolder === null || workspaceFolder === void 0 ? void 0 : workspaceFolder.name) !== null && _b !== void 0 ? _b : '',
886
- rootPath,
887
- path,
888
- uri: rootUri,
889
- kinds,
890
- serviceInstance: this.createAnalyzerService((_c = workspaceFolder === null || workspaceFolder === void 0 ? void 0 : workspaceFolder.name) !== null && _c !== void 0 ? _c : path, services, libraryReanalysisTimeProvider),
891
- disableLanguageServices: false,
892
- disableOrganizeImports: false,
893
- disableWorkspaceSymbol: false,
894
- isInitialized: createInitStatus(),
895
- searchPathsToWatch: [],
896
- };
897
- }
898
853
  convertDiagnostics(fs, fileDiagnostics) {
899
854
  return [
900
855
  {
@@ -941,6 +896,9 @@ class LanguageServerBase {
941
896
  serverSettings = serverSettings !== null && serverSettings !== void 0 ? serverSettings : (await this.getSettings(workspace));
942
897
  // Set logging level first.
943
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.
944
902
  this.updateOptionsAndRestartService(workspace, serverSettings);
945
903
  workspace.disableLanguageServices = !!serverSettings.disableLanguageServices;
946
904
  workspace.disableOrganizeImports = !!serverSettings.disableOrganizeImports;
@@ -952,24 +910,26 @@ class LanguageServerBase {
952
910
  updateOptionsAndRestartService(workspace, serverSettings, typeStubTargetImportName) {
953
911
  var _a;
954
912
  analyzerServiceExecutor_1.AnalyzerServiceExecutor.runWithOptions(this.rootPath, workspace, serverSettings, typeStubTargetImportName);
955
- workspace.searchPathsToWatch = (_a = workspace.serviceInstance.librarySearchPathsToWatch) !== null && _a !== void 0 ? _a : [];
913
+ workspace.searchPathsToWatch = (_a = workspace.service.librarySearchPathsToWatch) !== null && _a !== void 0 ? _a : [];
956
914
  }
957
- convertLogLevel(logLevelValue) {
958
- if (!logLevelValue) {
959
- return console_1.LogLevel.Info;
960
- }
961
- switch (logLevelValue.toLowerCase()) {
962
- case 'error':
963
- return console_1.LogLevel.Error;
964
- case 'warning':
965
- return console_1.LogLevel.Warn;
966
- case 'information':
967
- return console_1.LogLevel.Info;
968
- case 'trace':
969
- return console_1.LogLevel.Log;
970
- default:
971
- 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();
972
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);
973
933
  }
974
934
  _sendDiagnostics(params) {
975
935
  for (const param of params) {
@@ -1086,8 +1046,8 @@ class LanguageServerBase {
1086
1046
  // Tell all of the services that the user is actively
1087
1047
  // interacting with one or more editors, so they should
1088
1048
  // back off from performing any work.
1089
- this._workspaceMap.forEach((workspace) => {
1090
- workspace.serviceInstance.recordUserInteractionTime();
1049
+ this._workspaceFactory.items().forEach((workspace) => {
1050
+ workspace.service.recordUserInteractionTime();
1091
1051
  });
1092
1052
  }
1093
1053
  getDocumentationUrlForDiagnosticRule(rule) {